境配置到模型部署:目標(biāo)檢測(cè)全流程實(shí)戰(zhàn)指南)
直接開始寫。1. 環(huán)境準(zhǔn)備裝 YOLOv5 之前先把這幾件事搞清楚很多人拿到 YOLOv5 教程就開始復(fù)制粘貼git clone命令結(jié)果裝到一半報(bào)錯(cuò)才回頭一個(gè)個(gè)排查環(huán)境問題。YOLOv5 是個(gè)看似簡(jiǎn)單、實(shí)則對(duì)環(huán)境干凈程度要求不低的項(xiàng)目我見過太多新手卡在環(huán)境上真正把時(shí)間浪費(fèi)在“安裝”而不是“使用”上。所以這篇教程我從環(huán)境講起把最容易被忽略的細(xì)節(jié)一次說透。先說結(jié)論YOLOv5 支持 Python 3.7-3.11官方推薦 PyTorch 1.7 以上版本。但“支持”和“能跑得舒服”是兩回事我個(gè)人長(zhǎng)期用的組合是 Python 3.8 或 3.10 PyTorch 1.10/1.13/2.0這個(gè)區(qū)間最穩(wěn)。Python 版本太新比如 3.12、3.13反而容易踩坑因?yàn)橐恍├习姹疽蕾噹爝€沒有對(duì)應(yīng)的輪子編譯起來會(huì)讓人崩潰。1.1 Python 版本與虛擬環(huán)境為什么不建議直接裝到系統(tǒng)環(huán)境第一步先確認(rèn)你的 Python 環(huán)境和顯卡情況。用 Anaconda 創(chuàng)建獨(dú)立虛擬環(huán)境是 YOLOv5 安裝中最值得養(yǎng)成的習(xí)慣。原因是 YOLOv5 的依賴項(xiàng)版本比較敏感比如numpy的版本會(huì)影響opencv的行為matplotlib版本太新會(huì)導(dǎo)致繪圖報(bào)錯(cuò)。如果你把 YOLOv5 裝到系統(tǒng)環(huán)境里后面跑其他項(xiàng)目時(shí)很容易出現(xiàn)“裝 A 包卸 B 包”的惡性循環(huán)。創(chuàng)建虛擬環(huán)境的命令非常簡(jiǎn)單conda create -n yolov5 python3.10 conda activate yolov5這里我特意選了 Python 3.10因?yàn)樗?PyTorch 生態(tài)里兼容性最好既支持老代碼也支持新庫。如果你用的是 Python 3.8也沒問題都是很穩(wěn)的版本。1.2 GPU 與 CUDA能不能跑顯卡決定了你的訓(xùn)練速度差多少倍接下來檢查 GPU 環(huán)境。YOLOv5 最大優(yōu)勢(shì)之一就是訓(xùn)練門檻低但“低”指的是算法層面不是硬件層面。你至少要有一塊像樣的 NVIDIA 顯卡建議顯存 4GB 以上。沒有獨(dú)顯也能跑但訓(xùn)練速度會(huì)慘不忍睹一個(gè)幾百?gòu)垐D片的小數(shù)據(jù)集可能都要幾小時(shí)。確認(rèn)顯卡驅(qū)動(dòng)和 CUDA 是否可用的標(biāo)準(zhǔn)操作nvidia-smi如果命令提示找不到說明驅(qū)動(dòng)沒裝好先去 NVIDIA 官網(wǎng)裝對(duì)應(yīng)驅(qū)動(dòng)。如果顯示正常你會(huì)看到驅(qū)動(dòng)版本和 CUDA 版本信息。注意nvidia-smi顯示的 CUDA 版本是驅(qū)動(dòng)最高支持的版本不代表你一定需要安裝對(duì)應(yīng)版本的 CUDA ToolkitPyTorch 自帶 CUDA 運(yùn)行庫你只需要合適的驅(qū)動(dòng)。然后是選擇 PyTorch 版本。這一點(diǎn)很多人搞混pip install torch默認(rèn)安裝的是 CPU 版本必須在 PyTorch 官網(wǎng)選擇對(duì)應(yīng)的 CUDA 版本命令安裝。比如pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118這里的cu118對(duì)應(yīng) CUDA 11.8cu121對(duì)應(yīng) CUDA 12.1。選哪個(gè)取決于你的顯卡驅(qū)動(dòng)官方支持穩(wěn)定版即可不用刻意追求最新。一個(gè)排查 GPU 是否生效的小技巧python -c import torch; print(torch.cuda.is_available())輸出True說明 GPU 可用。輸出False先檢查 PyTorch 裝的是不是 CPU 版本再看驅(qū)動(dòng)版本夠不夠新。1.3 目錄規(guī)劃一次把工作區(qū)和數(shù)據(jù)集分開后面能省一半事最后是目錄規(guī)劃。我建議建一個(gè)干凈的 YOLOv5 工作根目錄結(jié)構(gòu)類似下面這樣project/ ├── datasets/ # 數(shù)據(jù)集 ├── yolo_v5/ # 項(xiàng)目代碼 ├── runs/ # 訓(xùn)練輸出 └── weights/ # 預(yù)訓(xùn)練權(quán)重為什么要把數(shù)據(jù)、代碼、輸出分開因?yàn)?YOLOv5 默認(rèn)會(huì)把訓(xùn)練結(jié)果保存在runs/目錄下數(shù)據(jù)集放在項(xiàng)目外能避免誤刪、避免 git 提交時(shí)把幾千張圖片帶進(jìn)去也方便多個(gè)項(xiàng)目復(fù)用同一份數(shù)據(jù)集。別嫌這一步啰嗦我見過太多人數(shù)據(jù)集和代碼混在一個(gè)目錄里最后git clean一執(zhí)行數(shù)據(jù)全沒了的慘案。2. 依賴安裝pip 命令之外這些坑經(jīng)常勸退新手環(huán)境搭好后正式進(jìn)入安裝環(huán)節(jié)。YOLOv5 官方倉(cāng)庫提供了requirements.txt這是最標(biāo)準(zhǔn)和省事的方式。但“pip install”命令就一行真正讓人卡住的往往是網(wǎng)絡(luò)、權(quán)重下載和某些依賴的版本暗坑。2.1 克隆倉(cāng)庫與依賴安裝版本鎖定的用意先克隆倉(cāng)庫再安裝依賴git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txtrequirements.txt里的依賴項(xiàng)都帶有版本號(hào)或版本范圍這是官方在大量測(cè)試后鎖定的組合。比如opencv-python4.1.2、matplotlib3.2.2這些并不是隨便填的版本過低缺少函數(shù)版本過高可能出現(xiàn) API 變更導(dǎo)致腳本報(bào)錯(cuò)。安裝時(shí)盡量一次性裝完不要手動(dòng)一個(gè)個(gè)裝否則容易出現(xiàn)版本沖突。這里要特別說一個(gè)經(jīng)驗(yàn)如果你在中國(guó)大陸網(wǎng)絡(luò)環(huán)境pip install下載大尺寸依賴包如 PyTorch很容易超時(shí)中斷最好提前設(shè)置鏡像源pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple但注意下載 PyTorch 這種帶 CUDA 運(yùn)行庫的包時(shí)鏡像源不一定有對(duì)應(yīng)版本PyTorch 官方源的穩(wěn)定性更高。我的習(xí)慣是PyTorch 用官方源裝其他依賴用鏡像源裝。2.2 第一次運(yùn)行自動(dòng)下載權(quán)重文件安裝完依賴后很多人直接開始訓(xùn)練結(jié)果卡在權(quán)重下載這一步。YOLOv5 的模型權(quán)重文件托管在國(guó)外服務(wù)器首次運(yùn)行時(shí)會(huì)自動(dòng)下載網(wǎng)絡(luò)差的話經(jīng)常失敗。解決辦法是手動(dòng)下載。YOLOv5 官方提供的權(quán)重文件包括yolov5s.pt輕量版、yolov5m.pt中等版、yolov5l.pt重量版、yolov5x.pt超大版文件大小從十幾 MB 到 100 多 MB 不等。下載后將.pt文件放到項(xiàng)目根目錄或你規(guī)劃的weights/目錄即可。一個(gè)常見疑問是這幾個(gè)版本到底選哪個(gè)我做了一張表方便你快速?zèng)Q策模型版本參數(shù)大小約推理速度相對(duì)精度相對(duì)適用場(chǎng)景yolov5n1.9MB極快較低移動(dòng)端/嵌入式y(tǒng)olov5s7.2MB快中等大多數(shù)常規(guī)場(chǎng)景yolov5m21MB中較高對(duì)精度有要求yolov5l47MB慢高離線分析yolov5x89MB很慢最高極致精度追求新手入門一律選yolov5s.pt它平衡了速度和精度顯存需求也低跑通整個(gè)流程之后再按需換大模型。2.3 常見報(bào)錯(cuò)補(bǔ)充顯卡驅(qū)動(dòng)、numpy 版本與路徑問題安裝和使用過程中有幾個(gè)高頻報(bào)錯(cuò)我直接列出來你遇到就不用猜了。第一個(gè)報(bào)錯(cuò)AssertionError: CUDA unavailable, invalid device 0 requested。這是 PyTorch 認(rèn)為你的環(huán)境沒有 CUDA前面用torch.cuda.is_available()檢查一下大概率是裝錯(cuò)包了重裝 GPU 版 PyTorch 即可。第二個(gè)報(bào)錯(cuò)numpy.ndarray size changed, may indicate binary incompatibility。這是典型的 numpy 版本和其他包不兼容通常是 numpy 升級(jí)后二進(jìn)制接口變了降低版本即可pip install numpy1.23.5第三個(gè)報(bào)錯(cuò)FileNotFoundError: weights/yolov5s.pt。這不是代碼問題是權(quán)重文件路徑不對(duì)。檢查你啟動(dòng)訓(xùn)練的命令是在哪個(gè)目錄下執(zhí)行的YOLOv5 相對(duì)路徑依賴很強(qiáng)建議統(tǒng)一在yolov5/項(xiàng)目根目錄下執(zhí)行命令。我在實(shí)際使用中發(fā)現(xiàn)requirements.txt里的依賴一旦裝好就不要再動(dòng)不動(dòng)pip install --upgrade某個(gè)包除非你明確知道自己在做什么。YOLOv5 這套代碼對(duì)依賴版本很敏感無意間升級(jí)了某個(gè)庫可能就讓整個(gè)流程跑不通。3. 數(shù)據(jù)集準(zhǔn)備訓(xùn)練前必須搞懂的 YOLO 格式核心邏輯安裝只是熱身數(shù)據(jù)集才是 YOLOv5 使用里最核心、也最容易被忽視的一環(huán)。很多教程在安裝完之后直接讓你用官方預(yù)訓(xùn)練權(quán)重跑圖片檢測(cè)這當(dāng)然可以但如果你是要訓(xùn)練自己的模型就必須深刻理解 YOLO 格式的數(shù)據(jù)集結(jié)構(gòu)。3.1 目錄結(jié)構(gòu)訓(xùn)練集、驗(yàn)證集怎么擺放才叫規(guī)范YOLOv5 推薦的數(shù)據(jù)集目錄結(jié)構(gòu)是這樣datasets/ └── mydata/ ├── images/ │ ├── train/ # 訓(xùn)練圖片 │ └── val/ # 驗(yàn)證圖片 ├── labels/ │ ├── train/ # 訓(xùn)練標(biāo)簽 │ └── val/ # 驗(yàn)證標(biāo)簽 └── data.yaml # 數(shù)據(jù)配置文件圖片和標(biāo)簽的文件名必須一一對(duì)應(yīng)比如img_001.jpg對(duì)應(yīng)img_001.txt。圖片格式支持.jpg、.png、.bmp等常見格式但建議統(tǒng)一成.jpg因?yàn)?JPEG 壓縮更穩(wěn)定、讀取更快。標(biāo)簽文件是.txt純文本格式。訓(xùn)練集和驗(yàn)證集的比例沒有固定標(biāo)準(zhǔn)但我的習(xí)慣是 8:2 或 9:1。注意驗(yàn)證集不能和訓(xùn)練集有重復(fù)圖片否則驗(yàn)證結(jié)果沒有參考意義。如果你沒有現(xiàn)成的劃分腳本用train_test_split或者直接按文件名哈希分都行關(guān)鍵是保證隨機(jī)。3.2 標(biāo)簽格式每行代表一個(gè)目標(biāo)五個(gè)數(shù)字缺一不可這是 YOLO 格式最核心的部分。每一個(gè).txt標(biāo)簽文件里每一行對(duì)應(yīng)一張圖片中的一個(gè)目標(biāo)格式為object-class x_center y_center width height中間四個(gè)坐標(biāo)值全部是歸一化后的結(jié)果取值在 0 到 1 之間。歸一化的意思是x_center表示目標(biāo)中心點(diǎn)的橫坐標(biāo)占圖片寬度的比例y_center是縱坐標(biāo)占圖高的比例width、height同理。舉個(gè)例子一張 1000x800 的圖片里有一個(gè)目標(biāo)其邊界框左上角坐標(biāo)為 (200, 150)右下角坐標(biāo)為 (500, 650)。那么計(jì)算過程是x_center (200 500) / 2 / 1000 0.35 y_center (150 650) / 2 / 800 0.5 width (500 - 200) / 1000 0.3 height (650 - 150) / 800 0.625所以這一行就是0 0.35 0.5 0.3 0.625其中0代表類別 ID。我自己標(biāo)注數(shù)據(jù)的時(shí)候一般直接用 LabelImg 或 X-AnyLabeling 這類工具。標(biāo)注工具會(huì)自動(dòng)生成 YOLO 格式的標(biāo)簽避免手算坐標(biāo)。但無論用什么工具保存之前一定要確認(rèn)導(dǎo)出格式是 YOLO而不是 VOC 或 COCO。3.3 data.yaml 配置文件把數(shù)據(jù)集的“說明書”寫對(duì)數(shù)據(jù)集文件準(zhǔn)備好之后在datasets/mydata/下新建data.yaml文件。這個(gè)文件就像一份說明書告訴 YOLOv5 數(shù)據(jù)在哪里、有幾類、類別叫什么。內(nèi)容如下train: datasets/mydata/images/train val: datasets/mydata/images/val nc: 2 names: [person, car]注意train和val指向的是圖片文件夾路徑不是標(biāo)簽路徑。YOLOv5 會(huì)根據(jù)同名規(guī)則自動(dòng)去找標(biāo)簽。這個(gè)路徑是相對(duì)于你運(yùn)行訓(xùn)練命令的目錄而言的所以如果你在yolov5/根目錄下執(zhí)行訓(xùn)練命令datasets/要和它同級(jí)或者寫成絕對(duì)路徑。nc是類別數(shù)量names是類別名稱列表。這里有個(gè)非常搞笑的坑名字列表的順序一定要和標(biāo)注時(shí)定義的類別 ID 一致。你在標(biāo)注軟件里把person定義為 0在 names 里就要把person放在第一位否則訓(xùn)練出來的模型會(huì)把你所有的標(biāo)簽張冠李戴。3.4 標(biāo)注時(shí)容易犯的幾個(gè)錯(cuò)誤說到標(biāo)注我把新手最常犯的錯(cuò)集中講一下。第一個(gè)錯(cuò)誤一個(gè)標(biāo)注框里包含了太多背景。YOLO 要求標(biāo)注框盡量貼合目標(biāo)邊緣框得太大模型會(huì)把背景特征學(xué)進(jìn)去框得太小目標(biāo)特征不完整兩種情況都會(huì)影響檢測(cè)精度。第二個(gè)錯(cuò)誤類別不平衡。如果數(shù)據(jù)集里一類有兩千張圖另一類只有五十張圖模型大概率會(huì)把少數(shù)類忽略掉。這種情況可以收集更多少數(shù)類樣本或者用腳本做簡(jiǎn)單過采樣。第三個(gè)錯(cuò)誤圖片里有目標(biāo)但沒標(biāo)出來。這會(huì)產(chǎn)生“漏檢”樣本模型被隱性地告知“這里沒有目標(biāo)”后續(xù)極其容易誤判。每次標(biāo)完一批數(shù)據(jù)我建議用可視化腳本把標(biāo)簽畫到圖片上檢查一遍YOLOv5 里可以直接用detect.py配合--save-txt反過來檢查標(biāo)注質(zhì)量也可以用其它開源可視化工具。4. 開始訓(xùn)練參數(shù)、監(jiān)控與結(jié)果解讀一次跑通的基本功數(shù)據(jù)集準(zhǔn)備好環(huán)境沒問題就可以進(jìn)入訓(xùn)練環(huán)節(jié)了。YOLOv5 的訓(xùn)練命令本身不復(fù)雜真正值得講清楚的是參數(shù)的含義以及訓(xùn)練過程中應(yīng)該看什么、怎么判斷模型練得好不好。4.1 訓(xùn)練命令與核心參數(shù)解析最基礎(chǔ)的訓(xùn)練命令python train.py --img 640 --batch 16 --epochs 100 --data datasets/mydata/data.yaml --weights yolov5s.pt每個(gè)參數(shù)我都拆開講一下--img是訓(xùn)練時(shí)輸入的圖片尺寸。YOLOv5 會(huì)把所有訓(xùn)練圖片統(tǒng)一縮放到這個(gè)尺寸默認(rèn)是 640。它直接決定了模型的輸入分辨率和顯存占用一般用 640 起步如果你的目標(biāo)是小物體可以試試 1280但顯存需求會(huì)成倍增長(zhǎng)。--batch是批大小。它表示一次輸入多少?gòu)垐D片到 GPU 進(jìn)行訓(xùn)練。批大小由顯存決定顯存 8GB 的話 16 比較穩(wěn)妥顯存 4GB 就降到 8 或更低。批大小不宜過小否則梯度更新太頻繁收斂不穩(wěn)定。--epochs是訓(xùn)練輪數(shù)。小數(shù)據(jù)集 100-300 輪足夠大規(guī)模數(shù)據(jù)集可以 300-500。不是越多越好后面我會(huì)教你判斷什么時(shí)候該停。--weights指預(yù)訓(xùn)練權(quán)重。用yolov5s.pt會(huì)自動(dòng)下載并加載官方在 COCO 數(shù)據(jù)集上訓(xùn)練好的權(quán)重這叫做遷移學(xué)習(xí)。比從零訓(xùn)練收斂更快、精度更高。如果想從頭訓(xùn)練改成--weights 即可。另一個(gè)很重要的參數(shù)是--cache。它表示把數(shù)據(jù)提前緩存到內(nèi)存中省去每次迭代都從磁盤讀圖的 IO 時(shí)間訓(xùn)練速度能提升不少。顯存夠用的話建議加上python train.py --img 640 --batch 16 --epochs 100 --data datasets/mydata/data.yaml --weights yolov5s.pt --cache4.2 訓(xùn)練過程監(jiān)控怎么判斷模型在變好還是過擬合訓(xùn)練啟動(dòng)后終端會(huì)不斷打印日志同時(shí)會(huì)在runs/train/exp目錄下生成訓(xùn)練結(jié)果。你需要看三樣?xùn)|西loss 曲線、PR 曲線和驗(yàn)證集精度。loss 分為三部分box_loss邊框回歸損失、obj_loss目標(biāo)置信度損失、cls_loss分類損失。訓(xùn)練初期 loss 會(huì)快速下降中后期下降變慢這很正常。真正需要注意的是 val loss也就是驗(yàn)證集上的損失。如果 train loss 一直降、val loss 反而上升說明模型開始過擬合了這時(shí)應(yīng)該停掉訓(xùn)練或增加數(shù)據(jù)增強(qiáng)。訓(xùn)練結(jié)束后重點(diǎn)看results.png里的 PPrecision 精確率、RRecall 召回率、mAP平均精度均值。這里我給大家一個(gè)通俗解釋精確率是“你檢測(cè)出來的框里有多少是對(duì)的”召回率是“真實(shí)目標(biāo)里你有多少找出來了”mAP 是兩者的綜合指標(biāo)。對(duì)于絕大多數(shù)自定義場(chǎng)景mAP0.5 達(dá)到 0.9 以上就算非常好了。如果只有 0.5 左右先別急著調(diào)參一般先從數(shù)據(jù)下手檢查標(biāo)注對(duì)不對(duì)、樣本夠不夠、是否類別失衡。4.3 斷點(diǎn)續(xù)訓(xùn)與學(xué)習(xí)率調(diào)整訓(xùn)練是一件很耗時(shí)的事哪怕用 GPU幾百?gòu)垐D片的幾輪訓(xùn)練也可能要幾個(gè)小時(shí)。YOLOv5 支持自動(dòng)保存最新權(quán)重last.pt和最優(yōu)權(quán)重best.pt。如果你中途斷了不需要重新跑直接執(zhí)行python train.py --img 640 --batch 16 --epochs 100 --data datasets/mydata/data.yaml --weights runs/train/exp/weights/last.pt這就是斷點(diǎn)續(xù)訓(xùn)接著上次的進(jìn)度繼續(xù)。這是一個(gè)非常實(shí)用的功能我自己訓(xùn)練的時(shí)候基本都會(huì)提前規(guī)劃好訓(xùn)練輪數(shù)但總會(huì)因?yàn)楦鞣N意外中斷斷點(diǎn)續(xù)訓(xùn)省下的時(shí)間非常可觀。另外新手容易忽略的一個(gè)參數(shù)是--patience它表示如果驗(yàn)證集精度連續(xù)多少輪沒有提升就提前終止訓(xùn)練。默認(rèn)是 100意思是 100 輪沒進(jìn)步就自動(dòng)停。這個(gè)機(jī)制很好用能幫你節(jié)省大量時(shí)間。實(shí)際使用中我一般設(shè)置成 30-50讓它在精度上升乏力時(shí)及時(shí)止損。5. 推理檢測(cè)從命令行到 Python 調(diào)用把模型用起來訓(xùn)練完模型總算進(jìn)入“展示成果”的階段了。YOLOv5 既提供了簡(jiǎn)單的命令行方式也提供了靈活的 Python 接口。這個(gè)環(huán)節(jié)我會(huì)兩種都講因?yàn)槿粘?焖衮?yàn)證用命令行但真正嵌入項(xiàng)目時(shí)幾乎都是寫 Python 調(diào)用。5.1 命令行推理一行命令搞定圖片和視頻檢測(cè)使用訓(xùn)練好的best.pt對(duì)圖片進(jìn)行檢測(cè)python detect.py --weights runs/train/exp/weights/best.pt --source test_images/ --conf-thres 0.25--source可以是單張圖片、圖片文件夾、視頻文件甚至可以是攝像頭編號(hào)。比如用攝像頭實(shí)時(shí)檢測(cè)python detect.py --weights runs/train/exp/weights/best.pt --source 0--conf-thres是置信度閾值默認(rèn) 0.25也就是說模型認(rèn)為某個(gè)框有 25% 以上的概率是目標(biāo)才會(huì)畫出來。閾值調(diào)高框更少但更準(zhǔn)調(diào)低框更多但誤檢也會(huì)變多。這個(gè)參數(shù)沒有絕對(duì)標(biāo)準(zhǔn)實(shí)際部署時(shí)你需要根據(jù)自己的場(chǎng)景調(diào)一版比如寧可漏檢不要誤檢就把閾值調(diào)到 0.4 甚至 0.5。運(yùn)行結(jié)束后檢測(cè)結(jié)果會(huì)保存在runs/detect/exp目錄下圖片上已經(jīng)畫好了邊界框、類別標(biāo)簽和置信度。命令行方式能滿足大部分預(yù)覽需求但它的問題在于每次都要加載模型、解析參數(shù)、跑完整流程。如果你要在一個(gè)已有的業(yè)務(wù)系統(tǒng)里調(diào)用檢測(cè)能力絕對(duì)不適合用命令行方式。5.2 Python 接口加載模型、推理與結(jié)果解析YOLOv5 官方直接支持通過 Python 方式加載模型非常簡(jiǎn)單import torch model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/exp/weights/best.pt)這里path指向你自己的權(quán)重文件。加載之后就可以對(duì)圖片進(jìn)行推理img test_images/001.jpg results model(img)results對(duì)象包含很多好東西。我這里給你展示最常用的幾個(gè)屬性# 獲取邊界框坐標(biāo)、置信度、類別ID boxes results.xyxy[0] # 每行: x1, y1, x2, y2, conf, class # 顯示檢測(cè)結(jié)果 results.show() # 保存檢測(cè)結(jié)果 results.save(output/)如果你要在服務(wù)端部署絕對(duì)不建議再用model.show()這種帶 GUI 的調(diào)用方式。更專業(yè)的做法是把檢測(cè)結(jié)果轉(zhuǎn)成結(jié)構(gòu)化數(shù)據(jù)detections results.pandas().xyxy[0] for _, row in detections.iterrows(): x1, y1, x2, y2 int(row[xmin]), int(row[ymin]), int(row[xmax]), int(row[ymax]) conf row[confidence] cls_name row[name] print(f類別: {cls_name}, 置信度: {conf:.2f}, 坐標(biāo): ({x1},{y1})-({x2},{y2}))這一段代碼基本就是你在實(shí)際業(yè)務(wù)中處理 YOLOv5 輸出時(shí)的雛形。無論你接的是拍照檢測(cè)、視頻分析還是實(shí)時(shí)流處理前面加個(gè)讀取幀/圖片后面加個(gè)邏輯處理整個(gè)鏈路就通了。5.3 攝像頭或視頻流檢測(cè)的顯存注意點(diǎn)很多人興致勃勃跑攝像頭實(shí)時(shí)檢測(cè)結(jié)果發(fā)現(xiàn)視頻非??◣手挥袀€(gè)位數(shù)。這是因?yàn)闃I(yè)務(wù)邏輯沒優(yōu)化。YOLOv5 的默認(rèn)推理方式是每幀調(diào)用一次完整前向傳播而視頻每秒鐘有 20-30 幀對(duì) GPU 的消耗非常大。簡(jiǎn)單的優(yōu)化手段是跳幀檢測(cè)不是每一幀都做檢測(cè)而是每隔幾幀檢測(cè)一次比如每 3 幀檢測(cè)一次。這個(gè)策略對(duì)大部分場(chǎng)景完全夠用畢竟目標(biāo)不會(huì)在 100 毫秒內(nèi)憑空消失。另外檢測(cè)前把輸入圖片縮放到更小的尺寸也能顯著提速比如從 640 降到 416幀率能提升一半以上精度下降卻不太明顯。6. 模型導(dǎo)出從 PyTorch 到 ONNX部署前的最后一步模型訓(xùn)練好、驗(yàn)證好真正要落地到生產(chǎn)環(huán)境還需要做模型導(dǎo)出。YOLOv5 官方提供了一鍵導(dǎo)出功能支持導(dǎo)出為 ONNX、TorchScript、TensorRT 等格式。把這一步講清楚是因?yàn)楹芏嗳嗽凇芭芡z測(cè)”之后卡在了部署模型在開發(fā)機(jī)上運(yùn)行良好換一臺(tái)機(jī)器換成其他框架就完全跑不起來了。6.1 ONNX 導(dǎo)出跨平臺(tái)部署的標(biāo)準(zhǔn)動(dòng)作ONNXOpen Neural Network Exchange是一種跨框架的模型中間表示格式可以理解成“模型界的通用語言”。導(dǎo)出 ONNX 的步驟如下python export.py --weights runs/train/exp/weights/best.pt --include onnx --img 640導(dǎo)出的文件叫best.onnx放在權(quán)重同目錄下。之后你可以用 ONNX Runtime 加載它在完全不依賴 PyTorch 的環(huán)境下運(yùn)行import onnxruntime as ort import numpy as np import cv2 sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name img cv2.imread(test.jpg) img cv2.resize(img, (640, 640)) img img[:, :, ::-1].transpose(2, 0, 1) # BGR - RGB, HWC - CHW img np.ascontiguousarray(img, dtypenp.float32) / 255.0 img np.expand_dims(img, axis0) outputs sess.run(None, {input_name: img})ONNX 導(dǎo)出的最大價(jià)值在于部署靈活性你的模型現(xiàn)在可以被 C、Java、C# 等任意語言調(diào)用可以部署在云服務(wù)器也可以部署在邊緣設(shè)備完全繞開了 Python 和 PyTorch 的依賴。6.2 導(dǎo)出時(shí)的常見問題動(dòng)態(tài)尺寸和結(jié)果解析差異導(dǎo)出和使用 ONNX 時(shí)有兩個(gè)容易踩的坑。第一個(gè)坑是輸入尺寸固定問題。默認(rèn)情況下導(dǎo)出時(shí)指定的--img 640會(huì)把模型的輸入尺寸固定為 640x640。如果你需要用其他尺寸推理可以在導(dǎo)出時(shí)加上--dynamic讓 ONNX 模型支持動(dòng)態(tài)輸入尺寸但要注意動(dòng)態(tài)尺寸的推理速度通常會(huì)略慢一些。第二個(gè)坑是輸出解析差異。PyTorch 推理時(shí)results.xyxy已經(jīng)幫你把預(yù)測(cè)結(jié)果解析成了好理解的左上角右下角坐標(biāo)。但 ONNX 模型的原始輸出是一個(gè)高維數(shù)組需要你自己解析邊界框、置信度和類別。這個(gè)過程涉及 NMS非極大值抑制比較復(fù)雜。我建議新手不要改動(dòng) YOLOv5 的推理倉(cāng)庫直接復(fù)用官方提供的models/experimental.py或者用輔助工具庫處理可以少掉很多頭發(fā)。6.3 TensorRT 導(dǎo)出極致推理速度的一條小路如果你的部署環(huán)境是 NVIDIA 的 GPU那 TensorRT 是繞不開的加速手段。它可以對(duì)模型做層融合和精度校準(zhǔn)FP16/INT8推理速度通常能提升兩到三倍。導(dǎo)出命令也很簡(jiǎn)單python export.py --weights runs/train/exp/weights/best.pt --include engine --half--half表示使用半精度 FP16推理速度更快顯存占用更少。但要注意TensorRT 導(dǎo)出的.engine文件是與 GPU 型號(hào)強(qiáng)相關(guān)的在 A 卡上導(dǎo)出的引擎不一定能在 B 卡上運(yùn)行換機(jī)器必須重新導(dǎo)出。7. 訓(xùn)練效果提升數(shù)據(jù)與超參數(shù)的幾個(gè)實(shí)用調(diào)整思路安裝、訓(xùn)練、檢測(cè)、導(dǎo)出全流程已經(jīng)跑通。最后我想分享一些我長(zhǎng)期使用 YOLOv5 后總結(jié)的提效經(jīng)驗(yàn)這些不是官方文檔里會(huì)寫的東西但確實(shí)能幫你少走彎路。7.1 數(shù)據(jù)質(zhì)量比模型參數(shù)更重要如果把 YOLOv5 用的時(shí)間拉長(zhǎng)到幾個(gè)項(xiàng)目你會(huì)發(fā)現(xiàn)一個(gè)規(guī)律數(shù)據(jù)集質(zhì)量決定了精度的上限模型參數(shù)只是逼近這個(gè)上限。同一個(gè)模型我用質(zhì)量差的數(shù)據(jù)集訓(xùn)練到 mAP 0.6 后無論如何調(diào)參都上不去換成清洗過得當(dāng)?shù)臄?shù)據(jù)后不做任何調(diào)整精度直接沖到 0.92。差距不在模型在數(shù)據(jù)。所以當(dāng)精度不理想時(shí)第一反應(yīng)不應(yīng)該是網(wǎng)上找各種魔改模型而是回頭檢查數(shù)據(jù)標(biāo)注框貼合度、誤標(biāo)漏標(biāo)、類別平衡、場(chǎng)景多樣性把這些做扎實(shí)之后再考慮參數(shù)優(yōu)化。7.2 數(shù)據(jù)增強(qiáng)的克制使用YOLOv5 自帶了相當(dāng)豐富的數(shù)據(jù)增強(qiáng)策略比如隨機(jī)翻轉(zhuǎn)、縮放、拼接Mosaic等。理解這些增強(qiáng)策略之后有一個(gè)常見的錯(cuò)誤是為了追求“更強(qiáng)的泛化性”人為把增強(qiáng)參數(shù)拉滿結(jié)果訓(xùn)練出來的模型在驗(yàn)證集上表現(xiàn)極差。增強(qiáng)要適度。訓(xùn)練小數(shù)據(jù)集時(shí)建議保留默認(rèn)增強(qiáng)策略即可不要做太多自定義改動(dòng)。真實(shí)世界的項(xiàng)目場(chǎng)景優(yōu)先保證驗(yàn)證集和測(cè)試集與部署環(huán)境盡量一致而不是指望數(shù)據(jù)增強(qiáng)能彌補(bǔ)數(shù)據(jù)分布差異。7.3 遷移學(xué)習(xí)里的“凍結(jié)訓(xùn)練”技巧如果項(xiàng)目里可用的標(biāo)注數(shù)據(jù)很少比如幾百?gòu)埧梢钥紤]先凍結(jié)主干網(wǎng)絡(luò)、只訓(xùn)練檢測(cè)頭等 loss 穩(wěn)定后再解凍全部層訓(xùn)練。YOLOv5 里可以直接通過--freeze參數(shù)指定凍結(jié)前多少層python train.py --img 640 --batch 16 --epochs 50 --data datasets/mydata/data.yaml --weights yolov5s.pt --freeze 10這種做法在數(shù)據(jù)量有限時(shí)能有效避免過擬合因?yàn)轭A(yù)訓(xùn)練主干網(wǎng)絡(luò)已經(jīng)學(xué)到過通用的視覺特征你只需要讓它適配你當(dāng)前任務(wù)的檢測(cè)邏輯。等第一階段訓(xùn)練完畢去掉--freeze參數(shù)再繼續(xù)訓(xùn)練完整模型泛化效果通常比直接完整訓(xùn)練好不少。我最近一個(gè)項(xiàng)目就是用這個(gè)思路在只有 700 多張圖片的情況下把一個(gè)小目標(biāo)檢測(cè)場(chǎng)景的 mAP 從 0.67 拉到了 0.85而且訓(xùn)練時(shí)間比從頭完整訓(xùn)練還短。如果你的數(shù)據(jù)集不大這個(gè)技巧值得認(rèn)真試試。8. 寫在最后的一點(diǎn)體會(huì)YOLOv5 這個(gè)東西網(wǎng)上教程多如牛毛動(dòng)不動(dòng)號(hào)稱“超詳細(xì)”但大部分都停留在 command 復(fù)述層面。真正讓你成長(zhǎng)的是理解每一步操作背后的原因?yàn)槭裁从媚莻€(gè)倉(cāng)庫、為什么數(shù)據(jù)集要這么放、為什么調(diào)那個(gè)參數(shù)以及精度不行時(shí)從哪下手排查。我在實(shí)際使用中還有一個(gè)習(xí)慣每次訓(xùn)練完都會(huì)在runs/train/目錄外另存一份訓(xùn)練配置副本包括data.yaml、訓(xùn)練命令參數(shù)和best.pt的 mAP 指標(biāo)。這樣一個(gè)月后回頭想調(diào)模型時(shí)不用靠記憶猜當(dāng)時(shí)怎么訓(xùn)的直接翻記錄就能完整復(fù)現(xiàn)。這個(gè)習(xí)慣看起來不起眼但對(duì)長(zhǎng)期維護(hù)模型幫助極大。另外如果你打算把 YOLOv5 用到自己的業(yè)務(wù)里建議嚴(yán)格控制版本不要頻繁升級(jí)項(xiàng)目倉(cāng)庫。它本身已經(jīng)非常成熟不會(huì)因?yàn)樾鹿δ茴l繁變動(dòng)而給你帶來額外收益。用熟一個(gè)版本、吃透一套流程比天天追新版本更重要。這是我看過無數(shù)人折騰之后最想說的一句話。