練YOLOv8檢測(cè)模型)
簡(jiǎn)介面向光伏運(yùn)維與計(jì)算機(jī)視覺目標(biāo)檢測(cè)場(chǎng)景的太陽能光伏板積灰檢測(cè)數(shù)據(jù)集包含1463張真實(shí)光伏板表面圖像統(tǒng)一標(biāo)注為Dirt單一類別矩形框總數(shù)6822個(gè)可用于訓(xùn)練積灰識(shí)別、灰塵覆蓋程度評(píng)估等模型。數(shù)據(jù)集同時(shí)提供Pascal VOC與YOLO兩種格式xml標(biāo)注文件適配VOC系列工具txt標(biāo)簽文件可直接接入YOLO訓(xùn)練流程便于在主流檢測(cè)框架中快速加載與遷移學(xué)習(xí)。壓縮包共2000個(gè)文件主要文件類型為1463個(gè)xml標(biāo)注文件和537個(gè)txt標(biāo)簽/說明文件整體大小約75.98MB標(biāo)注工具為labelImg采用矩形框規(guī)則標(biāo)注信息準(zhǔn)確合理需要提醒的是其中部分圖片重復(fù)度較高且不包含訓(xùn)練好的模型權(quán)重。已有536人學(xué)習(xí)下載適合目標(biāo)檢測(cè)初學(xué)者、光伏組件清潔策略研究及工程驗(yàn)證用戶使用可直接用于模型訓(xùn)練、精度對(duì)比或作為自有數(shù)據(jù)集的補(bǔ)充樣本。1. 1463張積灰樣本夠不夠用光伏板檢測(cè)的第一個(gè)數(shù)據(jù)門檻手里只有1463張光伏板積灰樣本單類別VOC和YOLO兩套格式給出這個(gè)體量能訓(xùn)出能用的模型嗎我的答案是能但前提是你把這份數(shù)據(jù)當(dāng)起點(diǎn)而不是終點(diǎn)。光伏板積灰檢測(cè)和行人、車輛檢測(cè)不一樣灰塵是弱紋理、低對(duì)比、光照敏感的目標(biāo)1463張單類別樣本恰好夠把訓(xùn)練流程完整跑通也夠把最容易翻車的數(shù)據(jù)劃分、標(biāo)簽噪聲、閾值選擇這幾個(gè)坑暴露出來。下面按我做光伏巡檢項(xiàng)目的順序來講覆蓋格式怎么校驗(yàn)、YOLOv8訓(xùn)練參數(shù)怎么設(shè)、驗(yàn)證指標(biāo)怎么讀以及這套數(shù)據(jù)集真正適合誰去做初版模型。2. 先看清手里的數(shù)據(jù)VOC與YOLO格式的差異和1463張樣本的組織方式2.1 積灰檢測(cè)的“1個(gè)類別”框的是什么目標(biāo)定義是后面一切的前提拿到zip解壓后第一件事不是急著跑訓(xùn)練而是打開幾十張圖片和標(biāo)簽看一遍?;覊m目標(biāo)沒有銳利邊緣標(biāo)成矩形框時(shí)天然帶主觀性一個(gè)人把重度積灰區(qū)圈起來另一個(gè)人把輕度灰也帶進(jìn)框兩個(gè)標(biāo)注者畫同一張圖的IoU可能只有0.5。這個(gè)數(shù)據(jù)集只有1個(gè)類別意味著模型學(xué)的是“這一塊區(qū)域臟不臟”的二分類類別名在配置文件里可以叫dust、灰污或者dirt但語義上必須是“需要清理的積灰區(qū)域”而不是“整個(gè)光伏板”。我在做第一個(gè)光伏項(xiàng)目時(shí)吃過這個(gè)定義虧。當(dāng)時(shí)數(shù)據(jù)里的框有大有小小的只有幾十個(gè)像素大的框占整塊板面積的一半訓(xùn)練結(jié)果mAP看著不錯(cuò)實(shí)際部署時(shí)對(duì)遠(yuǎn)處小面積的初始積灰完全無感。后來把訓(xùn)練集的標(biāo)注框?qū)捀叻植籍嫵鰜聿琶靼卓虻某叨葒?yán)重分裂模型在“小框”和“大框”之間只能選一個(gè)偏向。拿到這批1463張數(shù)據(jù)也一樣先用一個(gè)統(tǒng)計(jì)腳本把框的寬高比和相對(duì)面積分布打出來再?zèng)Q定imgsz用640還是960這份錢不能省。還有一個(gè)容易被忽略的點(diǎn)同一張圖片里可能出現(xiàn)多個(gè)積灰框也可能一張圖一個(gè)框都沒有。沒有框的圖片如果進(jìn)了訓(xùn)練集YOLO會(huì)把它們當(dāng)作負(fù)樣本處理這對(duì)抑制誤檢有好處但訓(xùn)練配置里要確認(rèn)“允許空標(biāo)簽”是開著的否則數(shù)據(jù)加載階段就會(huì)報(bào)錯(cuò)中斷。單類別數(shù)據(jù)集看起來簡(jiǎn)單實(shí)際上因?yàn)橹挥幸活惐尘昂颓熬暗膮^(qū)分全靠框內(nèi)的紋理差異一旦標(biāo)注標(biāo)準(zhǔn)不統(tǒng)一噪聲會(huì)被模型當(dāng)成正常特征學(xué)進(jìn)去這是后續(xù)所有指標(biāo)虛高的根源。2.2 VOC的XML與YOLO的TXT兩種格式互轉(zhuǎn)與坐標(biāo)校驗(yàn)?zāi)_本VOC格式里每張圖片對(duì)應(yīng)一個(gè)XML框坐標(biāo)是xmin、ymin、xmax、ymax用的是絕對(duì)像素值YOLO格式里每張圖片對(duì)應(yīng)一個(gè)TXT坐標(biāo)是歸一化后的cx、cy、w、h類別用從0開始的整數(shù)索引。這兩種格式的差異可以歸納成一張表項(xiàng)目VOCYOLO文件后綴.xml.txt坐標(biāo)含義左上角和右下角絕對(duì)像素中心點(diǎn)x、y和寬高均歸一化到0~1類別表示字符串名稱整數(shù)索引從0開始形狀約束無默認(rèn)順序要求每行一個(gè)目標(biāo)class cx cy w h這個(gè)數(shù)據(jù)集把兩種格式都給了看起來省了轉(zhuǎn)換這一步但格式給全不代表內(nèi)容干凈。常見做法是寫一個(gè)校驗(yàn)?zāi)_本把坐標(biāo)越界、負(fù)寬高、類別索引越界這三種壞數(shù)據(jù)全部篩出來。下面是針對(duì)VOC側(cè)的基礎(chǔ)校驗(yàn)import os import xml.etree.ElementTree as ET voc_dir labels_voc bad_files [] for xml_name in os.listdir(voc_dir): if not xml_name.endswith(.xml): continue tree ET.parse(os.path.join(voc_dir, xml_name)) root tree.getroot() size root.find(size) w, h int(size.find(width).text), int(size.find(height).text) for obj in root.iter(object): name obj.find(name).text b obj.find(bndbox) xmin float(b.find(xmin).text) ymin float(b.find(ymin).text) xmax float(b.find(xmax).text) ymax float(b.find(ymax).text) if xmin 0 or ymin 0 or xmax w or ymax h: bad_files.append((xml_name, out_of_bounds)) if xmin xmax or ymin ymax: bad_files.append((xml_name, invalid_box)) if len(name) 0: bad_files.append((xml_name, empty_name)) print(fchecked: {len(os.listdir(voc_dir))}, bad: {len(bad_files)}) for item in bad_files[:20]: print(item)邏輯說明腳本遍歷VOC目錄下的每個(gè)XML先從size節(jié)點(diǎn)讀真實(shí)寬高再遍歷所有object節(jié)點(diǎn)逐框做三類判斷坐標(biāo)是否超出圖像邊界、是否出現(xiàn)負(fù)寬度或負(fù)高度、類別字符串是否為空。任何一個(gè)判斷失敗都會(huì)記進(jìn)bad_files列表并打印前20條。參數(shù)說明voc_dir路徑要按解壓后的實(shí)際目錄改這個(gè)腳本只查VOC側(cè)如果同時(shí)要查YOLO側(cè)需要反過來用歸一化坐標(biāo)乘以圖片寬高后再做同樣判斷。實(shí)際項(xiàng)目中我建議先跑VOC側(cè)因?yàn)閄ML是文本格式人類可讀壞標(biāo)簽更容易看出錯(cuò)在哪。VOC和YOLO互轉(zhuǎn)的規(guī)則也很固定VOC轉(zhuǎn)YOLO時(shí)cx(xminxmax)/2/wcy(yminymax)/2/h寬w_box(xmax-xmin)/w高h(yuǎn)_box(ymax-ymin)/hYOLO轉(zhuǎn)VOC則是乘回去再取整。唯一要注意的是四舍五入的邊界轉(zhuǎn)回VOC后xmax可能比原圖寬多1像素這類問題在后續(xù)訓(xùn)練里通常不致命但會(huì)污染框的評(píng)估結(jié)果所以我習(xí)慣在轉(zhuǎn)換后統(tǒng)一做一次“框不能超出圖像”的鉗制。對(duì)于空標(biāo)簽的TXT文件VOC側(cè)的表現(xiàn)是XML里沒有object節(jié)點(diǎn)這個(gè)不要當(dāng)成壞數(shù)據(jù)刪掉它在訓(xùn)練中是合法的負(fù)樣本。2.3 樣本劃分的隱藏門檻同一塊光伏板的重復(fù)幀不能亂分1463張這個(gè)數(shù)量級(jí)最常見的來源是無人機(jī)懸停視頻抽幀或巡檢車連續(xù)拍攝相鄰幀之間的重疊程度很高。如果直接按文件名隨機(jī)劃分訓(xùn)練集和驗(yàn)證集里會(huì)出現(xiàn)大量“同一個(gè)時(shí)刻、同一塊板、只有幾像素位移”的近重復(fù)樣本。這樣訓(xùn)出來的模型驗(yàn)證mAP會(huì)異常高但換到另一批光伏板上效果迅速下跌因?yàn)槟P驮隍?yàn)證集上見過幾乎相同的畫面。我一般會(huì)先用文件名前綴或拍攝時(shí)間戳做樣本聚類。比如文件名是PV01_0012.jpg這樣的結(jié)構(gòu)PV01就是組件ID按組件ID分組然后對(duì)組做隨機(jī)劃分保證同一組件ID的幀只落在訓(xùn)練集或驗(yàn)證集其中一個(gè)里面。如果文件名里沒有ID就按拍攝時(shí)間排序后每隔N幀取一幀也能大大降低相鄰幀泄漏。這一步做完再談?dòng)?xùn)練參數(shù)才有意義否則后面所有的指標(biāo)都是虛的。驗(yàn)證集的比例也要斟酌。1463張樣本我用85比15而不是更常見的90比10因?yàn)榛鶖?shù)小驗(yàn)證集太少時(shí)mAP的隨機(jī)波動(dòng)會(huì)很大可能這一輪0.72下一輪0.65完全看不出模型真實(shí)水平。15%大約是220張足夠讓評(píng)估結(jié)果穩(wěn)定下來。劃分時(shí)還要檢查一件事驗(yàn)證集里每個(gè)組件ID的樣本數(shù)不要差別太大否則驗(yàn)證集被某一個(gè)組件的畫面主導(dǎo)評(píng)估結(jié)果就偏了。3. 用YOLOv8訓(xùn)練自己的數(shù)據(jù)集從解壓到第一個(gè)權(quán)重文件的完整命令3.1 目錄結(jié)構(gòu)和數(shù)據(jù)集配置讓YOLOv8認(rèn)出這批1463張圖YOLOv8對(duì)自定義數(shù)據(jù)集的目錄組織有固定約定。把zip解壓后我一般會(huì)整理成下面這種結(jié)構(gòu)datasets/pv_dust/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── pv_dust.yamlimages和labels是平級(jí)目錄train和val在兩邊保持同名。圖片和對(duì)應(yīng)標(biāo)簽文件名要完全一致唯一區(qū)別是后綴圖片是.jpg或.png標(biāo)簽是.txt。如果zip里給出的是平鋪的images和labels各一個(gè)目錄需要自己寫劃分腳本把樣本按2.3的組件ID分組邏輯以大約85%對(duì)15%的比例分到train和val。文件名對(duì)齊這塊有個(gè)常見坑有的數(shù)據(jù)集圖片叫IMG_001.jpg標(biāo)簽叫IMG_001.txt這個(gè)沒問題但VOC格式下XML文件名和圖片名也可能不一致先統(tǒng)一改名再進(jìn)訓(xùn)練否則YOLO訓(xùn)練時(shí)會(huì)因?yàn)檎也坏綐?biāo)簽而跳過樣本訓(xùn)練集實(shí)際使用數(shù)量比目錄里少一大截。然后寫數(shù)據(jù)集配置文件# pv_dust.yaml path: ./datasets/pv_dust train: images/train val: images/val nc: 1 names: [dust]參數(shù)說明path指示數(shù)據(jù)集根目錄train和val用相對(duì)path的路徑nc是類別數(shù)本數(shù)據(jù)集只有1類names數(shù)組的下標(biāo)就是標(biāo)簽文件里寫在每行第一個(gè)位置的類別索引所以names[0]必須是dust。如果解壓后發(fā)現(xiàn)YOLO標(biāo)簽里的類別id不是0先批量改成0否則訓(xùn)練時(shí)不報(bào)錯(cuò)但推理結(jié)果在可視化時(shí)類別名永遠(yuǎn)對(duì)不上。這里還有個(gè)細(xì)節(jié)path建議寫相對(duì)路徑或完整絕對(duì)路徑不要寫帶空格的路徑訓(xùn)練腳本解析yaml時(shí)可能會(huì)因?yàn)槁窂嚼镉锌崭穸也坏綀D片。提示如果zip里沒有做train/val劃分只給了一堆圖片和兩套標(biāo)簽先按組件ID分組再做隨機(jī)劃分最后再生成yaml。順序反過來的話前面省的時(shí)間會(huì)在指標(biāo)評(píng)估上加倍還回去。3.2 訓(xùn)練命令與關(guān)鍵參數(shù)batch、epoch、imgsz和patience怎么設(shè)數(shù)據(jù)集配置好后訓(xùn)練命令在我這里通常長(zhǎng)這樣yolo detect train \ datadatasets/pv_dust/pv_dust.yaml \ modelyolov8s.pt \ imgsz640 \ batch16 \ epochs100 \ patience20 \ workers4 \ device0 \ projectrun_pv_dust \ nameexp_dust_v1邏輯說明data指定yaml配置model用yolov8s.pt做遷移學(xué)習(xí)imgsz是訓(xùn)練輸入尺寸batch是每批處理張數(shù)epochs是最大訓(xùn)練輪數(shù)patience是早停輪數(shù)device指定GPU編號(hào)。1463張單類別數(shù)據(jù)用yolov8s比n版更穩(wěn)比m版更容易在有限樣本上收斂。訓(xùn)練腳本啟動(dòng)后可以盯住終端輸出的box_loss和cls_loss兩條曲線持續(xù)下降且不劇烈震蕩基本不用管如果loss在中間回彈優(yōu)先檢查是不是學(xué)習(xí)率跑飛或者數(shù)據(jù)增強(qiáng)太強(qiáng)。參數(shù)說明imgsz設(shè)640是起步值我一般先用640跑一版再看2.1里統(tǒng)計(jì)的框相對(duì)面積分布決定要不要調(diào)960batch按顯存來16G顯存用168G顯存降到8epochs設(shè)100但實(shí)際會(huì)在60輪左右被早停攔住因?yàn)?463張小樣本到大后期基本在擬合噪聲workers設(shè)4即可不需要貪高數(shù)據(jù)讀取經(jīng)常不是這里的瓶頸。patience20的含義是驗(yàn)證集mAP連續(xù)20輪沒有刷新就停止訓(xùn)練這個(gè)參數(shù)對(duì)單類別小樣本特別有用能幫你省下大量無效訓(xùn)練時(shí)間。如果要換模型版本把model換成yolov8n.pt或者yolov8m.pt即可其他配置不用動(dòng)對(duì)比實(shí)驗(yàn)時(shí)注意固定data和imgsz否則指標(biāo)沒有可比性。3.3 驗(yàn)證命令與第一次預(yù)測(cè)先看框再談精度訓(xùn)練結(jié)束后必須做兩件事離線評(píng)估和在線推理預(yù)覽。離線評(píng)估看的是統(tǒng)計(jì)指標(biāo)在線推理看的是直覺判斷兩個(gè)互相補(bǔ)充。命令如下yolo detect val \ modelrun_pv_dust/exp_dust_v1/weights/best.pt \ datadatasets/pv_dust/pv_dust.yaml \ imgsz640 \ conf0.25 yolo predict \ modelrun_pv_dust/exp_dust_v1/weights/best.pt \ sourcetest_images/ \ imgsz640 \ conf0.25 \ saveTrue邏輯說明val命令在驗(yàn)證集上評(píng)估best.pt輸出Precision、Recall、mAP50和mAP50-95predict命令對(duì)source指定的一張圖或一個(gè)目錄做推理saveTrue會(huì)把帶框的結(jié)果圖存到runs/detect/predict目錄。調(diào)試階段不要只盯著終端里的mAP數(shù)字一定要打開結(jié)果圖看。如果框都?jí)涸诜e灰最重的區(qū)域并且沒有橫跨光伏板邊界說明模型學(xué)到的是積灰區(qū)域本身如果框大面積亂飄先回去查標(biāo)簽而不是換模型結(jié)構(gòu)。參數(shù)說明這里的conf0.25是評(píng)估和推理的置信度閾值驗(yàn)證時(shí)用0.25是慣例預(yù)測(cè)時(shí)應(yīng)該按業(yè)務(wù)場(chǎng)景調(diào)整。上面兩個(gè)命令中val的conf改動(dòng)會(huì)直接改變P和R的輸出同一個(gè)模型在conf0.1和conf0.4下的指標(biāo)可以差出20個(gè)百分點(diǎn)所以對(duì)比實(shí)驗(yàn)時(shí)conf必須固定不能今天0.25明天0.3。predict階段我習(xí)慣單獨(dú)跑一個(gè)不看conf的版本做排查比如加一行超參數(shù)改成conf0.05看看低閾值下模型到底能召回多少目標(biāo)這對(duì)判斷“漏檢是模型沒學(xué)會(huì)”還是“閾值卡太死”非常關(guān)鍵。4. 避坑手冊(cè)1463張單類別樣本最容易翻車的4個(gè)坑4.1 現(xiàn)象loss正常下降驗(yàn)證集卻幾乎沒有框輸出原因驗(yàn)證集和訓(xùn)練集分布不一致。1463張數(shù)據(jù)如果隨機(jī)劃分驗(yàn)證集里可能全是遠(yuǎn)距離俯拍幀或者全是逆光幀訓(xùn)練時(shí)模型沒見過這些形態(tài)推理置信度全部低于閾值終端打印的框數(shù)量接近零。解決先用2.3的組件ID分組重做劃分然后回到predict命令把conf臨時(shí)降到0.1跑一遍。如果低閾值下框能出現(xiàn)說明模型學(xué)進(jìn)去了問題出在閾值或尺度如果降到0.05還是沒框說明驗(yàn)證集本身和訓(xùn)練集差異大到模型無法泛化這個(gè)時(shí)候不要調(diào)參回去做數(shù)據(jù)分桶或者補(bǔ)充驗(yàn)證集樣本。還有一個(gè)輔助判斷打開val輸出目錄里的原始圖片肉眼確認(rèn)驗(yàn)證集里有沒有和訓(xùn)練集同構(gòu)圖但不同光照的極端場(chǎng)景這類場(chǎng)景往往是“看起來像驗(yàn)證集實(shí)際是另一個(gè)域”。4.2 現(xiàn)象mAP50很高但實(shí)際巡檢漏檢率依然大原因mAP50只看IoU大于0.5的框積灰區(qū)域的邊界本來就模糊框稍微偏一點(diǎn)照樣算命中所以mAP50很容易虛高。我做光伏項(xiàng)目時(shí)目標(biāo)不光是“檢測(cè)到灰”還要估算積灰覆蓋面積框的邊界偏移四分之一面積估算就差出30%以上這是mAP50看不出來的。解決把評(píng)估指標(biāo)的重點(diǎn)轉(zhuǎn)到mAP50-95上這個(gè)指標(biāo)統(tǒng)計(jì)IoU從0.5到0.95多個(gè)檔位的平均值對(duì)框的定位精度更敏感。如果mAP50-95明顯低優(yōu)先做法是把imgsz從640提到960再檢查標(biāo)注框是否本身畫得不齊人工修一批邊界離譜的框比換模型收益更大。處理這類單類別弱紋理目標(biāo)時(shí)很多團(tuán)隊(duì)會(huì)直接用默認(rèn)評(píng)估結(jié)果結(jié)果部署時(shí)被打得措手不及。我的經(jīng)驗(yàn)是單類別積灰檢測(cè)里mAP50和mAP50-95之間的差值超過0.2就說明定位精度不合格必須先解決這個(gè)問題再談上線。4.3 現(xiàn)象batch16一個(gè)epoch沒跑完顯存先崩原因光伏板巡檢圖片往往來自無人機(jī)或高清相機(jī)原始分辨率可能到4000×3000。訓(xùn)練時(shí)如果imgsz不小心設(shè)成原圖尺寸顯存會(huì)被直接吃爆數(shù)據(jù)加載階段沒報(bào)錯(cuò)跑起來才崩。解決訓(xùn)練統(tǒng)一用imgsz640或960不要喂原圖。推理階段如果確實(shí)要處理高清大圖先把原圖裁剪成若干640或960的子圖分別推理再合并結(jié)果。這段“訓(xùn)練用小圖、推理用滑窗”的做法比單純買大顯存實(shí)惠得多。如果batch降到8還是崩再檢查workers是否設(shè)得過高導(dǎo)致內(nèi)存占用疊加。顯存不足的另一個(gè)常見原因是開啟了mosaic增強(qiáng)合成長(zhǎng)圖需要額外顯存4.4里關(guān)閉mosaic之后顯存壓力通常會(huì)下降一截。4.4 現(xiàn)象數(shù)據(jù)增強(qiáng)一開灰塵標(biāo)簽反而被“增強(qiáng)”沒了原因YOLOv8默認(rèn)開啟mosaic、隨機(jī)透視、翻轉(zhuǎn)等增強(qiáng)但灰塵是弱紋理目標(biāo)旋轉(zhuǎn)45度后視覺特征幾乎消失mosaic把四張圖拼在一起時(shí)灰塵區(qū)域可能被裁到拼接縫上標(biāo)簽跟著失效。數(shù)據(jù)增強(qiáng)是為了增加多樣性對(duì)強(qiáng)紋理目標(biāo)有效對(duì)弱紋理目標(biāo)常常是幫倒忙。解決在yaml中先關(guān)閉強(qiáng)增強(qiáng)保留輕量增強(qiáng)# pv_dust.yaml 追加增強(qiáng)覆蓋 mosaic: 0.0 flipud: 0.0 fliplr: 0.0 hsv_h: 0.01 hsv_s: 0.2 hsv_v: 0.2 scale: 0.3 translate: 0.1參數(shù)說明mosaic、flipud、fliplr都是翻轉(zhuǎn)和拼接類強(qiáng)增強(qiáng)灰塵標(biāo)簽在這種變換下容易失真直接置0hsv_h、hsv_s、hsv_v保留很小的擾動(dòng)模擬不同光照下的板面顏色變化scale和translate控制隨機(jī)縮放和平移0.3和0.1是相對(duì)克制的取值。這些參數(shù)可以直接追加到pv_dust.yaml末尾YOLOv8訓(xùn)練時(shí)會(huì)自動(dòng)讀取并覆蓋默認(rèn)增強(qiáng)配置。調(diào)試原則是小樣本、弱紋理目標(biāo)寧可用弱增強(qiáng)把訓(xùn)練穩(wěn)住也不要讓強(qiáng)增強(qiáng)把標(biāo)簽“洗掉”。這是我從血淚經(jīng)驗(yàn)里換來的結(jié)論第一批模型翻車幾乎都卡在這上面。5. 從1463張到能上巡檢現(xiàn)場(chǎng)評(píng)估不看單幀部署要防三類干擾5.1 指標(biāo)取舍P、R、mAP50和mAP50-95各自盯什么1463張單類別樣本訓(xùn)練出來的模型P和R很難同時(shí)拉到0.9以上。業(yè)務(wù)上“少漏報(bào)”和“少誤報(bào)”常常沖突把置信度閾值調(diào)低R上升但P下降誤報(bào)區(qū)域會(huì)讓運(yùn)維人員白白跑一趟電站閾值調(diào)高P上去了漏檢的積灰板又會(huì)導(dǎo)致發(fā)電量損失。我一般會(huì)畫出Precision-Recall曲線找一個(gè)兼顧兩者的工作點(diǎn)而不是盲目用默認(rèn)0.25。下面的表是我常用的閾值參考業(yè)務(wù)訴求推薦閾值區(qū)間代價(jià)少漏檢、允許人工復(fù)核0.10~0.15誤報(bào)增多運(yùn)維復(fù)查壓力大巡檢初篩、平衡誤報(bào)與漏報(bào)0.25~0.30兩者兼顧適合跑第一版少誤報(bào)、自動(dòng)化直接派單0.40~0.50漏檢風(fēng)險(xiǎn)升高適合配合其他傳感器參數(shù)說明閾值不是模型參數(shù)是推理階段的后處理參數(shù)改閾值不需要重訓(xùn)所以可以反復(fù)試。對(duì)1463張小樣本模型我建議先按0.25跑基線再做兩次閾值掃描分別看0.15和0.4下的預(yù)測(cè)圖最后根據(jù)運(yùn)維人工成本挑一個(gè)工作點(diǎn)。YOLOv8的val輸出里自帶pr_curve.png這張圖能直觀看出P和R的拉扯關(guān)系選點(diǎn)時(shí)以它為參考比盯著終端數(shù)字更可靠。5.2 部署時(shí)的三類干擾反光、污漬、紋理數(shù)據(jù)集里的樣本大多是“干凈背景明顯灰塵”的清晰畫面但真實(shí)光伏板現(xiàn)場(chǎng)的反光、污漬和紋理都會(huì)騙過模型。玻璃反光會(huì)產(chǎn)生大范圍高亮區(qū)域顏色和積灰接近鳥糞和水漬在色調(diào)上常常和灰塵混在一起板面本身的柵格紋理在某些光照下也會(huì)被模型當(dāng)成邊緣特征。我部署第一版模型時(shí)最典型的翻車就是反光導(dǎo)致大量誤報(bào)最后是靠把圖像輸入從彩色圖換成了經(jīng)過灰度歸一化的圖同時(shí)加了一個(gè)“反光區(qū)域強(qiáng)度閾值”的后處理才壓下來。另一個(gè)有效辦法是先做光伏板區(qū)域分割只對(duì)板面區(qū)域做積灰檢測(cè)這樣背景里的護(hù)欄、支架、地面反光都能被提前濾掉。后處理這層不能省。我見過不少項(xiàng)目把模型輸出的框直接送到工單系統(tǒng)結(jié)果反光導(dǎo)致的誤報(bào)讓運(yùn)維團(tuán)隊(duì)一天跑三次空趟。輕量做法是對(duì)每個(gè)檢測(cè)框計(jì)算框內(nèi)區(qū)域的亮度方差和邊緣密度如果方差過高且邊緣密度過低就判定為反光區(qū)域降置信度或直接丟棄。這個(gè)規(guī)則不復(fù)雜卻能把誤報(bào)率壓下一個(gè)數(shù)量級(jí)代價(jià)只是誤傷一小部分邊界模糊的真實(shí)積灰。5.3 擴(kuò)充數(shù)據(jù)集的方向抽幀復(fù)用、自采和電力公開數(shù)據(jù)1463張只能打底。最穩(wěn)妥的擴(kuò)充是在同一批電站上再飛一段視頻按間隔抽幀然后用已有模型做半自動(dòng)標(biāo)注人工修框。這里有個(gè)原則擴(kuò)充要加“難樣本”不要加大量相似幀。相似幀只會(huì)讓訓(xùn)練集變大驗(yàn)證集虛高指標(biāo)漲的是水份不是能力。去重可以用簡(jiǎn)單的幀間差分實(shí)現(xiàn)把連續(xù)幀轉(zhuǎn)成灰度圖計(jì)算相鄰幀的像素差均值低于閾值就說明幾乎沒變化直接丟棄。抽幀間隔也要從視頻運(yùn)動(dòng)速度反推無人機(jī)緩慢飛行時(shí)每2秒抽一幀就足夠抽太密全是重復(fù)信息。想要讓模型對(duì)弱紋理更魯棒可以找firc-dataset這類電力紅外數(shù)據(jù)集做輔助預(yù)訓(xùn)練紅外圖像里溫差形成的輪廓能幫助模型學(xué)習(xí)“板面區(qū)域”的結(jié)構(gòu)再遷移回可見光數(shù)據(jù)也可以納入公開的絕緣子、光伏板檢測(cè)數(shù)據(jù)做域?qū)R訓(xùn)練。需要留意的是不同數(shù)據(jù)集之間類別的含義可能不一樣合并訓(xùn)練前要先把類別體系統(tǒng)一框的坐標(biāo)也要重新檢查。對(duì)1463張這種規(guī)模的打底數(shù)據(jù)集我的建議是第一版先單獨(dú)訓(xùn)拿到基線后再做域增強(qiáng)和混合訓(xùn)練否則一開始就把多個(gè)來源的數(shù)據(jù)揉在一起出了問題很難定位。6. 進(jìn)階技巧訓(xùn)練前先跑一次數(shù)據(jù)體檢把壞框和空標(biāo)簽清干凈訓(xùn)練前的最后一道工序我習(xí)慣跑一個(gè)簡(jiǎn)短的數(shù)據(jù)體檢腳本。它的作用不是訓(xùn)練模型而是用一個(gè)數(shù)字告訴你這批數(shù)據(jù)里有多少空標(biāo)簽、多少個(gè)框的面積占比異常小、多少張圖的框尺度分布嚴(yán)重分裂。腳本如下import os import numpy as np import xml.etree.ElementTree as ET voc_dir labels_voc empty_files [] box_ratio [] for xml_name in os.listdir(voc_dir): if not xml_name.endswith(.xml): continue tree ET.parse(os.path.join(voc_dir, xml_name)) root tree.getroot() objs root.findall(object) if len(objs) 0: empty_files.append(xml_name) size root.find(size) w, h int(size.find(width).text), int(size.find(height).text) for obj in objs: b obj.find(bndbox) bw (float(b.find(xmax).text) - float(b.find(xmin).text)) / w bh (float(b.find(ymax).text) - float(b.find(ymin).text)) / h box_ratio.append(bw * bh) print(empty label files:, len(empty_files)) print(total objects:, len(box_ratio)) print(avg box area ratio: %.3f % np.mean(box_ratio)) print(small boxes ratio(0.01): %.3f % (sum(1 for x in box_ratio if x 0.01) / len(box_ratio)))邏輯說明腳本讀每個(gè)XML先統(tǒng)計(jì)沒有object節(jié)點(diǎn)的空標(biāo)簽文件數(shù)再計(jì)算每個(gè)框相對(duì)整張圖的面積占比最后輸出平均值和占比小于0.01的框比例。空標(biāo)簽文件多說明負(fù)樣本不少要在訓(xùn)練配置里打開空標(biāo)簽開關(guān)小框比例高說明場(chǎng)景以小目標(biāo)為主訓(xùn)練時(shí)imgsz要考慮用960并配合滑窗推理。參數(shù)說明0.01這個(gè)閾值對(duì)應(yīng)640分辨率下大約64×64像素的框如果框面積占比再小模型很難學(xué)到有效特征這類框要么清洗掉要么在標(biāo)注階段就不該被畫出來。我在第一個(gè)光伏項(xiàng)目上就吃過標(biāo)簽臟的虧。當(dāng)時(shí)拿到的數(shù)據(jù)里有一批框比正常值大30%模型訓(xùn)完肉眼看著沒問題一換電站就崩。后來養(yǎng)成了一個(gè)習(xí)慣不管數(shù)據(jù)集是誰給的先跑一遍體檢腳本再進(jìn)訓(xùn)練順手把腳本輸出的幾行數(shù)字貼到工單里。這個(gè)習(xí)慣幫我少走了很多彎路也省掉了不少重復(fù)訓(xùn)練的時(shí)間。從1463張出發(fā)做出一個(gè)能用的初版模型并不難難的是在每一步都對(duì)數(shù)據(jù)保持懷疑。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取