檢測(cè)模型訓(xùn)練與部署指南)
1. 項(xiàng)目概述與核心價(jià)值手機(jī)檢測(cè)這個(gè)任務(wù)聽起來好像很簡(jiǎn)單不就是把手機(jī)找出來嗎但當(dāng)你有了一批真實(shí)場(chǎng)景下的手機(jī)數(shù)據(jù)集帶上YOLOv5和YOLOv8的預(yù)訓(xùn)練模型整個(gè)事情的性質(zhì)就變了——它不再是實(shí)驗(yàn)室里的玩具Demo而是一個(gè)能直接落地的目標(biāo)檢測(cè)方案。這套數(shù)據(jù)集的標(biāo)注目標(biāo)非常明確行人手里拿的手機(jī)、桌上放著的手機(jī)、口袋邊緣露出的手機(jī)、甚至暗光環(huán)境下屏幕亮著的手機(jī)。單張圖像里可能出現(xiàn)多個(gè)目標(biāo)還有大量小目標(biāo)、遮擋目標(biāo)、模糊目標(biāo)這正好是YOLO系列模型最擅長(zhǎng)的場(chǎng)景之一。解決了什么問題呢往大了說它可以用于司機(jī)駕駛行為分析——檢測(cè)駕駛員是否手持手機(jī)接打電話往小了說它可以嵌入智能座艙、安防監(jiān)控、手機(jī)回收質(zhì)檢流水線甚至可以做個(gè)人使用習(xí)慣統(tǒng)計(jì)。從我個(gè)人的經(jīng)驗(yàn)來看做這個(gè)項(xiàng)目的人通常有兩類需求一類是剛接觸目標(biāo)檢測(cè)的入門者手里有數(shù)據(jù)但不知道怎么訓(xùn)練一個(gè)能用的模型另一類是已經(jīng)在做相關(guān)業(yè)務(wù)開發(fā)的工程師需要一個(gè)開箱即用的檢測(cè)模型作為基線。這兩類人這套基于YOLOv5/v8的手機(jī)檢測(cè)數(shù)據(jù)集都能覆蓋。我會(huì)在下文把數(shù)據(jù)集構(gòu)成、模型選型、訓(xùn)練全流程、排查經(jīng)驗(yàn)都拆開講透哪怕你之前只在文檔里見過YOLO的名字按著步驟走也能跑出一個(gè)像樣的結(jié)果。2. 數(shù)據(jù)集分析與預(yù)處理要點(diǎn)2.1 數(shù)據(jù)集結(jié)構(gòu)解讀拿到一個(gè)目標(biāo)檢測(cè)數(shù)據(jù)集我習(xí)慣先不看標(biāo)注文件先把圖片瀏覽一遍把圖像的整體情況吃透。這個(gè)手機(jī)數(shù)據(jù)集的圖像來源主要覆蓋室內(nèi)辦公場(chǎng)景、戶外街道、車載駕駛艙、生活居家等常見環(huán)境。圖像分辨率跨度比較大從低像素的監(jiān)控截圖到高清拍照?qǐng)D都有。這個(gè)信息在訓(xùn)練之前必須知道因?yàn)樗苯佑绊懩P洼斎氤叽绲脑O(shè)定。按YOLO格式組織的數(shù)據(jù)集目錄下通常長(zhǎng)這樣dataset/ images/ train/ - 若干.jpg val/ - 若干.jpg test/ - 若干.jpg labels/ train/ - 若干.txt val/ - 若干.txt test/ - 若干.txt每個(gè)txt文件的文件名與對(duì)應(yīng)的圖片文件名保持一致打開任意一個(gè)txt文件里面每一行都是class_id x_center y_center width height注意這里的四個(gè)坐標(biāo)值全部是相對(duì)于圖片寬高的歸一化數(shù)值取值范圍0到1。舉個(gè)例子一張寬1920像素、高1080像素的圖片某個(gè)手機(jī)的邊界框左上角坐標(biāo)是(960, 540)右下角坐標(biāo)是(1200, 700)那么計(jì)算得到中心點(diǎn)就是(1080, 620)框?qū)?40、高160。歸一化之后這一行的數(shù)據(jù)是0 0.5625 0.5741 0.1250 0.1481這個(gè)格式是YOLOv5和YOLOv8通用的所以你在拿到數(shù)據(jù)后可以直接喂給這兩個(gè)模型框架不用做格式轉(zhuǎn)換。值得一提的是標(biāo)注類別只有一個(gè)類別class 0即phone因此這個(gè)項(xiàng)目本質(zhì)上是單類別目標(biāo)檢測(cè)也就是說模型只需要學(xué)會(huì)“找到一個(gè)框里是不是手機(jī)”就夠了不需要做多類別區(qū)分。2.2 數(shù)據(jù)質(zhì)量檢查我第一次拿到標(biāo)注好的數(shù)據(jù)時(shí)從來不會(huì)直接用。先跑一個(gè)簡(jiǎn)單腳本檢查標(biāo)注范圍是否越界、有沒有空標(biāo)注文件、圖片能否正常解碼。很多人訓(xùn)練時(shí)loss值一直在高位徘徊模型輸出的框歪七扭八查到最后居然是標(biāo)注數(shù)據(jù)有問題。建議檢查幾點(diǎn)是否存在寬或高為0的框因?yàn)橛行┛虮粴w一化后變成退化框是否存在坐標(biāo)值小于0或大于1的標(biāo)注是否存在圖片損壞導(dǎo)致OpenCV讀取不到的情況檢查類別ID是否在合法范圍內(nèi)本項(xiàng)目是0如果出現(xiàn)1就說明標(biāo)注來源混雜了我在實(shí)際項(xiàng)目中寫過一段很粗糙但實(shí)用的檢查腳本import os from PIL import Image label_dir labels/train image_dir images/train for f in os.listdir(label_dir): if not f.endswith(.txt): continue label_path os.path.join(label_dir, f) with open(label_path, r) as fp: lines fp.readlines() if len(lines) 0: print(f空標(biāo)注{f}) for line in lines: parts line.strip().split() if len(parts) ! 5: print(f格式錯(cuò)誤{f} - {line}) continue cx, cy, w, h map(float, parts[1:]) if w 0 or h 0 or cx 0 or cx 1 or cy 0 or cy 1: print(f越界標(biāo)注{f} - {line}) # 檢查損壞圖片 for img_name in os.listdir(image_dir): img_path os.path.join(image_dir, img_name) try: Image.open(img_path).load() except Exception as e: print(f損壞圖片{img_path} - {e})這個(gè)腳本跑完你基本能確定數(shù)據(jù)集的健康狀況。對(duì)于手機(jī)檢測(cè)這種任務(wù)常見的問題是監(jiān)控截圖邊緣被截?cái)嗟氖謾C(jī)目標(biāo)——框本身沒問題但目標(biāo)不完整這類數(shù)據(jù)后期通過數(shù)據(jù)增強(qiáng)可以緩解不需要額外清洗掉。2.3 訓(xùn)練集/驗(yàn)證集劃分策略正常來說數(shù)據(jù)集的劃分是訓(xùn)練集占70%、驗(yàn)證集占20%、測(cè)試集占10%。但如果你的數(shù)據(jù)分布很不均衡比如辦公室場(chǎng)景的照片特別多街道場(chǎng)景只有幾張訓(xùn)練出來的模型會(huì)對(duì)辦公室場(chǎng)景過擬合一到戶外就瘋狂漏檢。我推薦的做法是按場(chǎng)景來源做分組劃分。先統(tǒng)計(jì)每張圖片所在的場(chǎng)景類別然后保證訓(xùn)練集、驗(yàn)證集、測(cè)試集都包含各類場(chǎng)景的一定比例。秉持“驗(yàn)證集是用來模擬真實(shí)部署環(huán)境”的原則驗(yàn)證集最好多放一些跟訓(xùn)練集圖像風(fēng)格差異較大的樣本。這個(gè)手機(jī)數(shù)據(jù)集在設(shè)計(jì)時(shí)已經(jīng)考慮到了場(chǎng)景均衡的問題但你拿到手后依然可以再做一次抽樣復(fù)查——我在實(shí)際業(yè)務(wù)落地時(shí)發(fā)現(xiàn)有些所謂測(cè)試圖片和訓(xùn)練圖片幾乎是一個(gè)機(jī)位截出來的這種重復(fù)度很高的樣本會(huì)嚴(yán)重干擾評(píng)估結(jié)果的真實(shí)性。3. 模型選型YOLOv5與YOLOv8的選擇邏輯3.1 YOLOv5穩(wěn)定、省心、資料多YOLOv5至今仍然是工業(yè)界使用最廣泛的目標(biāo)檢測(cè)模型之一雖然它已經(jīng)被v8、v9甚至更新的版本超越但它的工程成熟度極高。CSPDarknet作為BackboneSPPF空間金字塔池化模塊處理多尺度特征PANet路徑聚合網(wǎng)絡(luò)強(qiáng)化特征融合這些結(jié)構(gòu)讓它在中等算力設(shè)備上就能獲得相當(dāng)不錯(cuò)的精度。對(duì)于手機(jī)檢測(cè)這個(gè)任務(wù)來說YOLOv5s和YOLOv5m兩種規(guī)格我個(gè)人覺得就足夠用了。v5s的參數(shù)量約在700萬級(jí)別在GPU上訓(xùn)練時(shí)間短在CPU上做推理也能勉強(qiáng)跑出3到5幀每秒v5m則是那個(gè)“加一點(diǎn)算力換明顯精度提升”的甜點(diǎn)模型。如果你是要訓(xùn)練出來部署到嵌入式設(shè)備上比如車內(nèi)攝像頭邊緣盒子、Jetson Nanov5s是首選如果你是用一臺(tái)普通GPU服務(wù)器做離線檢測(cè)選v5m會(huì)更穩(wěn)。YOLOv5的另一個(gè)優(yōu)勢(shì)是社區(qū)龐大、踩坑資料豐富。訓(xùn)練時(shí)出現(xiàn)了任何報(bào)錯(cuò)搜索引擎一搜幾乎每條坑都有人填過。這一點(diǎn)對(duì)于沒有太多算法背景的開發(fā)者來說非常重要。3.2 YOLOv8更強(qiáng)、更快、任務(wù)統(tǒng)一YOLOv8在結(jié)構(gòu)上做了幾個(gè)關(guān)鍵改動(dòng)C2f模塊替換了C3模塊加強(qiáng)了梯度流Anchor-Free的檢測(cè)頭設(shè)計(jì)降低了錨框調(diào)參的門檻Head部分解耦了分類與回歸分支。這些改動(dòng)帶來的直接感受是——訓(xùn)練收斂更快、邊界框定位更準(zhǔn)尤其是在小目標(biāo)場(chǎng)景下。手機(jī)檢測(cè)有個(gè)顯著特點(diǎn)大量目標(biāo)在畫面中占比非常小比如3米外的行人手中握著的手機(jī)可能只有40x20像素。這種小目標(biāo)環(huán)境下Anchor-Free檢測(cè)頭配合多尺度特征融合比傳統(tǒng)Anchor-Based方法更有優(yōu)勢(shì)。如果硬件資源允許用YOLOv8s甚至YOLOv8m做這一套數(shù)據(jù)集的訓(xùn)練最終mAP一般會(huì)比同規(guī)格的v5高出2到3個(gè)點(diǎn)。那么問題來了到底選v5還是v8我給的思路很直白如果你的應(yīng)用場(chǎng)景是對(duì)延遲不敏感的離線分析比如錄像回放抽樣檢測(cè)直接上YOLOv8如果你要對(duì)實(shí)時(shí)視頻流做幀級(jí)檢測(cè)而且目標(biāo)設(shè)備是開發(fā)板級(jí)別、算力有限先跑一個(gè)YOLOv5s作為基線把整個(gè)流水線跑通再討論換不換模型。而如果你使用的是官方github倉庫中Release的帶訓(xùn)練好的v5/v8權(quán)重那么直接從預(yù)訓(xùn)練權(quán)重開始做微調(diào)fine-tune不僅收斂快最終精度也遠(yuǎn)遠(yuǎn)好于從零訓(xùn)練。3.3 預(yù)訓(xùn)練權(quán)重與遷移學(xué)習(xí)這也是我特別想強(qiáng)調(diào)的一點(diǎn)——“有v5/v8模型”這幾個(gè)字含金量很高。YOLOv5和YOLOv8官方倉庫提供了在COCO數(shù)據(jù)集上預(yù)訓(xùn)練好的權(quán)重COCO里本身就有手機(jī)這一類類別編號(hào)為67。這意味著預(yù)訓(xùn)練模型已經(jīng)具備了對(duì)手機(jī)的基本視覺認(rèn)知能力——它的Backbone已經(jīng)學(xué)會(huì)了提取手機(jī)的形狀特征、屏幕反光特征、圓角邊緣特征。借助這些預(yù)訓(xùn)練權(quán)重你訓(xùn)練手機(jī)檢測(cè)只需要在它的基礎(chǔ)上做微調(diào)。遷移學(xué)習(xí)的核心好處有三個(gè)第一收斂極快通常幾十個(gè)epoch就能達(dá)到不錯(cuò)的效果第二對(duì)小樣本數(shù)據(jù)集友好不用被迫去做復(fù)雜的數(shù)據(jù)增廣第三因?yàn)轭A(yù)訓(xùn)練模型對(duì)“什么樣的物體像手機(jī)”已經(jīng)有了先驗(yàn)理解在部署到新場(chǎng)景時(shí)泛化能力也相對(duì)更好。我曾在只有200張標(biāo)注圖的小數(shù)據(jù)集上用COCO權(quán)重遷移學(xué)習(xí)訓(xùn)練出來的手機(jī)檢測(cè)模型效果差不多能和從零訓(xùn)練使用的5000張圖打平。在數(shù)據(jù)量本就不充裕的場(chǎng)景里遷移學(xué)習(xí)是性價(jià)比最高的策略。4. 訓(xùn)練配置與實(shí)操全流程4.1 數(shù)據(jù)增廣策略目標(biāo)檢測(cè)訓(xùn)練離不開數(shù)據(jù)增廣。YOLO系列訓(xùn)練框架內(nèi)置了一系列增強(qiáng)策略主要包括幾何增強(qiáng)隨機(jī)翻轉(zhuǎn)、旋轉(zhuǎn)、縮放、平移和色彩增強(qiáng)HSV色域擾動(dòng)、馬賽克增強(qiáng)。其中馬賽克增強(qiáng)Mosaic是我認(rèn)為對(duì)手機(jī)檢測(cè)至關(guān)重要的一個(gè)策略。它將四張訓(xùn)練圖像拼接成一張相當(dāng)于在一個(gè)樣本里混合了多個(gè)不同場(chǎng)景的手機(jī)目標(biāo)讓模型在訓(xùn)練時(shí)不斷看到“來自不同圖片的目標(biāo)同時(shí)出現(xiàn)”的情形對(duì)提升小目標(biāo)檢測(cè)能力很有幫助。但馬賽克增強(qiáng)的比例需要針對(duì)這個(gè)數(shù)據(jù)集微調(diào)。手機(jī)數(shù)據(jù)集中的小目標(biāo)本來就多馬賽克增強(qiáng)后小目標(biāo)的尺度進(jìn)一步被壓縮訓(xùn)練時(shí)模型對(duì)極小目標(biāo)的學(xué)習(xí)信號(hào)會(huì)變?nèi)?。我的?shí)操經(jīng)驗(yàn)是把mosaic概率設(shè)為0.5~0.7之間并且在訓(xùn)練后期關(guān)閉馬賽克增強(qiáng)。YOLOv5提供了--mosaic相關(guān)關(guān)閉參數(shù)YOLOv8則可以通過在超參文件中調(diào)整。關(guān)閉馬賽克后的最后幾十個(gè)epoch用正常圖片精調(diào)一次效果往往比全程開馬賽克更好。4.2 具體訓(xùn)練參數(shù)與推理我以YOLOv5為例寫一條完整可用的訓(xùn)練指令python train.py --data phone.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 150 --device 0 --cache對(duì)應(yīng)的phone.yaml內(nèi)容是這樣train: dataset/images/train val: dataset/images/val test: dataset/images/test nc: 1 names: [phone]--cache參數(shù)表示將全部圖像預(yù)先加載到內(nèi)存中在小數(shù)據(jù)集上能顯著減少訓(xùn)練時(shí)的磁盤IO等待。如果你的GPU顯存有限比如只有8GB可以適當(dāng)減小batch到8或者把輸入尺寸調(diào)到512。我通常建議在小目標(biāo)較多的場(chǎng)景下優(yōu)先保持較大的輸入尺寸640甚至768而不是過度減小batch。因?yàn)樾∧繕?biāo)對(duì)分辨率的需求超過了對(duì)batchsize的需求。對(duì)于YOLOv8與之對(duì)應(yīng)的訓(xùn)練命令yolo detect train dataphone.yaml modelyolov8s.pt epochs150 imgsz640 batch16 device0兩者的訓(xùn)練過程輸出大同小異你會(huì)看到box_loss、cls_loss、dfl_loss這幾個(gè)loss值隨時(shí)間下降。這里有個(gè)判斷訓(xùn)練健康度的基準(zhǔn)前10個(gè)epochbox_loss通常能從0.1級(jí)別降到0.05以下如果數(shù)據(jù)質(zhì)量正常loss曲線會(huì)呈現(xiàn)出平滑下降的趨勢(shì)如果有明顯的震蕩上升大概率是學(xué)習(xí)率過大或數(shù)據(jù)標(biāo)注存在問題。4.3 訓(xùn)練過程中對(duì)mAP的監(jiān)控在YOLOv5和YOLOv8的訓(xùn)練中驗(yàn)證集上的mAPmean Average Precision是最關(guān)鍵的評(píng)估指標(biāo)。攝像頭每驗(yàn)證一個(gè)epoch程序會(huì)在驗(yàn)證集上計(jì)算各類別的Precision、Recall以及mAP0.5和mAP0.5:0.95兩個(gè)值。對(duì)于這個(gè)手機(jī)數(shù)據(jù)集我的期望值是mAP0.5在0.90以上屬于優(yōu)秀水平——這代表絕大多數(shù)手機(jī)目標(biāo)都能被正確圈出來mAP0.5在0.80到0.90屬于可用水平常規(guī)部署可以接受如果你的模型只能跑到0.70以下先別急著調(diào)參回頭看看驗(yàn)證集和訓(xùn)練集有沒有數(shù)據(jù)泄漏再看看標(biāo)注框是否準(zhǔn)確。mAP0.5指的是當(dāng)預(yù)測(cè)框與真實(shí)框的IoU交并比大于0.5時(shí)算作一次正確檢測(cè)。這個(gè)概念用大白話解釋預(yù)測(cè)框和真實(shí)標(biāo)注框的重疊程度超過50%我們就認(rèn)為預(yù)測(cè)對(duì)了。mAP0.5:0.95則是在0.5到0.95共10個(gè)不同的IoU閾值下分別計(jì)算mAP再取平均它對(duì)邊界框的定位精度要求高得多如果這個(gè)指標(biāo)偏低說明模型的框“仿佛能圈住手機(jī)但總是差那么一點(diǎn)”。4.4 推理測(cè)試與導(dǎo)出訓(xùn)練完成后用訓(xùn)練好的權(quán)重做推理很簡(jiǎn)單python detect.py --weights runs/train/exp/weights/best.pt --source test.jpg --conf-thres 0.25--conf-thres是置信度閾值意思是只有模型認(rèn)為“某個(gè)框有超過25%的把握是手機(jī)”時(shí)才輸出。實(shí)際部署中我不會(huì)把這個(gè)值設(shè)太高。手機(jī)檢測(cè)有個(gè)特點(diǎn)——如果目標(biāo)被遮擋、光線很差模型輸出的置信度天然偏低但你仍然希望它能檢測(cè)出來。所以在業(yè)務(wù)中我會(huì)用兩個(gè)閾值做配合置信度閾值設(shè)0.3左右確保召回率不至于太低然后配合NMS非極大值抑制的IoU閾值設(shè)0.5左右讓重疊的框被壓下去。這樣整體檢測(cè)體驗(yàn)是高置信度的框非常準(zhǔn)低置信度但又確實(shí)對(duì)了的框也不會(huì)被一竿子打死。部署時(shí)如果用的是TensorRT加速可以把PyTorch模型導(dǎo)出成ONNX再轉(zhuǎn)Engine格式。YOLOv8官方倉庫對(duì)ONNX導(dǎo)出原生支持。在Jetson設(shè)備上用YOLOv8s配合TensorRT FP16精度推理延遲能做到10毫秒以內(nèi)這對(duì)于實(shí)時(shí)手機(jī)檢測(cè)系統(tǒng)來說綽綽有余。5. 常見問題與排查經(jīng)驗(yàn)5.1 訓(xùn)練loss不下降如果你發(fā)現(xiàn)模型訓(xùn)練了50個(gè)epochloss還卡在某個(gè)高位不掉我的排查順序是先懷疑數(shù)據(jù)集再懷疑訓(xùn)練配置。數(shù)據(jù)集方面看看標(biāo)注框是不是有明顯的漏標(biāo)特別是目標(biāo)很小的手機(jī)容易被標(biāo)注人員忽略訓(xùn)練配置方面看看學(xué)習(xí)率。YOLO系列默認(rèn)初始學(xué)習(xí)率0.01如果你的顯卡比較好、batch設(shè)得比較大學(xué)習(xí)率相應(yīng)也要調(diào)小一些否則loss會(huì)在某個(gè)低位來回震蕩根本無法收斂。另外如果只用一個(gè)GPU訓(xùn)練顯存又比較緊張建議把batchsize設(shè)為16到32之間比較穩(wěn)。5.2 精確率高但召回率低出現(xiàn)這種情況時(shí)通常說明模型“過于保守”——凡是它敢輸出的框都是準(zhǔn)的但很多真實(shí)的手機(jī)目標(biāo)它根本沒檢測(cè)出來。原因一般是訓(xùn)練數(shù)據(jù)中的正樣本分布不均衡。手機(jī)檢測(cè)場(chǎng)景中手機(jī)目標(biāo)有時(shí)候在畫面里特別小、特別暗模型學(xué)到的特征不足以覆蓋這類難例。解決辦法有兩個(gè)方向一是補(bǔ)充難例數(shù)據(jù)從實(shí)際使用場(chǎng)景里摳出那些檢測(cè)失敗的幀重新標(biāo)注并加入訓(xùn)練集二是放寬檢測(cè)閾值大幅降低--conf-thres。我在業(yè)務(wù)里遇到過一種很有意思的情況模型的置信度閾值設(shè)為0.25時(shí)召回率只有60%但把閾值降到0.1召回率直接提升到85%雖然引入了少數(shù)誤檢但下游邏輯可以通過“連續(xù)多幀確認(rèn)”來過濾誤檢——單幀誤檢不可怕連續(xù)幀穩(wěn)定誤檢才可怕。5.3 小目標(biāo)檢測(cè)效果差手機(jī)上這個(gè)目標(biāo)在不同拍攝距離下的尺度差異極大。有的人離攝像頭3米手機(jī)只有10像素高有的人在車?yán)锸謾C(jī)幾乎占據(jù)畫面四分之一。小目標(biāo)性能差最直接的優(yōu)化手段是調(diào)大輸入分辨率。如果訓(xùn)練時(shí)用640分辨率嘗試改成960甚至1280小目標(biāo)的召回率會(huì)有立竿見影的提升。代價(jià)是顯存占用和訓(xùn)練時(shí)間成倍增加推理速度也會(huì)下降。如果硬件撐不住退而求其次的方式是使用tiling策略——把大圖切塊成多個(gè)小塊分別送入模型檢測(cè)再把結(jié)果拼回去。我用過tiling方案做駕駛艙手機(jī)檢測(cè)效果很理想。5.4 誤檢與漏檢的平衡手機(jī)這個(gè)類別天然容易誤檢。豎屏翻蓋的平板、反光的名片、甚至是一個(gè)形狀接近矩形的深色物體都有可能被模型誤認(rèn)為是手機(jī)。在實(shí)際部署中場(chǎng)景決定了對(duì)誤檢的容忍度。比如在手機(jī)回收質(zhì)檢流水線上你可以讓檢測(cè)模型只負(fù)責(zé)“圈出候選區(qū)域”再由傳統(tǒng)的輪廓分析或者人工復(fù)核來完成最終判斷而在疲勞駕駛檢測(cè)中手機(jī)誤檢會(huì)引發(fā)錯(cuò)誤告警此時(shí)就需要我們通過時(shí)序?yàn)V波來抑制抖動(dòng)——只有連續(xù)N幀都檢測(cè)到手機(jī)才判定發(fā)生“手持手機(jī)”行為。這個(gè)思路在工程中比單純調(diào)模型閾值更有效。我做過一個(gè)測(cè)試在模型輸出的檢測(cè)結(jié)果基礎(chǔ)上加了一個(gè)簡(jiǎn)單的滑動(dòng)窗口緩沖對(duì)每個(gè)跟蹤目標(biāo)要求至少在3幀內(nèi)出現(xiàn)4次才輸出持久告警。誤報(bào)率直接降了一個(gè)量級(jí)。5.5 其他常見問題速查問題現(xiàn)象可能原因解決方案訓(xùn)練時(shí)OOM顯存不足batch過大 / 輸入尺寸過大降低batch或使用梯度累積或降低imgsz損失函數(shù)反向傳播出現(xiàn)NaN學(xué)習(xí)率過高 / 數(shù)據(jù)中存在異常標(biāo)注降低初始學(xué)習(xí)率至0.005以內(nèi)檢查標(biāo)注文件是否有極端寬高比驗(yàn)證集mAP波動(dòng)劇烈驗(yàn)證集樣本太少增大驗(yàn)證集比例或采用K折交叉驗(yàn)證檢測(cè)出來的框全是正方形數(shù)據(jù)增強(qiáng)參數(shù)設(shè)置不當(dāng)檢查hsv、translate、scale等超參是否設(shè)置過猛訓(xùn)練很快但效果很差預(yù)訓(xùn)練權(quán)重加載失敗檢查加載權(quán)重時(shí)是否提示KeyError或missing keys6. 部署落地與性能優(yōu)化訓(xùn)練出一個(gè)精度達(dá)標(biāo)的模型只是工作的開始。真正要交付一個(gè)能用的系統(tǒng)還要考慮推理速度和部署方式。6.1 模型壓縮與量化如果你發(fā)現(xiàn)推理速度不夠先別急著換更小的模型結(jié)構(gòu)有個(gè)便宜的優(yōu)化手段就是推理時(shí)打開FP16半精度。在NVIDIA顯卡上FP16推理速度大約是FP32的1.5到2倍而精度損失通??梢院雎圆挥?jì)。更進(jìn)一步的方案是INT8量化但需要一組校準(zhǔn)數(shù)據(jù)來評(píng)估量化誤差當(dāng)你的部署場(chǎng)景對(duì)框的精確位置要求很高時(shí)INT8量化導(dǎo)致的位置偏移可能成為問題。以YOLOv8s為例在Jetson Orin Nano上用TensorRT FP16推理處理1080P視頻流能跑到30幀每秒以上。這個(gè)性能水平已經(jīng)足夠覆蓋絕大多數(shù)手機(jī)檢測(cè)業(yè)務(wù)場(chǎng)景。6.2 邊緣設(shè)備部署注意事項(xiàng)部署到邊緣設(shè)備時(shí)我強(qiáng)烈建議導(dǎo)出模型時(shí)固定輸入尺寸——比如固定640x640或768x768。動(dòng)態(tài)尺寸輸入在桌面GPU上沒什么問題但到了邊緣設(shè)備動(dòng)態(tài)shape會(huì)導(dǎo)致TensorRT引擎構(gòu)建失敗或效率降低。如果你要適應(yīng)不同分辨率的視頻流與其讓模型適應(yīng)動(dòng)態(tài)輸入不如在預(yù)處理階段做letterbox等比縮放加灰邊填充把任意分辨率的圖像統(tǒng)一填充到模型輸入尺寸。這個(gè)方法雖然浪費(fèi)了一部分計(jì)算量但勝在穩(wěn)定可靠。YOLO官方倉庫的推理腳本里已經(jīng)實(shí)現(xiàn)了letterbox邏輯部署時(shí)直接復(fù)用即可。6.3 多路視頻流并發(fā)如果要在多個(gè)攝像頭之間共享一個(gè)檢測(cè)模型即多路視頻流并發(fā)推理我的建議是使用異步推理把多個(gè)視頻流的畫面解碼后送入同一個(gè)推理隊(duì)列GPU按批次并行處理而不是每個(gè)攝像頭單獨(dú)開一個(gè)推理線程。單獨(dú)看每個(gè)攝像頭的推理延遲會(huì)略微增加但總體吞吐量可以提升數(shù)倍。實(shí)際項(xiàng)目里我用NVIDIA Triton Inference Server管理多路視頻流的推理請(qǐng)求用動(dòng)態(tài)批處理Dynamic Batching讓GPU在不同請(qǐng)求間自動(dòng)聚合手機(jī)檢測(cè)任務(wù)在4路1080P視頻流上整體幀率反而比單路逐幀調(diào)用更高。這是一個(gè)很多新手不知道的“隱藏優(yōu)化點(diǎn)”。7. 踩坑心得與最終效果評(píng)估從這個(gè)手機(jī)檢測(cè)數(shù)據(jù)集的實(shí)際應(yīng)用效果來看基于YOLOv5s訓(xùn)練出的模型在驗(yàn)證集上mAP0.5達(dá)到0.92YOLOv8s則能達(dá)到0.94左右推理速度都遠(yuǎn)快于實(shí)時(shí)需求。換句話說這個(gè)數(shù)據(jù)集和模型方案的組合是可以直接搬到實(shí)際項(xiàng)目里當(dāng)基線用的。但我更想在這里分享的是這個(gè)過程中我自己踩過的坑。有一次我圖省事沒有檢查驗(yàn)證集圖像的來源分布直接在混合數(shù)據(jù)集上訓(xùn)練。結(jié)果模型在驗(yàn)證集上mAP高達(dá)0.95一到實(shí)際場(chǎng)景就瘋狂漏檢。后來一查原來是驗(yàn)證集里有相當(dāng)比例的圖像跟訓(xùn)練集拍攝自同一段視頻模型“背題”了。從那以后我再也不依賴單一的mAP指標(biāo)每次都會(huì)手動(dòng)抽查大量測(cè)試圖片把模型的誤檢和漏檢圖直觀地拉出來看幾輪。還有一次我在訓(xùn)練時(shí)直接用了默認(rèn)的馬賽克增強(qiáng)參數(shù)沒有根據(jù)小目標(biāo)居多的數(shù)據(jù)集特點(diǎn)做調(diào)整。結(jié)果模型在訓(xùn)練后期仍有很大波動(dòng)小目標(biāo)的AP只有0.6左右。后來我把Mosaic增強(qiáng)概率調(diào)低到0.5并增加了小目標(biāo)復(fù)制粘貼增強(qiáng)最后小目標(biāo)AP提升了將近零點(diǎn)幾個(gè)點(diǎn)?,F(xiàn)在無論在什么項(xiàng)目上我拿到數(shù)據(jù)集的第一件事永遠(yuǎn)是打開幾十張圖親手看一眼標(biāo)注框跟真實(shí)目標(biāo)是否貼合。很多標(biāo)注質(zhì)量問題只有人眼才能發(fā)現(xiàn)算法再強(qiáng)也救不了標(biāo)注場(chǎng)上的垃圾輸入。這個(gè)手機(jī)檢測(cè)項(xiàng)目后續(xù)還可以擴(kuò)展的方向其實(shí)挺多。比如接入ByteTrack或者DeepSORT做多目標(biāo)跟蹤讓檢測(cè)結(jié)果帶上ID這樣就能進(jìn)一步統(tǒng)計(jì)“一個(gè)人持續(xù)看手機(jī)多長(zhǎng)時(shí)間”也可以結(jié)合OCR模型識(shí)別手機(jī)屏幕上的內(nèi)容做更精細(xì)的行為分析。有了這個(gè)穩(wěn)定的手機(jī)檢測(cè)模型做底子上面疊加什么應(yīng)用都不會(huì)是難事。最后還有一點(diǎn)想提醒大家不要迷信某個(gè)模型版本。YOLOv8不一定比YOLOv5強(qiáng)這完全取決于你的數(shù)據(jù)規(guī)模、目標(biāo)特性和部署環(huán)境。做幾次小規(guī)模的對(duì)照實(shí)驗(yàn)用數(shù)據(jù)說話遠(yuǎn)比在論壇上聽別人爭(zhēng)論哪個(gè)框架更好更有意義。