據(jù)集:快遞包裹缺陷檢測從推理到微調(diào)實戰(zhàn))
簡介面向快遞包裹與包裝盒質(zhì)檢的YOLOv10缺陷檢測權(quán)重包模型已訓(xùn)練完成可直接加載權(quán)重進行推理檢測適配物流分揀、倉儲品控等自動外觀缺陷識別場景。附帶1200多張快遞包裹與包裝盒缺陷檢測數(shù)據(jù)集已劃分train、val、test目錄配置好data.yamltxt格式標(biāo)簽也可供YOLOv5、YOLOv7、YOLOv8、YOLOv9等算法復(fù)用訓(xùn)練。資源共2000個文件主體為982個txt標(biāo)注與1002個xml標(biāo)注配合15個說明文檔和1個Python腳本壓縮包76.86MB結(jié)構(gòu)清晰便于快速接入。目前已有121人學(xué)習(xí)下載。拿到后可立即用于實際檢測驗證也能借助現(xiàn)成數(shù)據(jù)集與配置繼續(xù)微調(diào)訓(xùn)練減少數(shù)據(jù)整理和適配工作量適合有一定目標(biāo)檢測基礎(chǔ)的開發(fā)者直接上手。1. 為什么“1200 多張圖 訓(xùn)練好的權(quán)重”夠直接上產(chǎn)線試跑快遞包裹和包裝盒的缺陷檢測聽起來是個小眾方向但干過物流自動化和制造業(yè)質(zhì)檢的人都知道它比想象中更常被問到破損、壓痕、污漬、封口不良、膠帶異常這些缺陷形態(tài)雜、背景亂、光照不穩(wěn)定通用目標(biāo)檢測模型直接拿來用經(jīng)常是訓(xùn)練出來一堆框、實際漏檢一片。而 YOLOv10 算法配合已經(jīng)訓(xùn)練好的權(quán)重和 1200 多張缺陷檢測數(shù)據(jù)集正好解決了這個尷尬——你不需要從零開始標(biāo)數(shù)據(jù)、跑幾百輪訓(xùn)練才能看到效果拿到權(quán)重先跑通推理確認(rèn)邊界后再決定要不要微調(diào)。這篇文章就圍繞這套東西講清楚三件事拿到權(quán)重和數(shù)據(jù)集后該怎么盤、怎么推理、怎么用這批數(shù)據(jù)重新微調(diào)以及快遞包裹場景下那些最容易翻車的坑。2. 拿到權(quán)重和數(shù)據(jù)集后先盤清楚目錄結(jié)構(gòu)、標(biāo)注格式與模型文件的實際約束2.1 1200 多張圖在這個量級意味著什么1200 多張圖在制造業(yè)缺陷檢測數(shù)據(jù)集里屬于“中小樣本”。像 COCO、DOTA 那種幾萬張的大數(shù)據(jù)集訓(xùn)練策略可以很奔放但 1200 張圖如果還分了六七個缺陷類別平均每個類別可能只有一兩百個實例這時候最怕的不是模型容量不夠而是過擬合和類別不均衡。不過對這個項目來說1200 張圖不是用來從零訓(xùn)練的它有兩個實際作用一是配合已經(jīng)訓(xùn)練好的權(quán)重做驗證確認(rèn)模型在你自己拍的樣圖上表現(xiàn)如何二是給你一個“數(shù)據(jù)集參照物”照它的目錄結(jié)構(gòu)和標(biāo)注格式去整理自己的數(shù)據(jù)。YOLO 格式的數(shù)據(jù)集目錄結(jié)構(gòu)通常長這樣express_defect/ ├── data.yaml ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/每張 images/train/xxx.jpg 圖片對應(yīng)一個同名 txt 文件放在 labels/train/xxx.txt 里。這個 txt 的每一行代表一個目標(biāo)格式固定類別 ID、歸一化后的中心點 x、中心點 y、歸一化后的寬和高。舉個例子一行內(nèi)容是2 0.4531 0.7281 0.2344 0.1875含義就是“類別 ID 為 2 的目標(biāo)中心點在圖像寬度的 45.31%、高度的 72.81% 處寬度占整張圖的 23.44%高度占 18.75%”。拿到手之后我建議先別急著推理花十分鐘確認(rèn)三件事第一txt 文件里的類別 ID 是否連續(xù)、是否從 0 開始第二每個類別下的實例數(shù)量是否均衡如果有類別只有十幾條標(biāo)注后面推理時它的置信度基本不會高第三訓(xùn)練集和驗證集圖片是否有重疊有些人整理數(shù)據(jù)時圖省事把同一批圖既放 train 又放 val會導(dǎo)致驗證指標(biāo)虛高這個后面坑很大。2.2 權(quán)重文件怎么接進你的環(huán)境版本與加載細(xì)節(jié)標(biāo)題里說了“模型已經(jīng)訓(xùn)練好可以直接推理檢測”所以核心交付物大概率是一個或多個 pt 后綴的權(quán)重文件。在 ultralytics 框架里訓(xùn)練結(jié)束后 runs/detect/train 目錄下會同時生成 best.pt 和 last.ptbest.pt 是驗證集上指標(biāo)最好的那一個last.pt 是最后一輪的權(quán)重。如果你的壓縮包里兩個文件都有日常推理用 best.pt想接著訓(xùn)練用 last.pt這是默認(rèn)的省心做法。加載權(quán)重時要注意 PyTorch 版本和 ultralytics 版本的匹配。YOLOv10 是在 2024 年 5 月隨著 ultralytics 框架更新被集成的如果你的 ultralytics 版本太老直接加載會報 key 不匹配或直接拋異常。我的習(xí)慣是先把 ultralytics 升到當(dāng)前最新版再加載權(quán)重如果項目環(huán)境不允許升級至少保證 PyTorch 1.8 以上Python 3.8 以上這是 YOLOv10 能跑起來的最低基礎(chǔ)。另外 YOLOv10 和 YOLOv8 的模型結(jié)構(gòu)有差異v10 用了無 NMS 的端到端推理模型內(nèi)部通過 dual head 分配策略和 one-to-one head 直接輸出最終檢測框不再需要像 v8 那樣做 NMS 后處理。這個差異帶來一個實際好處導(dǎo)出 ONNX 后部署邏輯更簡單推理鏈路上少一個超參數(shù)NMS IoU 閾值需要調(diào)。而你拿到的這份權(quán)重如果當(dāng)初是用 YOLOv10 結(jié)構(gòu)訓(xùn)練的注意不要拿它硬套 YOLOv8 的部署腳本輸出張量的解析方式不一樣細(xì)節(jié)在第 5 章的坑里展開。2.3 拿到壓縮包后的檢查清單每類項目交付物的整理習(xí)慣不太一樣但按下面的表檢查一遍能避免很多低級問題。下表是常見檢查項建議逐條對照你手里的文件確認(rèn)檢查項關(guān)注點檢查方法images 與 labels 目錄結(jié)構(gòu)是否按 train/val 分好用文件管理器直接看目錄層級標(biāo)簽與圖片對應(yīng)關(guān)系每張圖是否都有同名 txt寫腳本統(tǒng)計 images 數(shù)量與 labels 數(shù)量是否一致類別 names 順序names 列表與 txt 中 ID 是否一致打開 data.yaml 與任意一個 txt 對照驗證集規(guī)模val 占總圖比例是否合理一般不低于 10%低于 5% 時指標(biāo)水分大權(quán)重文件完整性best.pt 能否被 torch.load 加載跑一次 yolo detect predict 試推理是否附帶 data.yaml后續(xù)微調(diào)直接復(fù)用沒有 yaml 時按第 4 章自己創(chuàng)建這六項里最容易出錯的是第三項。很多人訓(xùn)練時改過類別順序但沒有同步修改已有標(biāo)注文件導(dǎo)致模型推斷出的類別名和實際標(biāo)注對不上。拿到權(quán)重后先跑一張圖看看輸出的類別名是否符合預(yù)期再批量跑別一上來就全量推理。3. 一條命令跑通推理從命令行到 Python API 的參數(shù)取舍3.1 最小推理命令先跑通再談優(yōu)化如果是第一次接觸這套權(quán)重我強烈建議先用命令行跑通一張圖出結(jié)果后再上 Python API。命令行方式代碼少、參數(shù)透明出問題也好排查。在虛擬環(huán)境里安裝好 ultralytics 之后進入權(quán)重和測試圖片所在目錄執(zhí)行yolo detect predict \ modelbest.pt \ source./test_images/demo.jpg \ conf0.25 \ iou0.7 \ imgsz640 \ saveTrue這條命令的意思是把 best.pt 加載進來對 demo.jpg 做預(yù)測置信度閾值 0.25IoU 閾值 0.7輸入圖像尺寸 640預(yù)測結(jié)果畫框后保存到 runs/detect/predict 目錄。第一次跑通后把 source 參數(shù)換成一張包含多個包裹、有重疊、有光照反光的現(xiàn)場圖看框的位置和置信度分布是否合理。如果圖片路徑是個目錄ultralytics 會遍歷整個目錄做推理。這一步驗證有兩個目的一是確認(rèn)權(quán)重能正常加載、輸出也沒問題二是評估這套權(quán)重對你實際場景的適應(yīng)程度。如果一個典型的破損包裹圖沒有一個框的置信度超過 0.5那基本可以判斷訓(xùn)練數(shù)據(jù)里的場景和你的現(xiàn)場差異較大后續(xù)需要微調(diào)而不是直接部署。3.2 Python API 推理把框取出來變成自己的業(yè)務(wù)數(shù)據(jù)命令行適合驗證但真正接產(chǎn)線或者做批量后處理還是要用 Python API。YOLOv10 作為 ultralytics 家族的成員推理接口和 YOLOv8 完全一致以下代碼是一個可以直接改的最小模板from ultralytics import YOLO # 加載訓(xùn)練好的權(quán)重路徑可以是絕對路徑或相對路徑 model YOLO(best.pt) # 對單張圖片做推理conf/iou/imgsz 與命令行參數(shù)一一對應(yīng) results model.predict( sourcetest_images/demo.jpg, conf0.25, iou0.7, imgsz640, device0, # 用 0 號 GPU沒有 GPU 就填 cpu saveFalse, # 先用 False自己控制保存邏輯 verboseFalse, # 關(guān)掉逐張打印批量時日志更干凈 ) # results 是列表每個元素對應(yīng) source 里的一個輸入 for r in results: boxes r.boxes print(檢測到, len(boxes), 個目標(biāo)) for box in boxes: cls_id int(box.cls[0]) # 類別 ID name model.names[cls_id] # 類別名從權(quán)重自帶 names 里取 conf float(box.conf[0]) # 該框的置信度 x1, y1, x2, y2 box.xyxy[0].tolist() # 框的左上角與右下角坐標(biāo) print(f{name} {conf:.3f} ({x1:.1f}, {y1:.1f}, {x2:.1f}, {y2:.1f}))這個模板里的關(guān)鍵點是model.names 不是從外部配置文件讀的而是權(quán)重文件內(nèi)部攜帶的類別名列表。也就是說你不需要手動維護一個類別名數(shù)組只要權(quán)重文件是正確的names 就自動對得上。如果你在推理時打印出的類別名和預(yù)期不符那問題一定出在訓(xùn)練時 data.yaml 的 names 順序上和第 2 章提到的檢查項呼應(yīng)。批量推理時要注意內(nèi)存控制。如果一次傳入幾百張圖片的路徑列表ultralytics 內(nèi)部會根據(jù) batch 參數(shù)自動分批但默認(rèn)情況下一張一張跑是最穩(wěn)的。我做批量壓測時會先跑 50 張、觀察顯存占用穩(wěn)定后再加大輸入規(guī)模。3.3 推理參數(shù)怎么調(diào)conf、iou、imgsz 的取舍這四個參數(shù)幾乎決定了你部署后的體驗它們之間是聯(lián)動的不能孤立地調(diào)。直接用下表做參考再結(jié)合你自己的業(yè)務(wù)邏輯定值參數(shù)默認(rèn)值調(diào)低的影響調(diào)高的影響快遞包裹場景建議conf0.25召回提升誤檢變多輸出框變密漏檢變多但剩下的框更可信先 0.25 看全貌再按現(xiàn)場接受度調(diào) 0.3~0.5iou0.7相鄰框更容易被合并重復(fù)框變少重復(fù)框變多但不會吞掉小目標(biāo)包裹重疊嚴(yán)重時降到 0.5imgsz640推理變快小缺陷可能丟失小目標(biāo)壓痕、小破洞更容易檢出有細(xì)微信號時先試 1280再評估速度max_det300輸出目標(biāo)數(shù)上限上限越高越不容易漏目標(biāo)包裹密集時調(diào)到 400imgsz 是被低估的一個參數(shù)。訓(xùn)練時用的什么尺寸推理時最好用同樣尺寸如果你把訓(xùn)練時 640 的模型拿到 1280 上推理理論上對但實際會改變特征金字塔的感受野分布小目標(biāo)的檢出能力提高的同時一些原本被抑制的背景噪聲也會被放大。所以改 imgsz 之前先確認(rèn)訓(xùn)練時的 imgsz能查訓(xùn)練結(jié)果的 results.csv 或保存的配置文件就不難確認(rèn)。如果確認(rèn)不了先用默認(rèn) 640再用 1280 做 A/B 對比看現(xiàn)場最關(guān)鍵的那類缺陷檢出率變化。4. 用你自己的數(shù)據(jù)重新微調(diào)yaml 文件、訓(xùn)練命令與輸出權(quán)重怎么讀4.1 整理自己的標(biāo)注數(shù)據(jù)把圖片和標(biāo)簽組織成 YOLO 格式前面說過1200 多張數(shù)據(jù)集的價值之一是作為整理自有數(shù)據(jù)的參照?,F(xiàn)實中你從產(chǎn)線拿到的往往是手機拍的、工業(yè)相機拍的、監(jiān)控截取的各種格式圖片標(biāo)注工具可能是 LabelImg、labelme 或者 X-AnyLabeling。最終都要轉(zhuǎn)成上面第 2 章描述的 YOLO 目錄結(jié)構(gòu)。轉(zhuǎn)換這一步最常見的錯誤是標(biāo)注框坐標(biāo)沒有歸一化。YOLO 格式要求 x_center、y_center、w、h 全部除以圖片寬高轉(zhuǎn)成 0 到 1 之間的小數(shù)而不是像素值。如果從 labelme 的 JSON 里把 polygon 或 rectangle 的絕對坐標(biāo)直接寫進 txt訓(xùn)練時 loss 會異常大、模型完全學(xué)不進去。寫轉(zhuǎn)換腳本時核心代碼就幾句話import json with open(annotation.json) as f: ann json.load(f) img_w ann[imageWidth] img_h ann[imageHeight] for shape in ann[shapes]: label shape[label] x1, y1 shape[points][0] x2, y2 shape[points][1] # 修正左上角/右下角順序 x_min, x_max sorted([x1, x2]) y_min, y_max sorted([y1, y2]) # 轉(zhuǎn)成 YOLO 歸一化格式 x_center ((x_min x_max) / 2) / img_w y_center ((y_min y_max) / 2) / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h print(label, round(x_center, 6), round(y_center, 6), round(w, 6), round(h, 6))另一個容易被忽略的點是“空標(biāo)簽圖”。如果某張圖確實沒有缺陷它可以不帶 txt 文件ultralytics 會把它當(dāng)作負(fù)樣本不會報錯。但如果所有圖片都沒有標(biāo)簽訓(xùn)練會直接卡在 “No labels found” 的警告上幾千張圖白跑。我一般會在整理完后寫一個校驗?zāi)_本統(tǒng)計所有圖片對應(yīng) txt 的行數(shù)分布類別分布以及檢查每條標(biāo)注的寬高是否小于等于 0、中心點坐標(biāo)是否超出 0~1 范圍把臟數(shù)據(jù)提前清掉。4.2 yolov10 yaml 文件怎么創(chuàng)建目錄與類別名的映射在 ultralytics 框架里訓(xùn)練自定義數(shù)據(jù)集yaml 文件是唯一的數(shù)據(jù)入口。它不需要多復(fù)雜卻要求所有字段都準(zhǔn)確。下面是一個以快遞包裹缺陷為例的 yaml 模板names 列表要和你的標(biāo)簽 ID 嚴(yán)格對應(yīng)# express_defect.yaml # path 指向數(shù)據(jù)集根目錄建議用絕對路徑避免換目錄后找不到數(shù)據(jù) path: D:/datasets/express_defect # train 和 val 是相對 path 的目錄 train: images/train val: images/val # 類別數(shù)量必須與 names 長度一致 nc: 6 # names 順序決定 txt 里類別 ID 的含義 names: 0: break 1: dent 2: stain 3: wrinkle 4: tape_abnormal 5: unsealed創(chuàng)建 yaml 文件時最容易踩的坑是 path 用了相對路徑。如果你執(zhí)行訓(xùn)練命令的終端目錄和數(shù)據(jù)目錄不在同一層級fill 相對路徑大概率報 FileNotFoundError。我的習(xí)慣是直接寫絕對路徑macOS/Linux 寫/Users/xxx/datasets/express_defectWindows 寫D:/datasets/express_defect正斜杠和反斜杠在 ultralytics 里都能識別但正斜杠更保險。另外 nc 的值如果和 names 個數(shù)不一致訓(xùn)練不會報錯但驗證時會發(fā)現(xiàn)你期望的類別 ID 和模型輸出的 ID 錯位——這個錯位最隱蔽因為測試集上 mAP 可能還挺高但部署時類別名全反了。4.3 微調(diào)命令在別人權(quán)重基礎(chǔ)上繼續(xù)訓(xùn)練1200 多張圖直接從頭訓(xùn)練不劃算最可靠的做法是加載一個預(yù)訓(xùn)練權(quán)重再在這個基礎(chǔ)上微調(diào)。如果你只是想加快收斂用官方提供的 YOLOv10 預(yù)訓(xùn)練權(quán)重比如 yolov10s.pt、yolov10m.pt下載后放到當(dāng)前目錄命令里直接指定路徑。如果你覺得別人訓(xùn)練好的這個快遞包裹權(quán)重對你的場景已經(jīng)比較接近也可以拿它作為起點接著訓(xùn)效果通常比從 COCO 預(yù)訓(xùn)練開始更好但前提是類別定義和它一致。下面是一套適合 1200 張左右數(shù)據(jù)量級的訓(xùn)練命令參數(shù)yolo detect train \ dataexpress_defect.yaml \ modelyolov10s.pt \ epochs120 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ freeze10 \ close_mosaic10 \ ampTrue \ patience30逐項說下為什么這么設(shè)。模型用 yolov10s 是因為快遞包裹缺陷里破損和污漬這類目標(biāo)大小差異很大但整體不算極端小目標(biāo)s 級能平衡精度和顯存只有幾百兆顯存的舊顯卡換成 yolov10n推理精度會略降但速度更快訓(xùn)練時長也明顯縮短。epochs 設(shè) 120 是因為 1200 張圖在小數(shù)據(jù)集上 60 到 100 輪基本收斂120 是留出余量配合早停機制patience30 表示驗證集指標(biāo)連續(xù) 30 輪不提升就自動停止。freeze10 表示凍結(jié)模型前 10 層參數(shù)這個在小數(shù)據(jù)集上是防過擬合非常有效的常規(guī)操作——主干網(wǎng)絡(luò)底層學(xué)的是邊緣、紋理這類通用特征凍結(jié)它們讓訓(xùn)練只更新后層能明顯緩解 val loss 與 train loss 差距過大的問題。close_mosaic10 表示最后 10 個 epoch 關(guān)閉 mosaic 增強因為 mosaic 會切碎圖片、引入大量拼接邊界長期開著會讓模型學(xué)到奇怪的偽影后段關(guān)掉再精調(diào)幾輪是 YOLO 系列訓(xùn)練里常見做法。4.4 訓(xùn)練輸出怎么讀best.pt、last.pt 與 results.csv訓(xùn)練結(jié)束后runs/detect/train 目錄下會有一批文件真正有用的三樣是 best.pt、last.pt 和 results.csv。results.csv 是每一輪的訓(xùn)練指標(biāo)打開后可以看到 train 和 val 兩套 loss以及 precision、recall、mAP50、mAP50-95 等指標(biāo)曲線。判斷訓(xùn)練有沒有出問題先看 val mAP50 是不是穩(wěn)步上升再對比 train loss 和 val loss 的走勢如果 train loss 一路下降但 val loss 在某個 epoch 后掉頭向上就是過擬合的典型信號。關(guān)于選權(quán)重我平時主要看兩個維度一是 val mAP50 峰值在哪個 epoch 附近二是 val loss 最低點在哪個 epoch。如果兩者不一致優(yōu)先選 val loss 最低點對應(yīng)的那輪權(quán)重因為 mAP 只統(tǒng)計置信度閾值下的匹配結(jié)果而 val loss 衡量的是整個分布的擬合程度后者在真實場景里往往更穩(wěn)。確認(rèn)權(quán)重文件名不用改best.pt 在訓(xùn)練結(jié)束后就是按指標(biāo)選出來的直接拿去推理就可以。5. 避坑快遞包裹檢測最容易翻車的 5 個環(huán)節(jié)5.1 現(xiàn)象驗證集指標(biāo)還可以一到產(chǎn)線新批次漏檢一片原因驗證集圖片是從訓(xùn)練數(shù)據(jù)里按比例抽出來的和訓(xùn)練集共享同一批相機、同一批光照條件、同一種擺放方式指標(biāo)自然好看。但產(chǎn)線環(huán)境換一條皮帶線、換一個光源角度背景紋理和反射特征就變了模型的泛化能力跟不上。解決不要只依賴訓(xùn)練時的 val 指標(biāo)單獨留一份“現(xiàn)場壓測集”。從目標(biāo)部署位置重新拍 100 到 200 張圖包含不同時間段、不同光照強度、不同包裹破損程度這份數(shù)據(jù)不參與訓(xùn)練只用來做最終評估。如果壓測集上的 mAP50 比訓(xùn)練 val 低 0.2 以上說明現(xiàn)場跟訓(xùn)練分布差距太大需要采集現(xiàn)場圖做增量微調(diào)。這一步?jīng)]做好部署再快都是白搭。5.2 現(xiàn)象明顯的破洞和壓痕在圖上清清楚楚模型就是檢不出來原因這類缺陷在整張圖中占的像素比例太小。如果一張 1920x1080 的現(xiàn)場圖里破損區(qū)域只有 40x50 像素輸入 imgsz640 縮放后缺陷可能只剩下十幾個像素經(jīng)過幾次下采樣特征圖里基本就丟了。解決先用 imgsz1280 試通常能顯著提升小缺陷召回。還不夠的話用 SAHI 這類切片推理工具把大圖切成 640x640 的重疊小塊分別推理再合并結(jié)果缺陷相對尺寸變大檢出率提升明顯。代價是推理時間翻倍但對離線抽檢和產(chǎn)線慢速輸送場景完全夠用。注意切片重疊率設(shè)個 0.2 就夠了太高會引入大量重復(fù)檢測框。5.3 現(xiàn)象想把模型接進 OpenCV 的現(xiàn)有缺陷檢測流程加載 ONNX 后取不到框原因OpenCV DNN 模塊的通用 YOLO 后處理腳本大多是為 YOLOv5/v8 的多個輸出頭寫的會去解析三個尺度的特征圖輸出。而 YOLOv10 無 NMS 的設(shè)計導(dǎo)出的 ONNX 輸出是一個固定的端到端檢測結(jié)果張量格式是 (1, 300, 6) 這樣的候選框數(shù)組每一行是 x1、y1、x2、y2、score、cls沒有三個輸出的分支直接用舊的 decode 邏輯解析當(dāng)然拿不到框。解決先在 OpenCV 里把輸出張量的形狀打印出來確認(rèn)是端到端格式后寫一段新的后處理取前 N 行按置信度過濾跳過無效行。如果不想自己解析更省事的是用 onnxruntime 配合 ultralytics 官方示例里的 YOLOv10 解碼代碼。說句實在話除非你的平臺只能跑 OpenCV DNN否則推薦用 onnxruntime它的算子和速度控制更好部署心智負(fù)擔(dān)也更小。5.4 現(xiàn)象訓(xùn)練一輪下來 loss 降了但 val mAP50 始終在 0.3 以下原因除了數(shù)據(jù)量本身小之外最常見的是數(shù)據(jù)增強配置和閥值設(shè)定不匹配。1200 張圖把 mosaic 增強開到默認(rèn) 1.0每張訓(xùn)練圖里可能有四張圖拼接導(dǎo)致大量訓(xùn)練樣本帶有拼接邊界模型學(xué)到的目標(biāo)邊界是“斷裂”的另外小數(shù)據(jù)集內(nèi)部如果 train/val 劃分不當(dāng)驗證集里包含了和訓(xùn)練集高度相似的圖片val loss 和 mAP 也會互相扯后腿。解決調(diào)低增強強度。mosaic 從 1.0 降到 0.3 到 0.5close_mosaic 提前到第 20 到第 30 個 epoch給模型一段“干凈”的收斂期同時把 hsv_h、hsv_s、hsv_v 這些顏色增強適當(dāng)調(diào)大??爝f包裹的塑料表面和紙箱對顏色變化非常敏感適當(dāng)增強顏色抖動反而能提升泛化。如果調(diào)完一輪后 mAP50 還上不去回頭檢查 labels 里的標(biāo)注是否有多余的重疊框或者某些類別本身實例數(shù)太少合并掉不足 20 個實例的類別通常能讓整體指標(biāo)明顯抬升。5.5 現(xiàn)象best.pt 與 last.pt 差距巨大線上表現(xiàn)像“黑匣子”原因best.pt 是在驗證集上按 mAP 選出來的驗證集本身不能代表現(xiàn)場分布這兩者差距大說明訓(xùn)練過程里模型波動嚴(yán)重最后的權(quán)重選擇策略更多是“矮子里拔將軍”。如果連 doctored 的 val 都不能穩(wěn)住更別提線上穩(wěn)定運行了。解決把訓(xùn)練收斂節(jié)奏調(diào)穩(wěn)而不是追求峰值。訓(xùn)練結(jié)束后不要只看 best.pt把 last.pt 也拿到壓測集上跑一遍如果兩者差異大說明這是模型本身對某些類別的不穩(wěn)定表現(xiàn)而不是權(quán)重文件的問題。如果時間允許可以把 epochs 提高到 180配合早停讓模型在更多 epochs 里尋找穩(wěn)定解最后再選 val loss 最低的幾個 epoch 的權(quán)重做集成平均。這個經(jīng)驗是實打?qū)崗漠a(chǎn)線上磨出來的單點指標(biāo)的峰值往往不可靠穩(wěn)定解才是能交付的解。6. 進階先做批量壓測再談 ONNX 與 TensorRT 部署權(quán)重拿到手、推理也跑通了這時候最容易犯的錯誤是拿幾張好看的圖就去匯報效果。我會建議先做一次批量壓測把真實的表現(xiàn)量化出來。做法很簡單準(zhǔn)備 200 到 500 張覆蓋不同缺陷類型和不同背景的樣圖循環(huán)推理統(tǒng)計每類的檢出數(shù)量、平均置信度、單幀耗時把結(jié)果輸出成 JSON 存檔。from ultralytics import YOLO from pathlib import Path import json, time model YOLO(best.pt) image_paths [str(p) for p in Path(batch_images).glob(*.jpg)] t0 time.time() results model.predict( sourceimage_paths, conf0.35, imgsz640, device0, verboseFalse, ) total_time time.time() - t0 records [] for impath, r in zip(image_paths, results): objs [] for box in r.boxes: objs.append({ cls: model.names[int(box.cls[0])], conf: float(box.conf[0]), box: [float(v) for v in box.xyxy[0].tolist()], }) records.append({image: impath, objects: objs}) out {total_time: total_time, fps: len(image_paths) / total_time, records: records} json.dump(out, open(batch_result.json, w), indent2)這里一次傳入所有圖片路徑ultralytics 內(nèi)部會按 batch 自動分批比循環(huán)單張調(diào)用省去大量加載開銷。壓測的目的是摸清兩個數(shù)一是 fps判斷能不能滿足產(chǎn)線節(jié)拍二是每類缺陷的檢出數(shù)量如果某個類別在整個壓測集里一框未出基本可以判定這個類別在當(dāng)前場景下不可用要回到第 4 章的微調(diào)流程去補數(shù)據(jù)。壓測集要單獨存放不要隨手從訓(xùn)練集里拷圖否則壓測結(jié)果就是第 5 章說的“自欺欺人”。批量壓測通過之后才考慮正式部署形態(tài)。YOLOv10 的端到端設(shè)計對部署很友好導(dǎo)出 ONNX 的命令是yolo export modelbest.pt formatonnx imgsz640 halfFalse dynamicFalse simplifyTrue三個參數(shù)的含義要心里有數(shù)imgsz 固定 640 而不是 dynamic是為了換取更快的推理速度和更小的顯存占用因為動態(tài)尺寸會迫使推理框架預(yù)留最大尺寸的顯存half 半精度在部分老顯卡和 edge 設(shè)備上不支持先保持 False確認(rèn)目標(biāo)平臺支持 FP16 再開simplify 用 onnxsim 簡化計算圖省略掉不必要的節(jié)點TensorRT 轉(zhuǎn)換時能省去很多算子的兼容問題。導(dǎo)出后用 onnxruntime 驗證一次輸入輸出維度和 pt 推理結(jié)果的一致性別直接扔給 TensorRT。TensorRT 轉(zhuǎn)換我一般只在延遲要求特別高的時候做??爝f包裹缺陷檢測大多不是高速動態(tài)抓拍場景ONNX 在普通 GPU 上已經(jīng)能跑到幾十毫秒一幀TensorRT 的收益集中在極端延遲敏感的流水線上如果只是產(chǎn)線抽檢完全沒必要增加這層維護成本。我現(xiàn)在的習(xí)慣是拿到任何一套訓(xùn)練好的權(quán)重先跑批量壓測打分再決定是直接部署還是回到數(shù)據(jù)側(cè)微調(diào)最后才碰導(dǎo)出和加速——這三步順序換一下往往會多走兩輪彎路。希望幫到你。本文還有配套的精品資源點擊獲取