據(jù)集:2970張VOC+YOLO雙格式,從零跑通YOLOv8訓(xùn)練)
簡介這份資源是面向計(jì)算機(jī)視覺初學(xué)者與目標(biāo)檢測工程實(shí)踐者的家禽雞只檢測數(shù)據(jù)集可用于訓(xùn)練和驗(yàn)證雞類目標(biāo)識別模型適用于課程設(shè)計(jì)、算法練手及小型養(yǎng)殖場景的智能監(jiān)測原型開發(fā)。壓縮包共約2000個(gè)文件以1999個(gè)VOC格式xml標(biāo)注文件和1個(gè)說明txt為主另含對應(yīng)的YOLO格式txt與jpg圖片整體約50.18MBxml與txt分別適配Pascal VOC和YOLO兩種主流訓(xùn)練流程方便直接接入常見檢測框架。數(shù)據(jù)集共2971張圖片標(biāo)注類別為chicken累計(jì)6358個(gè)標(biāo)注框全部由labelImg手工完成標(biāo)注質(zhì)量相對可靠。目前已有462人學(xué)習(xí)下載可作為入門目標(biāo)檢測的實(shí)戰(zhàn)素材幫助讀者快速跑通數(shù)據(jù)加載、格式轉(zhuǎn)換、模型訓(xùn)練與評估的完整鏈路并在此基礎(chǔ)上嘗試數(shù)據(jù)增強(qiáng)與類別擴(kuò)展。1. 家禽雞小雞檢測數(shù)據(jù)集2970 張 VOCYOLO 雙格式到底能干什么養(yǎng)殖場里做雛雞存活率統(tǒng)計(jì)最頭疼的不是模型選哪個(gè)而是手里根本沒有能直接喂給 YOLO 的標(biāo)注數(shù)據(jù)。網(wǎng)上公開的雞類數(shù)據(jù)集要么只有幾百張、要么只給分類標(biāo)簽不給檢測框真正能拿來訓(xùn)練目標(biāo)檢測模型的少之又少。這個(gè)標(biāo)題里的家禽雞小雞檢測數(shù)據(jù)集2970 張圖、VOC 和 YOLO 雙格式、手工標(biāo)注恰好卡在了「能直接開訓(xùn)」這個(gè)點(diǎn)上。它解決的核心問題是你不需要從零標(biāo) 3000 張雞圖拿到就能跑通訓(xùn)練流程驗(yàn)證自己的檢測方案在禽類場景下到底行不行。適合兩類人——?jiǎng)側(cè)腴T目標(biāo)檢測想找一個(gè)真實(shí)場景練手的以及做養(yǎng)殖智能化需要快速驗(yàn)證雛雞檢測可行性的工程師。手工標(biāo)注意味著框的質(zhì)量比自動(dòng)標(biāo)注靠譜VOC 和 YOLO 雙格式意味著你不用寫轉(zhuǎn)換腳本就能對接不同框架。下面從數(shù)據(jù)本身講到訓(xùn)練落地把這條鏈路走通。2. 拆開這個(gè)數(shù)據(jù)集VOC 與 YOLO 雙格式的結(jié)構(gòu)差異2.1 VOC 格式的目錄結(jié)構(gòu)與 XML 字段含義VOC 格式是目標(biāo)檢測領(lǐng)域最經(jīng)典的標(biāo)注格式之一它的組織方式是一圖一 XML。拿到數(shù)據(jù)集后你通常會(huì)看到這樣的目錄結(jié)構(gòu)dataset/ ├── JPEGImages/ # 所有原始圖片jpg 格式 │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── Annotations/ # 每張圖對應(yīng)的 XML 標(biāo)注文件 │ ├── 000001.xml │ ├── 000002.xml │ └── ... └── ImageSets/ └── Main/ ├── train.txt # 訓(xùn)練集圖片名列表不含擴(kuò)展名 ├── val.txt └── test.txt每個(gè) XML 文件里最關(guān)鍵的是object節(jié)點(diǎn)它記錄了標(biāo)注框的類別和坐標(biāo)。一個(gè)典型的 XML 長這樣annotation folderJPEGImages/folder filename000001.jpg/filename size width640/width height480/height depth3/depth /size object namechicken/name !-- 類別名 -- poseUnspecified/pose truncated0/truncated !-- 是否被截?cái)?-- difficult0/difficult !-- 是否難以識別 -- bndbox xmin112/xmin !-- 左上角 x -- ymin85/ymin !-- 左上角 y -- xmax340/xmax !-- 右下角 x -- ymax290/ymax !-- 右下角 y -- /bndbox /object /annotation這里有幾個(gè)字段值得注意。name是類別標(biāo)簽這個(gè)數(shù)據(jù)集里大概率是 chicken、chick 或者統(tǒng)一成一個(gè)類。truncated和difficult在訓(xùn)練時(shí)可以選擇性忽略——如果你想讓模型專注學(xué)清晰目標(biāo)可以把 difficult1 的框過濾掉。bndbox的坐標(biāo)是絕對像素值原點(diǎn)在左上角這是 VOC 的標(biāo)準(zhǔn)約定。注意有些數(shù)據(jù)集的 XML 里會(huì)出現(xiàn)坐標(biāo)越界的情況比如 xmax 大于圖片寬度。訓(xùn)練前一定要做一遍校驗(yàn)否則 YOLO 轉(zhuǎn)換時(shí)會(huì)直接報(bào)錯(cuò)或者生成錯(cuò)誤的標(biāo)簽。2.2 YOLO 格式的歸一化坐標(biāo)與類別索引YOLO 格式和 VOC 最大的區(qū)別在于它把每張圖的標(biāo)注寫成一個(gè) txt 文件每行一個(gè)目標(biāo)坐標(biāo)是歸一化后的中心點(diǎn)加寬高。對應(yīng)的目錄結(jié)構(gòu)通常是dataset_yolo/ ├── images/ │ ├── train/ │ │ ├── 000001.jpg │ │ └── ... │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ │ ├── 000001.txt │ │ └── ... │ ├── val/ │ └── test/ └── data.yaml # 數(shù)據(jù)集配置文件每個(gè) txt 文件的內(nèi)容格式是class_id x_center y_center width height全部是 0 到 1 之間的浮點(diǎn)數(shù)。舉個(gè)例子如果一張 640×480 的圖里有一個(gè)框VOC 坐標(biāo)是 (112, 85, 340, 290)轉(zhuǎn)成 YOLO 格式就是0 0.353125 0.390625 0.356250 0.427083計(jì)算方式x_center (112340)/2/640 0.353125y_center (85290)/2/480 0.390625width (340-112)/640 0.356250height (290-85)/480 0.427083。data.yaml是 YOLO 訓(xùn)練時(shí)的入口配置文件內(nèi)容一般長這樣path: ./dataset_yolo train: images/train val: images/val test: images/test nc: 1 names: - chickennc是類別數(shù)names是類別名列表。這個(gè)數(shù)據(jù)集如果只有雞一個(gè)類nc 就是 1。如果區(qū)分了大雞和小雞nc 就是 2names 里對應(yīng)寫 chicken 和 chick。2.3 兩種格式的選型判斷什么場景用哪個(gè)VOC 格式的優(yōu)勢在于通用性強(qiáng)。很多經(jīng)典檢測框架Faster R-CNN、SSD 的早期實(shí)現(xiàn)以及一些標(biāo)注工具LabelImg默認(rèn)就用 VOC。如果你要做格式轉(zhuǎn)換、數(shù)據(jù)分析、可視化標(biāo)注框XML 的可讀性比 txt 好得多——至少你能直接打開看到坐標(biāo)和類別名。YOLO 格式的優(yōu)勢在于訓(xùn)練效率。YOLO 系列v5、v8、v11 以及更新的版本原生吃這種格式不需要在訓(xùn)練時(shí)做在線轉(zhuǎn)換。而且歸一化坐標(biāo)對圖片縮放更友好數(shù)據(jù)增強(qiáng)時(shí)不用反復(fù)換算。我的建議是如果你確定用 YOLO 系列訓(xùn)練直接用 YOLO 格式那份省去轉(zhuǎn)換步驟。如果你還在對比不同框架或者需要做數(shù)據(jù)清洗和可視化先用 VOC 格式做分析確認(rèn)沒問題后再轉(zhuǎn) YOLO。這個(gè)數(shù)據(jù)集同時(shí)給了兩種格式省掉了很多來回折騰的時(shí)間。3. 從零跑通訓(xùn)練用 YOLOv8 在本地把雞檢測模型訓(xùn)起來3.1 環(huán)境配置與依賴安裝的版本選擇訓(xùn)練之前先把環(huán)境搭好。YOLOv8 對環(huán)境的容忍度比較高但有幾個(gè)關(guān)鍵依賴的版本需要注意。我一般用 conda 建一個(gè)獨(dú)立環(huán)境避免和系統(tǒng)里的其他包打架conda create -n chicken_det python3.10 -y conda activate chicken_det # 安裝 PyTorch根據(jù)你的 CUDA 版本選對應(yīng)命令 # CUDA 11.8 的情況 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安裝 ultralyticsYOLOv8 官方包 pip install ultralytics # 驗(yàn)證安裝 yolo checkspython3.10是我實(shí)測下來兼容性最好的版本3.11 和 3.12 也能跑但偶爾會(huì)遇到某些依賴沒有預(yù)編譯 wheel 的情況。PyTorch 的版本跟著 CUDA 走如果你沒有 GPU直接pip install torch torchvision裝 CPU 版也能跑只是訓(xùn)練速度會(huì)慢很多。yolo checks會(huì)輸出當(dāng)前環(huán)境的信息包括 PyTorch 版本、CUDA 是否可用、GPU 型號等確認(rèn)沒有報(bào)錯(cuò)再往下走。提示如果你用的是 30 系或 40 系顯卡建議 CUDA 11.8 以上。50 系顯卡需要 CUDA 12.8 以上和 PyTorch 2.7 以上版本對不上會(huì)直接報(bào) no kernel image 錯(cuò)誤。3.2 數(shù)據(jù)集目錄整理與 data.yaml 配置拿到數(shù)據(jù)集后先確認(rèn)目錄結(jié)構(gòu)符合 YOLO 訓(xùn)練的要求。如果你的數(shù)據(jù)還是 VOC 格式需要先轉(zhuǎn)成 YOLO 格式。轉(zhuǎn)換腳本可以自己寫也可以用現(xiàn)成的工具。下面是一個(gè)我常用的轉(zhuǎn)換腳本處理了坐標(biāo)越界和空標(biāo)注的情況import os import xml.etree.ElementTree as ET from pathlib import Path def voc_to_yolo(xml_dir, img_dir, output_dir, class_names): xml_dir: VOC 標(biāo)注文件夾路徑 img_dir: 圖片文件夾路徑 output_dir: 輸出 YOLO 標(biāo)簽的文件夾路徑 class_names: 類別名列表如 [chicken] os.makedirs(output_dir, exist_okTrue) skipped 0 for xml_file in Path(xml_dir).glob(*.xml): tree ET.parse(xml_file) root tree.getroot() # 獲取圖片尺寸 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in class_names: continue cls_id class_names.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 坐標(biāo)裁剪防止越界 xmin max(0, min(xmin, img_w)) ymin max(0, min(ymin, img_h)) xmax max(0, min(xmax, img_w)) ymax max(0, min(ymax, img_h)) # 跳過無效框 if xmax xmin or ymax ymin: skipped 1 continue # 轉(zhuǎn)歸一化中心點(diǎn)坐標(biāo) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) # 寫出對應(yīng)的 txt 文件 txt_path Path(output_dir) / (xml_file.stem .txt) with open(txt_path, w) as f: f.write(\n.join(lines)) print(f轉(zhuǎn)換完成跳過 {skipped} 個(gè)無效框) # 調(diào)用示例 voc_to_yolo( xml_dirdataset/Annotations, img_dirdataset/JPEGImages, output_dirdataset_yolo/labels/all, class_names[chicken] )這個(gè)腳本做了三件事讀取 XML 里的圖片尺寸和標(biāo)注框、把絕對坐標(biāo)轉(zhuǎn)成歸一化中心點(diǎn)坐標(biāo)、寫出 YOLO 格式的 txt。坐標(biāo)裁剪那幾行是血淚經(jīng)驗(yàn)——有些標(biāo)注員會(huì)不小心把框拉到圖片外面不處理的話 YOLO 訓(xùn)練時(shí)會(huì)報(bào) assert 錯(cuò)誤。skipped計(jì)數(shù)器用來統(tǒng)計(jì)被跳過的無效框數(shù)量轉(zhuǎn)換完看一眼如果跳過太多說明標(biāo)注質(zhì)量有問題。轉(zhuǎn)換完成后按 train/val/test 劃分?jǐn)?shù)據(jù)集。我一般按 8:1:1 分如果數(shù)據(jù)量少可以 7:2:1。劃分腳本很簡單就是隨機(jī)抽樣加文件復(fù)制import random import shutil from pathlib import Path def split_dataset(img_dir, label_dir, output_dir, ratios(0.8, 0.1, 0.1)): img_dir Path(img_dir) label_dir Path(label_dir) output_dir Path(output_dir) # 獲取所有圖片文件名不含擴(kuò)展名 stems [f.stem for f in img_dir.glob(*.jpg)] random.seed(42) # 固定隨機(jī)種子保證可復(fù)現(xiàn) random.shuffle(stems) n len(stems) n_train int(n * ratios[0]) n_val int(n * ratios[1]) splits { train: stems[:n_train], val: stems[n_train:n_train n_val], test: stems[n_train n_val:] } for split_name, split_stems in splits.items(): img_out output_dir / images / split_name lbl_out output_dir / labels / split_name img_out.mkdir(parentsTrue, exist_okTrue) lbl_out.mkdir(parentsTrue, exist_okTrue) for stem in split_stems: # 復(fù)制圖片 src_img img_dir / f{stem}.jpg if src_img.exists(): shutil.copy(src_img, img_out / f{stem}.jpg) # 復(fù)制標(biāo)簽 src_lbl label_dir / f{stem}.txt if src_lbl.exists(): shutil.copy(src_lbl, lbl_out / f{stem}.txt) print(ftrain: {len(splits[train])}, val: {len(splits[val])}, test: {len(splits[test])}) split_dataset(dataset/JPEGImages, dataset_yolo/labels/all, dataset_yolo)random.seed(42)是為了保證每次劃分結(jié)果一致方便復(fù)現(xiàn)實(shí)驗(yàn)。劃分完之后檢查一下每個(gè)子集的圖片數(shù)和標(biāo)簽數(shù)是否一一對應(yīng)缺標(biāo)簽的圖片在訓(xùn)練時(shí)會(huì)被跳過但最好提前發(fā)現(xiàn)。3.3 啟動(dòng)訓(xùn)練與關(guān)鍵超參數(shù)設(shè)置數(shù)據(jù)準(zhǔn)備好之后寫一個(gè)data.yaml放在數(shù)據(jù)集根目錄path: /absolute/path/to/dataset_yolo train: images/train val: images/val test: images/test nc: 1 names: - chickenpath建議寫絕對路徑相對路徑在不同工作目錄下容易出問題。然后就可以啟動(dòng)訓(xùn)練了yolo detect train \ datadataset_yolo/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/chicken \ nameexp1幾個(gè)關(guān)鍵參數(shù)的含義和調(diào)整建議參數(shù)含義建議值調(diào)整邏輯model預(yù)訓(xùn)練權(quán)重yolov8n.pt / yolov8s.pt數(shù)據(jù)量 3000 張左右用 n 或 s 就夠m 以上容易過擬合epochs訓(xùn)練輪數(shù)100~300看驗(yàn)證集 loss 曲線還在降就繼續(xù)加imgsz輸入尺寸640雞的目標(biāo)如果很小可以提到 1280但顯存翻倍batch批大小16顯存不夠就降到 8 或 4配合 accumulate 使用lr0初始學(xué)習(xí)率0.01默認(rèn)值通常夠用loss 震蕩厲害就降到 0.001patience早停耐心值2020 輪驗(yàn)證集指標(biāo)不提升就停省時(shí)間yolov8n.pt是 YOLOv8 最小的預(yù)訓(xùn)練模型在 COCO 上預(yù)訓(xùn)練過。用預(yù)訓(xùn)練權(quán)重比從零訓(xùn)收斂快很多3000 張數(shù)據(jù)大概幾十個(gè) epoch 就能看到不錯(cuò)的 mAP。如果你的雞目標(biāo)特別小比如剛出殼的雛雞在畫面里只占幾十個(gè)像素把imgsz提到 1280 會(huì)有明顯提升但 batch 要相應(yīng)降到 4 或 8。訓(xùn)練過程中重點(diǎn)看幾個(gè)指標(biāo)box_loss和cls_loss是否穩(wěn)定下降、mAP50是否在漲、驗(yàn)證集 loss 和訓(xùn)練集 loss 的差距。如果訓(xùn)練集 loss 一直降但驗(yàn)證集 loss 開始漲就是過擬合了需要加數(shù)據(jù)增強(qiáng)或者減模型復(fù)雜度。3.4 訓(xùn)練結(jié)果解讀與推理驗(yàn)證訓(xùn)練結(jié)束后runs/chicken/exp1/目錄下會(huì)生成權(quán)重文件和評估結(jié)果。weights/best.pt是驗(yàn)證集上表現(xiàn)最好的權(quán)重weights/last.pt是最后一輪的。用 best.pt 做推理驗(yàn)證from ultralytics import YOLO model YOLO(runs/chicken/exp1/weights/best.pt) # 單張圖片推理 results model(test_image.jpg, conf0.25, iou0.45) results[0].save(output.jpg) # 批量推理整個(gè)測試集 results model(dataset_yolo/images/test, conf0.25, saveTrue)conf0.25是置信度閾值低于這個(gè)值的檢測框會(huì)被過濾掉。iou0.45是 NMS 的 IoU 閾值控制重疊框的合并程度。這兩個(gè)參數(shù)對最終結(jié)果影響很大——conf 調(diào)高會(huì)減少誤檢但可能漏檢調(diào)低則相反。建議在測試集上跑幾組不同閾值畫一條 P-R 曲線來選最優(yōu)點(diǎn)。推理結(jié)果里每張圖會(huì)輸出檢測框的坐標(biāo)、類別和置信度。如果發(fā)現(xiàn)大量漏檢先檢查訓(xùn)練集的標(biāo)注是否覆蓋了各種場景光照、遮擋、密集程度再考慮調(diào)低 conf 或者增加訓(xùn)練輪數(shù)。如果誤檢多看看是不是背景里有和雞顏色相近的物體可以加一些負(fù)樣本圖片進(jìn)去。4. 避坑與排查訓(xùn)練雞檢測模型時(shí)最容易翻車的 5 個(gè)地方4.1 類別名不一致導(dǎo)致訓(xùn)練時(shí)全部標(biāo)為背景現(xiàn)象訓(xùn)練日志里cls_loss一直是 0 或者異常低mAP 始終上不去推理時(shí)一個(gè)框都檢測不出來。原因data.yaml里的names和標(biāo)注文件里的類別索引對不上。比如標(biāo)注里 chicken 的 class_id 是 0但 data.yaml 里 names 列表第一個(gè)是別的類別或者 nc 設(shè)成了 2 但實(shí)際只有 1 個(gè)類。解決轉(zhuǎn)換完數(shù)據(jù)后用腳本統(tǒng)計(jì)一遍所有 txt 里出現(xiàn)的 class_id 集合確認(rèn)和 data.yaml 的 nc 及 names 完全對應(yīng)。這個(gè)檢查花不了兩分鐘但能省掉幾個(gè)小時(shí)的無效訓(xùn)練。4.2 圖片和標(biāo)簽文件名不匹配導(dǎo)致大量樣本被跳過現(xiàn)象訓(xùn)練時(shí)提示No labels found或者實(shí)際參與訓(xùn)練的圖片數(shù)遠(yuǎn)少于預(yù)期。原因YOLO 要求圖片和標(biāo)簽同名擴(kuò)展名不同且放在對應(yīng)的 images/labels 目錄下。如果圖片是000001.jpg但標(biāo)簽是000001_chicken.txt或者標(biāo)簽放在錯(cuò)誤的子目錄里就會(huì)被跳過。解決寫一個(gè)校驗(yàn)?zāi)_本遍歷 images 下所有圖片檢查 labels 下是否存在同名 txt。缺失的列出來要么補(bǔ)標(biāo)簽要么刪圖片。同時(shí)檢查 labels 目錄下有沒有多余的 txt沒有對應(yīng)圖片的這些也會(huì)被忽略。4.3 小目標(biāo)檢測效果差雛雞在畫面里太小現(xiàn)象大雞能檢測到小雞漏檢嚴(yán)重mAP50 里小目標(biāo)的指標(biāo)明顯低于整體。原因YOLOv8 默認(rèn)輸入 640如果雛雞在原圖里只有 20×20 像素縮放到 640 后可能只剩幾個(gè)像素特征提取網(wǎng)絡(luò)根本抓不到。解決三個(gè)方向——把imgsz提到 1280 或更高用yolov8s或yolov8m這種更大的模型特征金字塔層數(shù)更多在數(shù)據(jù)增強(qiáng)里開啟mosaic和scale讓模型見過不同尺度的目標(biāo)。如果顯存不夠用batch4配合accumulate4來等效大 batch。4.4 驗(yàn)證集指標(biāo)虛高但實(shí)際推理效果差現(xiàn)象訓(xùn)練日志里 mAP50 到了 0.9 以上但拿真實(shí)場景的圖片去測漏檢誤檢一大堆。原因訓(xùn)練集和驗(yàn)證集來自同一批數(shù)據(jù)分布太接近。如果數(shù)據(jù)集里的圖片都是同一養(yǎng)殖場、同一角度拍的模型只是記住了這個(gè)場景換一個(gè)環(huán)境就廢了。解決劃分驗(yàn)證集時(shí)確保覆蓋不同場景——不同光照、不同背景、不同密度。如果數(shù)據(jù)集本身多樣性不夠做推理測試時(shí)一定要用訓(xùn)練集之外的圖片。另外可以開啟val時(shí)的save_jsonTrue把預(yù)測結(jié)果導(dǎo)出來逐張看比只看指標(biāo)靠譜。4.5 顯存溢出導(dǎo)致訓(xùn)練中斷現(xiàn)象訓(xùn)練跑了幾十個(gè) epoch 突然報(bào) CUDA out of memory或者一開始就起不來。原因batch或imgsz設(shè)太大或者同時(shí)開了太多數(shù)據(jù)增強(qiáng) worker。另外如果訓(xùn)練過程中有內(nèi)存泄漏某些版本的 ultralytics 有過這個(gè)問題跑久了也會(huì) OOM。解決先把batch降到 4 試試能跑起來再逐步往上加。imgsz從 640 起步需要更高分辨率再往上調(diào)。設(shè)置workers4而不是默認(rèn)的 8減少數(shù)據(jù)加載的顯存占用。如果還是不行用yolo detect train ... device0明確指定單卡避免多卡通信的開銷。5. 把 2970 張數(shù)據(jù)的價(jià)值榨干標(biāo)注質(zhì)量復(fù)核與增量標(biāo)注技巧數(shù)據(jù)集到手直接用是最省事的但 2970 張里難免有標(biāo)注瑕疵。我一般會(huì)花半天時(shí)間做一輪標(biāo)注質(zhì)量復(fù)核這一步的投入產(chǎn)出比極高。具體做法是用訓(xùn)練好的模型在訓(xùn)練集上跑一遍推理把預(yù)測框和原始標(biāo)注框做 IoU 對比IoU 低于 0.5 的挑出來人工看。這些低 IoU 樣本要么是標(biāo)注框畫歪了要么是模型確實(shí)沒學(xué)好——兩種情況都值得關(guān)注。from ultralytics import YOLO import cv2 model YOLO(runs/chicken/exp1/weights/best.pt) # 在訓(xùn)練集上推理找出預(yù)測和標(biāo)注差異大的樣本 results model(dataset_yolo/images/train, conf0.1, iou0.5, saveTrue, save_txtTrue) # 對比 save_txt 輸出的預(yù)測標(biāo)簽和原始標(biāo)簽 # 逐張計(jì)算 IoU低于閾值的記錄下來人工復(fù)核conf0.1故意設(shè)低是為了讓模型多輸出一些框方便和標(biāo)注對比。save_txtTrue會(huì)把預(yù)測結(jié)果按 YOLO 格式存下來直接和原始標(biāo)簽做 diff 就行。復(fù)核的時(shí)候重點(diǎn)關(guān)注三類模型檢測到但標(biāo)注里沒有的可能是漏標(biāo)、標(biāo)注里有但模型沒檢測到的可能是標(biāo)錯(cuò)了或者目標(biāo)太模糊、框位置明顯偏移的。復(fù)核完之后如果發(fā)現(xiàn)某些場景下漏標(biāo)嚴(yán)重可以針對性地補(bǔ)標(biāo)。補(bǔ)標(biāo)不需要從頭來——用模型先預(yù)測一遍人工只修正錯(cuò)誤的框效率比純手工高好幾倍。LabelImg 和 CVAT 都支持導(dǎo)入預(yù)標(biāo)注結(jié)果在這個(gè)基礎(chǔ)上改就行。補(bǔ)標(biāo)的數(shù)據(jù)和原始數(shù)據(jù)混在一起重新訓(xùn)練通常能帶來幾個(gè)點(diǎn)的 mAP 提升。還有一個(gè)技巧是難例挖掘。訓(xùn)練完一輪后把驗(yàn)證集里 loss 最高的那批樣本挑出來看看它們有什么共性——是遮擋嚴(yán)重、還是目標(biāo)太小、還是背景干擾強(qiáng)。然后針對這些場景補(bǔ)充數(shù)據(jù)或者調(diào)整增強(qiáng)策略。這個(gè)循環(huán)做兩三遍模型在真實(shí)場景下的魯棒性會(huì)有明顯改善。我自己踩過的最大坑是拿到數(shù)據(jù)集后急著跑訓(xùn)練忽略了標(biāo)注復(fù)核結(jié)果模型在驗(yàn)證集上指標(biāo)很好看部署到養(yǎng)殖場里發(fā)現(xiàn)一堆漏檢。后來回頭查標(biāo)注發(fā)現(xiàn)有一批圖片的框只標(biāo)了雞的身體沒標(biāo)頭模型學(xué)到的特征不完整?;〞r(shí)間做標(biāo)注復(fù)核這件事后悔藥沒得吃但提前做就是最好的保險(xiǎn)。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取