戰(zhàn):冬蟲(chóng)夏草小目標(biāo)檢測(cè)從訓(xùn)練到部署全流程)
簡(jiǎn)介目標(biāo)檢測(cè)是計(jì)算機(jī)視覺(jué)領(lǐng)域的核心任務(wù)之一其本質(zhì)是在圖像中定位并識(shí)別感興趣的目標(biāo)。在實(shí)際工程中針對(duì)小目標(biāo)、復(fù)雜背景的檢測(cè)場(chǎng)景模型的選擇與訓(xùn)練策略往往比網(wǎng)絡(luò)結(jié)構(gòu)本身更關(guān)鍵。YOLOv5作為成熟穩(wěn)定的檢測(cè)框架憑借其輕量級(jí)設(shè)計(jì)、靈活的配置和豐富的生態(tài)資源在諸多垂直領(lǐng)域中得到廣泛應(yīng)用。本文以冬蟲(chóng)夏草生長(zhǎng)檢測(cè)為實(shí)踐案例系統(tǒng)介紹從數(shù)據(jù)集構(gòu)建、標(biāo)注規(guī)范、數(shù)據(jù)增強(qiáng)到模型訓(xùn)練、超參調(diào)整、權(quán)重選擇再到推理優(yōu)化與邊緣設(shè)備部署的完整鏈路。通過(guò)合理調(diào)整置信度閾值、輸入分辨率與錨框參數(shù)可有效提升小目標(biāo)的召回率。該技術(shù)路線同樣適用于農(nóng)作物監(jiān)測(cè)、野生資源調(diào)查、工業(yè)缺陷檢測(cè)等場(chǎng)景為開(kāi)發(fā)者提供了一套可復(fù)用的工程化解決方案。 這個(gè)項(xiàng)目其實(shí)挺有意思的。冬蟲(chóng)夏草這玩意兒跟工業(yè)質(zhì)檢里那些規(guī)規(guī)矩矩的螺絲釘完全不一樣它長(zhǎng)在高原草甸上背景是枯草、泥土、碎石混在一起的復(fù)雜環(huán)境子座從土里冒出來(lái)個(gè)頭小、顏色跟周圍環(huán)境還特別接近人眼找起來(lái)都得瞇著眼睛仔細(xì)看。用YOLOv5來(lái)做單類別檢測(cè)聽(tīng)起來(lái)不算復(fù)雜但真正跑通“數(shù)據(jù)準(zhǔn)備→標(biāo)注→訓(xùn)練→權(quán)重部署”這條鏈路里頭的坑一點(diǎn)不少。這篇就把整個(gè)實(shí)戰(zhàn)過(guò)程掰開(kāi)揉碎從數(shù)據(jù)集怎么來(lái)、標(biāo)注要注意什么到訓(xùn)練參數(shù)怎么調(diào)、權(quán)重文件怎么選再到推理和常見(jiàn)問(wèn)題排查一次性講清楚。1. 項(xiàng)目核心思路與方案選型1.1 為什么選YOLOv5而不是YOLOv8或者更重的框架先說(shuō)結(jié)論單類別目標(biāo)檢測(cè)YOLOv5目前依然是性價(jià)比最高的選擇沒(méi)有之一。雖然YOLOv8、YOLOv9這些新版本在COCO這類通用數(shù)據(jù)集上刷榜刷得很歡但放到“冬蟲(chóng)夏草生長(zhǎng)檢測(cè)”這種垂直場(chǎng)景里YOLOv5的生態(tài)成熟度、踩坑資料數(shù)量、部署資料完整度都遠(yuǎn)超新版本。具體原因有三點(diǎn)。第一YOLOv5對(duì)硬件的要求足夠友善。蟲(chóng)草檢測(cè)這套任務(wù)目標(biāo)是小尺寸、低對(duì)比度通常需要在實(shí)地設(shè)備上跑可能是Jetson Nano可能是RK3568也可能是工廠或者實(shí)驗(yàn)室里一臺(tái)普通的老GPU。YOLOv5s和YOLOv5n這兩個(gè)輕量級(jí)版本在GTX 1660這種入門(mén)級(jí)顯卡上就能訓(xùn)練推理時(shí)甚至CPU都能跑只不過(guò)速度慢一些。而YOLOv8雖然也有n/s版本但很多老設(shè)備上的推理庫(kù)和工具鏈對(duì)它的支持還沒(méi)有完全跟上。第二YOLOv5的代碼結(jié)構(gòu)清晰配置文件簡(jiǎn)單適合做二次改動(dòng)。比如后面要講的anchor尺寸調(diào)整、數(shù)據(jù)增強(qiáng)策略開(kāi)關(guān)都是幾行配置的事。而且國(guó)內(nèi)外關(guān)于YOLOv5的教程、踩坑記錄、社區(qū)問(wèn)答簡(jiǎn)直是海量遇到問(wèn)題搜一下基本都有答案。對(duì)這類偏應(yīng)用型的項(xiàng)目來(lái)說(shuō)框架的“可救性”比“先進(jìn)性”重要得多。第三YOLOv5的輸出權(quán)重格式對(duì)后續(xù)部署非常友好。不管是轉(zhuǎn)成onnx、TorchScript還是TensorRT都有成熟穩(wěn)定的轉(zhuǎn)換腳本這在后面做邊緣設(shè)備部署時(shí)會(huì)省掉大量時(shí)間。單類別任務(wù)尤其適合YOLOv5還有一個(gè)隱藏優(yōu)勢(shì)它的Neck和Head設(shè)計(jì)本身是按通用物體檢測(cè)優(yōu)化的在處理單類別、小目標(biāo)、復(fù)雜背景這類場(chǎng)景時(shí)可控的調(diào)節(jié)空間很大不需要做網(wǎng)絡(luò)結(jié)構(gòu)層面的改動(dòng)只需要在數(shù)據(jù)增強(qiáng)、錨框、超參上做文章。1.2 單類別“生長(zhǎng)檢測(cè)”的任務(wù)定位這里需要先把“檢測(cè)”和“分類”的概念理清楚。這個(gè)項(xiàng)目做的是“冬蟲(chóng)夏草生長(zhǎng)檢測(cè)”本質(zhì)上是在圖像中回答兩個(gè)問(wèn)題圖中有沒(méi)有冬蟲(chóng)夏草如果有它在哪里這類需求在實(shí)際業(yè)務(wù)中對(duì)應(yīng)很多場(chǎng)景。比如高原產(chǎn)區(qū)做蟲(chóng)草資源的動(dòng)態(tài)監(jiān)測(cè)通過(guò)無(wú)人機(jī)或地面巡拍采集圖像用模型自動(dòng)框出每個(gè)蟲(chóng)草的位置統(tǒng)計(jì)分布密度再比如藥材企業(yè)做收購(gòu)分級(jí)前的初篩把大量歷史照片里的蟲(chóng)草快速標(biāo)記出來(lái)替代人工一張張翻找還有科研單位做生長(zhǎng)周期觀測(cè)通過(guò)連續(xù)圖像中的蟲(chóng)草位置變化來(lái)分析出土?xí)r間、生長(zhǎng)速度等指標(biāo)。“1類別”意味著不需要區(qū)分蟲(chóng)草的種類、等級(jí)、生長(zhǎng)階段只要能找到“目標(biāo)在哪”就行。這看起來(lái)比多類別任務(wù)簡(jiǎn)單但實(shí)際做下來(lái)會(huì)發(fā)現(xiàn)單類別任務(wù)的難點(diǎn)不在“區(qū)分度”而在“查全率”也就是漏檢率。蟲(chóng)草的顏色和周圍枯草接近早期出土的子座非常小幾十像素到一百像素都很常見(jiàn)如果不專門(mén)優(yōu)化小目標(biāo)檢測(cè)能力模型很容易漏掉大量真實(shí)目標(biāo)。所以這個(gè)項(xiàng)目的數(shù)據(jù)集設(shè)計(jì)和訓(xùn)練策略一切都是圍繞“少漏檢、少誤檢”來(lái)做的而不是追求把某個(gè)類別的AP刷到99%。2. 數(shù)據(jù)集構(gòu)建與預(yù)處理2.1 數(shù)據(jù)來(lái)源與采集策略冬蟲(chóng)夏草的數(shù)據(jù)集不像車牌、行人那么爛大街公開(kāi)的現(xiàn)成數(shù)據(jù)集很少所以很大概率需要自己動(dòng)手?jǐn)€。根據(jù)我做類似農(nóng)作物檢測(cè)項(xiàng)目的經(jīng)驗(yàn)數(shù)據(jù)來(lái)源可以分三條路按優(yōu)先級(jí)排列。第一條路是實(shí)地采集也就是帶著相機(jī)或手機(jī)到種植基地、產(chǎn)區(qū)草甸去拍。這是最理想的方式因?yàn)榕牡降膱D像和實(shí)際部署場(chǎng)景完全一致沒(méi)有域偏移問(wèn)題。拍攝時(shí)要注意幾個(gè)細(xì)節(jié)盡量覆蓋不同時(shí)間段因?yàn)樵绯亢桶淼墓饩€角度、色溫完全不一樣要拍不同天氣條件晴天、陰天、雨后蟲(chóng)草出土后帶著水珠的樣子和干燥時(shí)差別很大還要覆蓋不同背景純草地、碎石地、枯草密集地都要有。拍攝高度和角度也要模擬實(shí)際使用場(chǎng)景如果最終打算用無(wú)人機(jī)俯拍那訓(xùn)練數(shù)據(jù)就不要大量使用平視角度拍攝的圖。第二條路是整理歷史照片。很多產(chǎn)區(qū)的研究者、收購(gòu)商手里都有大量歷史照片雖然可能沒(méi)有針對(duì)檢測(cè)任務(wù)做過(guò)標(biāo)注但作為檢測(cè)任務(wù)的原始素材非常合適。我建議在動(dòng)手標(biāo)注之前先建一個(gè)簡(jiǎn)單的素材池把同角度、同光線、同背景的相似照片去重避免模型過(guò)擬合到重復(fù)背景。第三條路是網(wǎng)絡(luò)公開(kāi)圖片。這個(gè)只能作為補(bǔ)充因?yàn)楣_(kāi)圖片的版權(quán)、分辨率、拍攝角度差異太大而且能搜到的蟲(chóng)草特寫(xiě)圖大多是大目標(biāo)、清晰背景跟實(shí)際野外場(chǎng)景差距很大。如果非要用只能作為增加背景多樣性的輔助不能作為主力數(shù)據(jù)。我以自己做的這套數(shù)據(jù)為例總共1080張圖其中實(shí)地采集約700張歷史資料整理300張網(wǎng)絡(luò)補(bǔ)充80張。數(shù)量不算多但單類別檢測(cè)本身數(shù)據(jù)需求就不像多類別那么高關(guān)鍵是質(zhì)量。2.2 標(biāo)注工具與YOLO格式要點(diǎn)標(biāo)注工具我用的是LabelImg開(kāi)源免費(fèi)操作簡(jiǎn)單安裝后直接就能用。用pip安裝就行pip install labelImg然后命令行啟動(dòng)labelImg在工具里把圖片文件夾和預(yù)定義的類別文件路徑配置好類別文件就是一個(gè)txt每一行寫(xiě)一個(gè)類別名。單類別項(xiàng)目就一行dongchongxiacao標(biāo)注界面里用矩形框把蟲(chóng)草的子座框出來(lái)。這里有個(gè)非常關(guān)鍵的實(shí)操經(jīng)驗(yàn)框的范圍寧小勿大。冬蟲(chóng)夏草的檢測(cè)重點(diǎn)通常放在子座也就是露出地面的那一段真菌結(jié)構(gòu)上不要把周圍的泥土、小草、雜物包進(jìn)框里。因?yàn)榭虻锰髸?huì)讓模型學(xué)到“蟲(chóng)草一堆背景區(qū)域一個(gè)小目標(biāo)”的錯(cuò)誤映射推理時(shí)誤檢率會(huì)直線上升。標(biāo)注完成后LabelImg默認(rèn)會(huì)生成VOC格式的XML文件需要轉(zhuǎn)成YOLO格式的txt。YOLO格式的核心是每張圖對(duì)應(yīng)一個(gè)txt文件每一行代表一個(gè)目標(biāo)格式是class_id center_x center_y width height注意這里的四個(gè)坐標(biāo)值全部是歸一化到0-1之間的用像素值除以圖像寬高得到。舉個(gè)例子一張1920x1080的圖中一個(gè)目標(biāo)框左上角在(500, 300)右下角在(800, 700)那么img_w, img_h 1920, 1080 x1, y1, x2, y2 500, 300, 800, 700 cx ((x1 x2) / 2) / img_w cy ((y1 y2) / 2) / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h如果自己寫(xiě)轉(zhuǎn)換腳本這段邏輯是核心。還要注意YOLO格式的txt文件名必須和圖片文件名完全一致包括擴(kuò)展名前面的部分且放在對(duì)應(yīng)的labels目錄下否則訓(xùn)練時(shí)數(shù)據(jù)加載會(huì)報(bào)錯(cuò)。2.3 數(shù)據(jù)增強(qiáng)策略與樣本平衡數(shù)據(jù)增強(qiáng)對(duì)于蟲(chóng)草這類小目標(biāo)、復(fù)雜背景的任務(wù)極其重要。YOLOv5內(nèi)置了Mosaic增強(qiáng)、隨機(jī)翻轉(zhuǎn)、HSV色域增強(qiáng)、隨機(jī)仿射變換等這些在訓(xùn)練時(shí)默認(rèn)會(huì)啟用。但對(duì)于蟲(chóng)草場(chǎng)景我建議做幾個(gè)針對(duì)性調(diào)整。首先是Mosaic增強(qiáng)的拼圖策略。Mosaic會(huì)把4張圖縮放到小尺寸再拼接好處是增加了小目標(biāo)的數(shù)量壞處是如果原圖本身分辨率不高縮放后目標(biāo)會(huì)變得更加模糊。所以我建議在數(shù)據(jù)準(zhǔn)備階段就不要把原圖壓得太小YOLOv5在訓(xùn)練時(shí)會(huì)把圖resize到輸入尺寸比如640x640如果原圖本身分辨率不足目標(biāo)信噪比會(huì)急劇下降。我自己的經(jīng)驗(yàn)是原圖分辨率至少保持1280以上訓(xùn)練時(shí)imgsz可以設(shè)成640讓模型在縮放過(guò)程中學(xué)到更多細(xì)節(jié)。其次是翻轉(zhuǎn)增強(qiáng)。YOLOv5默認(rèn)的翻轉(zhuǎn)參數(shù)是隨機(jī)水平翻轉(zhuǎn)0.5也就是一半概率左右翻轉(zhuǎn)。蟲(chóng)草的生長(zhǎng)方向雖然天然隨機(jī)的但如果你在實(shí)際部署時(shí)對(duì)方向有明確要求比如明確要檢測(cè)“從土里向上生長(zhǎng)”的狀態(tài)翻轉(zhuǎn)過(guò)狠會(huì)讓模型對(duì)方向不敏感。我在這個(gè)項(xiàng)目里把水平翻轉(zhuǎn)概率降到0.25垂直翻轉(zhuǎn)直接關(guān)閉因?yàn)榇怪狈D(zhuǎn)會(huì)讓蟲(chóng)草變成“倒掛”狀態(tài)實(shí)際場(chǎng)景不會(huì)出現(xiàn)學(xué)了反而干擾。第三是HSV色域增強(qiáng)。蟲(chóng)草和背景的顏色差異很微妙過(guò)度調(diào)整飽和度、色相會(huì)讓模型學(xué)到錯(cuò)誤的顏色特征。YOLOv5默認(rèn)的hsv_h、hsv_s、hsv_v參數(shù)是0.015、0.7、0.4對(duì)通用任務(wù)合適但對(duì)蟲(chóng)草這種低對(duì)比度目標(biāo)我建議把hsv_s降到0.3左右把hsv_v保持0.4讓模型更關(guān)注形狀和紋理特征而不是死記顏色。數(shù)據(jù)集規(guī)模不夠時(shí)還可以用離線增強(qiáng)的方式擴(kuò)充樣本比如旋轉(zhuǎn)90度、180度、270度對(duì)蟲(chóng)草這種無(wú)方向性目標(biāo)其實(shí)沒(méi)毛病以及加入高斯噪聲、輕微模糊模擬不同天氣條件下拍攝的效果。但要記住一個(gè)原則增強(qiáng)是為了模擬真實(shí)分布不是為了編造不存在的場(chǎng)景。2.4 數(shù)據(jù)集目錄結(jié)構(gòu)標(biāo)準(zhǔn)的YOLOv5數(shù)據(jù)集目錄結(jié)構(gòu)如下dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── dongchongxiacao.yaml其中images和labels必須嚴(yán)格對(duì)應(yīng)train、val的比例按8:1:1或9:1來(lái)分都可以。單類別任務(wù)數(shù)據(jù)量本身不大我建議驗(yàn)證集比例稍微高一些比如15%這樣評(píng)估指標(biāo)更可信。劃分的時(shí)候一定注意同一次拍攝的連續(xù)幀照片不要同時(shí)出現(xiàn)在訓(xùn)練集和驗(yàn)證集里不然驗(yàn)證集結(jié)果會(huì)虛高。我習(xí)慣按文件名前綴或目錄來(lái)劃分而不是隨機(jī)抽這樣更貼近真實(shí)場(chǎng)景。yaml配置文件內(nèi)容大概是這樣的train: dataset/images/train val: dataset/images/val test: dataset/images/test nc: 1 names: [dongchongxiacao]路徑建議用相對(duì)路徑這樣整個(gè)項(xiàng)目目錄拷到別的機(jī)器上不用改配置。yaml文件里的換行、空格縮進(jìn)要嚴(yán)格按YAML語(yǔ)法一個(gè)空格錯(cuò)位都會(huì)報(bào)錯(cuò)。3. 環(huán)境配置與訓(xùn)練關(guān)鍵步驟3.1 YOLOv5環(huán)境安裝環(huán)境安裝這塊網(wǎng)上教程五花八門(mén)我直接說(shuō)一套最穩(wěn)的流程。先創(chuàng)建Python虛擬環(huán)境推薦用condaconda create -n yolov5 python3.8 conda activate yolov5然后克隆YOLOv5倉(cāng)庫(kù)并安裝依賴git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txtrequirements.txt會(huì)裝torch、torchvision、opencv-python、numpy、matplotlib等一堆依賴。需要注意這里默認(rèn)裝的是CPU版torch如果你有NVIDIA GPU需要先裝對(duì)應(yīng)CUDA版本的torch再跑requirements。建議先單獨(dú)裝pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118再執(zhí)行pip install -r requirements.txt這樣能避免依賴順序問(wèn)題。裝完之后先跑一個(gè)最簡(jiǎn)單的測(cè)試python detect.py --weights yolov5s.pt --source data/images/bus.jpg如果順利輸出結(jié)果圖說(shuō)明環(huán)境通了。如果卡在下載權(quán)重文件那一步就手動(dòng)去下載yolov5s.pt放到項(xiàng)目根目錄。權(quán)重文件名必須嚴(yán)格匹配大小寫(xiě)都不能錯(cuò)。3.2 數(shù)據(jù)配置文件與訓(xùn)練啟動(dòng)環(huán)境就緒后把前面準(zhǔn)備好的dataset目錄和yaml配置文件放到Y(jié)OLOv5項(xiàng)目同級(jí)目錄下。訓(xùn)練命令是python train.py --img 640 --batch 16 --epochs 200 --data dongchongxiacao.yaml --weights yolov5s.pt --name dongchong_test逐項(xiàng)解釋一下--img是輸入圖像尺寸640是默認(rèn)值如果你的顯存夠比如12G以上可以調(diào)成960小目標(biāo)檢測(cè)效果會(huì)明顯提升--batch是批大小16在8G顯存下是安全的如果爆顯存就降到8--epochs是訓(xùn)練輪數(shù)單類別任務(wù)200輪完全夠再多了容易過(guò)擬合--weights是預(yù)訓(xùn)練權(quán)重這里用yolov5s.pt如果你顯存很小可以用yolov5n.pt更輕量但精度會(huì)掉一點(diǎn)--name是訓(xùn)練輸出的文件夾名YOLOv5會(huì)保存到runs/train/下。訓(xùn)練過(guò)程中要盯幾個(gè)東西。第一個(gè)是loss曲線YOLOv5的輸出里box_loss、obj_loss、cls_loss三條曲線單類別任務(wù)主要關(guān)注box_loss和obj_loss。正常情況是前50輪快速下降之后緩慢收斂如果曲線一路走平或者反彈說(shuō)明有問(wèn)題下面排查章節(jié)詳細(xì)說(shuō)。第二個(gè)是mAP曲線每10輪會(huì)自動(dòng)在驗(yàn)證集上評(píng)估一次mAP0.5一般到0.85以上就算能用蟲(chóng)草這種難檢測(cè)的小目標(biāo)0.8以上已經(jīng)算不錯(cuò)了。3.3 超參數(shù)調(diào)整與實(shí)戰(zhàn)心得YOLOv5自帶一個(gè)超參數(shù)文件data/hyps/hyp.scratch-low.yaml默認(rèn)值對(duì)通用任務(wù)比較穩(wěn)。但蟲(chóng)草檢測(cè)有幾個(gè)參數(shù)值得動(dòng)一動(dòng)。一個(gè)是錨框anchor。YOLOv5默認(rèn)的anchor是在COCO數(shù)據(jù)集聚類出來(lái)的對(duì)蟲(chóng)草這種小目標(biāo)來(lái)說(shuō)偏大。如果你在訓(xùn)練日志里看到某些anchor匹配率很低YOLOv5會(huì)自動(dòng)重聚類所以一般不用手動(dòng)改但為了保險(xiǎn)可以在訓(xùn)練前用YOLOv5自帶的聚類腳本對(duì)標(biāo)注框做一次分析。方法不復(fù)雜本質(zhì)是用K-means統(tǒng)計(jì)所有標(biāo)注框的長(zhǎng)寬分布。蟲(chóng)草的目標(biāo)框特點(diǎn)是細(xì)長(zhǎng)、瘦高子座是長(zhǎng)的跟COCO里那些方形目標(biāo)差異很大。建議訓(xùn)練時(shí)開(kāi)啟--multi-scale參數(shù)讓模型適應(yīng)不同尺度的目標(biāo)。另一個(gè)是正負(fù)樣本匹配的iou閾值。YOLOv5低版本用的是single anchor匹配策略新版本改成動(dòng)態(tài)分配。如果想調(diào)可以在模型配置文件里改anchor_t默認(rèn)4.0這個(gè)值越大允許預(yù)測(cè)框偏離真實(shí)框的程度越大對(duì)召回率有幫助但會(huì)犧牲一些精度。單類別任務(wù)我建議適度調(diào)高比如設(shè)成4.5因?yàn)橄x(chóng)草目標(biāo)小、形狀細(xì)長(zhǎng)太嚴(yán)格的正樣本匹配會(huì)讓模型學(xué)不到東西。還有一個(gè)非常容易被忽略的參數(shù)--workers。這個(gè)參數(shù)控制數(shù)據(jù)加載的線程數(shù)Windows下默認(rèn)0Linux下可以設(shè)成4或8。數(shù)據(jù)加載速度跟不上GPU時(shí)訓(xùn)練會(huì)一直等數(shù)據(jù)GPU利用率上不去看起來(lái)像模型壞了一樣實(shí)際是IO瓶頸。3.4 權(quán)重文件解讀與版本管理訓(xùn)練結(jié)束后runs/train/dongchong_test/weights/目錄下會(huì)有兩個(gè)文件best.pt和last.pt。這兩個(gè)文件看似差不多實(shí)際用途完全不同。best.pt是整個(gè)訓(xùn)練過(guò)程中在驗(yàn)證集上表現(xiàn)最好的權(quán)重也是我們?nèi)粘M评怼⒉渴鹨玫哪莻€(gè)。last.pt是最后一個(gè)epoch的權(quán)重主要用于中斷后恢復(fù)訓(xùn)練或者你想繼續(xù)在前一次訓(xùn)練結(jié)果的基礎(chǔ)上接著跑。千萬(wàn)別把它們搞混了很多人圖省事直接用last.pt部署結(jié)果精度明顯偏低。權(quán)重文件用起來(lái)有幾個(gè)細(xì)節(jié)要注意。第一best.pt是包含完整的模型結(jié)構(gòu)、優(yōu)化器狀態(tài)和訓(xùn)練配置的文件比較大yolov5s大約15M如果只是做推理可以在detect.py里正常加載但如果是部署到生產(chǎn)環(huán)境建議用export.py先轉(zhuǎn)成onnx或TorchScript格式體積更小、加載更快。第二權(quán)重文件的版本和代碼版本必須匹配。用YOLOv6.0的代碼跑出來(lái)的權(quán)重拿到Y(jié)OLOv5v5.0的代碼里直接推理大概率報(bào)錯(cuò)或者結(jié)果異常。我在本地會(huì)用一個(gè)簡(jiǎn)單的腳本管理多個(gè)項(xiàng)目的權(quán)重文件目錄結(jié)構(gòu)按項(xiàng)目分weights/ ├── dongchong/ │ ├── best.pt │ ├── last.pt │ └── onnx/ │ └── best.onnx這樣每次訓(xùn)練成果不會(huì)互相覆蓋也能快速回溯。4. 模型評(píng)估與推理部署實(shí)踐4.1 評(píng)估指標(biāo)怎么看訓(xùn)練完之后runs/train/dongchong_test/下會(huì)有results.png里面畫(huà)了所有指標(biāo)曲線。單類別任務(wù)重點(diǎn)看四個(gè)Precision精確率、Recall召回率、mAP0.5、mAP0.5:0.95。在蟲(chóng)草檢測(cè)場(chǎng)景里Recall比Precision重要。這個(gè)邏輯跟工業(yè)質(zhì)檢剛好相反質(zhì)檢里把良品誤判成次品會(huì)增加人工復(fù)檢成本但蟲(chóng)草檢測(cè)如果漏檢Recall低意味著實(shí)際有蟲(chóng)草的地方?jīng)]檢測(cè)出來(lái)統(tǒng)計(jì)密度或計(jì)數(shù)就會(huì)偏低這直接導(dǎo)致數(shù)據(jù)失真。所以訓(xùn)練階段如果發(fā)現(xiàn)Precision和Recall有矛盾優(yōu)先照顧Recall。YOLOv5在驗(yàn)證時(shí)輸出的PR曲線圖會(huì)顯示置信度閾值與Precision/Recall的平衡關(guān)系。默認(rèn)置信度閾值是0.25如果你發(fā)現(xiàn)推理時(shí)漏檢多可以把這個(gè)值降到0.15甚至0.1如果誤檢多就往上調(diào)到0.4。這個(gè)調(diào)參邏輯后面推理部分還會(huì)詳細(xì)說(shuō)。一個(gè)容易踩的坑mAP0.5:0.95這個(gè)指標(biāo)在蟲(chóng)草這種小目標(biāo)、細(xì)長(zhǎng)形狀的任務(wù)上通常不會(huì)好看可能只有0.3-0.4這是正常的。因?yàn)檫@個(gè)IoU閾值范圍太嚴(yán)格蟲(chóng)草的框稍微偏一點(diǎn)IoU就掉得厲害。不要單純因?yàn)閙AP0.5:0.95不高就認(rèn)為模型不行還是要看實(shí)際推理效果。4.2 推理參數(shù)優(yōu)化推理用detect.py基本命令python detect.py --weights runs/train/dongchong_test/weights/best.pt --source test_images/ --conf 0.25 --iou 0.45 --img 640--conf是置信度閾值--iou是NMS的IoU閾值。實(shí)際調(diào)參經(jīng)驗(yàn)是蟲(chóng)草檢測(cè)的置信度閾值不要設(shè)太高因?yàn)樾∧繕?biāo)、低對(duì)比度目標(biāo)的置信度天然偏低。我實(shí)測(cè)下來(lái)0.15-0.2這個(gè)區(qū)間的置信度閾值能在漏檢和誤檢之間找到比較好的平衡點(diǎn)。NMS的iou閾值保持在0.45-0.5就行蟲(chóng)草目標(biāo)之間基本不會(huì)互相重疊。如果檢測(cè)的是視頻或?qū)崟r(shí)攝像頭流還要注意--vid-stride參數(shù)默認(rèn)是1也就是逐幀檢測(cè)。野外拍攝的視頻如果幀率很高比如30fps相鄰幀內(nèi)容幾乎不變可以調(diào)成2或3省一半算力還不漏目標(biāo)。代碼層面如果想在推理時(shí)順便輸出目標(biāo)的數(shù)量可以在detect.py的輸出循環(huán)里加幾行判斷統(tǒng)計(jì)每個(gè)檢測(cè)結(jié)果里框的數(shù)量。這個(gè)功能在蟲(chóng)草密度統(tǒng)計(jì)場(chǎng)景特別實(shí)用。4.3 邊緣設(shè)備部署的思路如果最終要部署在Jetson、RK3588這類邊緣設(shè)備上做實(shí)時(shí)檢測(cè)建議提前把權(quán)重轉(zhuǎn)成TensorRT或RKNN格式。YOLOv5自帶的export.py支持onnx導(dǎo)出python export.py --weights best.pt --include onnx --opset 11轉(zhuǎn)出來(lái)的onnx可以接著用TensorRT的trtexec工具優(yōu)化或者轉(zhuǎn)成RKNN。這里有個(gè)重要提醒邊緣設(shè)備上的量化對(duì)細(xì)長(zhǎng)小目標(biāo)不友好。蟲(chóng)草目標(biāo)本身的像素面積小INT8量化后特征丟失嚴(yán)重很多目標(biāo)就檢測(cè)不到了。如果邊緣設(shè)備推理精度掉得厲害優(yōu)先考慮FP16而不是INT8或者干脆用FP32雖然慢一點(diǎn)但保精度。部署時(shí)還有一個(gè)很容易忽略的點(diǎn)輸入分辨率要和訓(xùn)練時(shí)保持一致。如果訓(xùn)練用640推理時(shí)為了提高速度改成320小目標(biāo)會(huì)大量漏檢。如果確實(shí)需要提速建議改batch size或換輕量主干而不是降低輸入分辨率。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 訓(xùn)練不收斂或loss震蕩這個(gè)現(xiàn)象在蟲(chóng)草項(xiàng)目里很常見(jiàn)因?yàn)槟繕?biāo)小、正負(fù)樣本極度不平衡。首先要確認(rèn)一個(gè)關(guān)鍵點(diǎn)是不是數(shù)據(jù)標(biāo)注出了問(wèn)題。我遇到過(guò)好幾次訓(xùn)練loss一直降不下去打開(kāi)標(biāo)注文件一看坐標(biāo)歸一化做錯(cuò)了有一半目標(biāo)框的cx、cy超過(guò)1模型根本學(xué)不到正確位置。如果確認(rèn)標(biāo)注沒(méi)問(wèn)題再檢查訓(xùn)練集和驗(yàn)證集是不是有重復(fù)。前面說(shuō)過(guò)連續(xù)幀照片如果同時(shí)進(jìn)訓(xùn)練集和驗(yàn)證集驗(yàn)證集的loss會(huì)很低但推理時(shí)表現(xiàn)差這是典型的“假收斂”。另外數(shù)據(jù)太少也會(huì)導(dǎo)致loss震蕩單類別任務(wù)至少要有500張有效圖再多就穩(wěn)很多。超參數(shù)方面如果前50輪loss完全沒(méi)有下降趨勢(shì)嘗試把--lr0初始學(xué)習(xí)率從默認(rèn)的0.01降到0.001。蟲(chóng)草這種難分類任務(wù)學(xué)習(xí)率太大容易在loss曲面震蕩小一點(diǎn)反而收斂更穩(wěn)。5.2 CUDA顯存不足顯存不足是新手遇到最多的報(bào)錯(cuò)英文提示通常是CUDA out of memory。最直接的解決辦法是降低--batch從16降到8再降到4直到能跑起來(lái)。但要注意batch太小導(dǎo)致梯度估計(jì)不準(zhǔn)訓(xùn)練會(huì)不穩(wěn)定。我建議優(yōu)先降低--img尺寸從640降到512或480這樣顯存占用下降非常明顯同時(shí)小目標(biāo)性能損失不算太大。如果batch和img都不想動(dòng)就開(kāi)梯度累積可以通過(guò)在訓(xùn)練腳本里設(shè)置--accumulate參數(shù)YOLOv5新版沒(méi)有直接暴露的CLI參數(shù)需要改代碼或在hyp里調(diào)相當(dāng)于每多步積累一次梯度再更新效果近似于變相擴(kuò)大batch。5.3 過(guò)擬合特征蟲(chóng)草數(shù)據(jù)集如果采集場(chǎng)景單一模型很容易過(guò)擬合。表現(xiàn)形式是訓(xùn)練集loss很低但驗(yàn)證集loss反彈或者驗(yàn)證集mAP遲遲上不去。解決辦法有兩個(gè)方向。一是嚴(yán)格劃分?jǐn)?shù)據(jù)集保證訓(xùn)練集和驗(yàn)證集的拍攝場(chǎng)景不重疊二是加大數(shù)據(jù)增強(qiáng)強(qiáng)度把Mosaic的縮放范圍調(diào)大、開(kāi)啟copy_paste增強(qiáng)YOLOv5新版支持讓模型見(jiàn)過(guò)更多樣的輸入。5.4 推理誤檢、漏檢調(diào)整思路把常見(jiàn)問(wèn)題整理成一張速查表方便直接對(duì)著排查。現(xiàn)象可能原因解決方式漏檢多該框的沒(méi)框置信度閾值偏高把--conf從0.25降到0.15漏檢多且小目標(biāo)完全看不見(jiàn)輸入分辨率太低把--img從640提高到960誤檢多把草、石頭框出來(lái)置信度閾值偏低把--conf從0.15升到0.35誤檢多且框偏大標(biāo)注框畫(huà)得太大重新檢查并修改部分標(biāo)注后重訓(xùn)驗(yàn)證集AP高但新圖效果差訓(xùn)練集和部署場(chǎng)景差異大補(bǔ)充部署場(chǎng)景的數(shù)據(jù)或做遷移微調(diào)輸出結(jié)果閃爍視頻檢測(cè)幀間置信度波動(dòng)結(jié)合跟蹤邏輯或提高幀推理穩(wěn)定性5.5 幾個(gè)容易忽視的細(xì)節(jié)這些細(xì)節(jié)是做完整個(gè)項(xiàng)目之后回頭看最想讓當(dāng)初的自己提前知道的。第一不要迷信訓(xùn)練輪數(shù)多。單類別蟲(chóng)草檢測(cè)150-200輪足夠再多就是浪費(fèi)算力和顯存。如果發(fā)現(xiàn)100輪以后mAP已經(jīng)開(kāi)始走平可以直接提前停YOLOv5自帶早停機(jī)制默認(rèn)patience是100也可以手動(dòng)設(shè)小一點(diǎn)。第二權(quán)重文件損壞問(wèn)題。從網(wǎng)上下載預(yù)訓(xùn)練權(quán)重時(shí)如果文件下載不全訓(xùn)練時(shí)可能不報(bào)錯(cuò)但loss亂跳。遇到訓(xùn)練異常先把權(quán)重文件刪掉重新下載排除這個(gè)最簡(jiǎn)單的可能性。第三配置文件的YAML格式陷阱。YOLOv5的data yaml里冒號(hào)后面一定要有空格train: dataset/images/train這種寫(xiě)法如果寫(xiě)成train:dataset/images/train會(huì)直接報(bào)錯(cuò)而且報(bào)錯(cuò)信息還很不直觀新人容易在這里卡一個(gè)小時(shí)。第四標(biāo)簽文件和圖片數(shù)量必須一一對(duì)應(yīng)。有些圖是沒(méi)有目標(biāo)的正確的做法是保留一個(gè)內(nèi)容的txt文件0字節(jié)千萬(wàn)不要把沒(méi)有目標(biāo)的圖直接刪掉或者不生成空txt。YOLOv5在加載數(shù)據(jù)時(shí)會(huì)校驗(yàn)數(shù)量對(duì)不上訓(xùn)練就會(huì)中斷。第五多尺度訓(xùn)練與推理分辨率的關(guān)系。如果訓(xùn)練時(shí)用了--multi-scale模型在各尺度下都能工作但推理時(shí)最好還是用訓(xùn)練時(shí)最常用的主尺度通常是640這樣效果最穩(wěn)定。最后再分享一個(gè)小技巧當(dāng)我對(duì)一個(gè)權(quán)重文件的效果不確定時(shí)會(huì)專門(mén)挑幾張最難的圖比如目標(biāo)極小、背景極亂、光線很差的單獨(dú)做測(cè)試而不是只看驗(yàn)證集mAP。因?yàn)轵?yàn)證集是數(shù)據(jù)集劃分出來(lái)的跟訓(xùn)練集同分布在這個(gè)數(shù)據(jù)集上效果好不代表真實(shí)現(xiàn)場(chǎng)效果好。用最難樣本做一個(gè)“壓力測(cè)試”這個(gè)權(quán)重能不能用心里馬上就有數(shù)了。這個(gè)項(xiàng)目做完最大的感受是目標(biāo)檢測(cè)項(xiàng)目的重心往往不在模型本身而在數(shù)據(jù)和細(xì)節(jié)上。YOLOv5的代碼和權(quán)重都是現(xiàn)成的真正決定蟲(chóng)草檢測(cè)效果好壞的是有沒(méi)有一張干凈的、標(biāo)注合理的、分布貼近真實(shí)場(chǎng)景的數(shù)據(jù)集以及遇到了loss不降、顯存爆掉、識(shí)別不準(zhǔn)這些問(wèn)題時(shí)能不能快速定位到癥結(jié)。把這套流程完整跑一遍后續(xù)再換其他單類別檢測(cè)項(xiàng)目基本就是復(fù)制粘貼再微調(diào)的事。本文還有配套的精品資源點(diǎn)擊獲取