據(jù)集6000張YOLO訓練全流程與避坑指南)
簡介面向yolo系列算法yolov5至yolo11目標檢測訓練的數(shù)據(jù)集包聚焦可回收廢物識別場景包含玻璃瓶、紙瓶、塑料瓶、塑料袋等類別標簽齊全可直接訓練與驗證。數(shù)據(jù)集已劃分好并同時提供yolo格式txt與voc格式xml兩種標注方便在不同框架間切換初學者與進階開發(fā)者均可快速上手。壓縮包共2000個xml標注文件對應VOC格式同時配套yolo標簽整體約229.98MB組織清晰適合垃圾分類檢測模型訓練與效果對比。目前已有47人學習/下載適合需要實際標注數(shù)據(jù)完成課程設計、項目開發(fā)或算法復現(xiàn)的讀者。使用時可依據(jù)yolo格式說明理解坐標歸一化規(guī)則也可借助voc格式進行數(shù)據(jù)增強或格式轉換。這套數(shù)據(jù)能節(jié)省人工標注時間專注模型調(diào)參與迭代是構建可回收物檢測系統(tǒng)的實用基礎資源。1. 可回收廢物數(shù)據(jù)集的 6000 張帶標簽圖像YOLO 分揀項目的起點準備做回收物分揀或者智能回收箱的人大概率會先去找數(shù)據(jù)集。這份可回收廢物數(shù)據(jù)集 zip 包里裝的是 6000 張帶標簽圖像覆蓋玻璃瓶、紙瓶、塑料瓶、塑料袋四類目標很明確喂給 YOLO 訓練一個能實時識別這幾類回收物的檢測模型。6000 張對四類目標檢測來說屬于「夠起步但不富余」的量級——訓練能出有效模型但標注質量和樣本分布稍微出問題指標就會明顯塌。它的適用人群很具體要做垃圾分類演示項目的學生、給分揀線做視覺方案的小團隊、以及想快速驗證 YOLO 落地效果的工程師。這篇文章順著「解包 → 校驗標簽 → 訓練 → 補數(shù)據(jù)」這條線把每一步的做法和坑位寫清楚讓你拿到 zip 之后能直接照做。2. 從 ZIP 到訓練集解包、標簽格式確認與數(shù)據(jù)集劃分2.1 解包之后的第一件事先看目錄別急著看圖拿到 zip 先別急著打開圖片欣賞。常見做法是解壓到一個不含中文和空格的路徑比如D:\recycle_dataset或~/datasets/recycle。用 unzip 或 Python 的 zipfile 都行命令如下mkdir -p ~/datasets/recycle unzip yolo算法-可回收廢物數(shù)據(jù)集-6000張圖像帶標簽-玻璃瓶紙瓶塑料瓶塑料袋.zip -d ~/datasets/recycle解壓完成后不要直接去看圖片內(nèi)容先確認頂層目錄結構。按這個標題的命名習慣包內(nèi)大概率是 images 和 labels 兩個平級目錄也可能按類別分子目錄。用 find 列出前兩層結構find ~/datasets/recycle -maxdepth 2 -type d | head -40這一步的目的有兩個一是確認圖像格式是 jpg 還是 png后續(xù)腳本里擴展名判斷要對上二是確認標簽和圖像是否同名。如果圖像 6000 張、標簽文件也是 6000 份說明配對關系大概率成立數(shù)量對不上后面訓練時 YOLO 會靜默跳過沒有標簽的圖像導致實際訓練集縮水val 指標虛高——這個坑我放到第 5 章詳細說。目錄里如果出現(xiàn)classes.txt或labels.txt這是關鍵文件它是類別順序的唯一權威來源先復制出來放好。2.2 YOLO txt 標簽和 VOC xml 標簽坐標系完全不一樣可回收廢物這類數(shù)據(jù)集的標簽最常見的就兩種格式。YOLO 格式下每個目標占一行五個數(shù)字分別是 class_id、歸一化后的中心 x、中心 y、寬 w、高 h全部是浮點數(shù)VOC 格式則是 xml 文件用 xmin、ymin、xmax、ymax 記錄左上右下角像素坐標類別寫在name節(jié)點里。兩者坐標系不同混用必翻車。我建議隨機抽三五個標簽文件看內(nèi)容別只看一個cat ~/datasets/recycle/labels/train/0001.txt如果輸出長這樣0 0.4829 0.5312 0.1842 0.3128 1 0.1124 0.7785 0.0901 0.0874那就是 YOLO txt 格式class id 0 對應第一個類別。如果打開是 xml先別急著跑轉換腳本確認一件事數(shù)據(jù) yaml 里的類別順序必須與 xml 里 name 節(jié)點和 id 的映射一致。VOC 轉 YOLO 時中心點和寬高都要除以圖像寬高歸一化這步做錯所有框的位置會整體偏移訓練出來的模型檢測框全偏屬于玄學難排查的一類問題。我見過有人轉換時忘了歸一化loss 曲線看起來正常但推理時框全跑到圖像邊緣浪費了一整輪訓練時間。提示隨機抽 35 個標簽文件看不要只抽一個。類別編號順序不一致是最容易踩的坑——有的包玻璃瓶是 0有的包塑料瓶是 0光看目錄名根本看不出來。2.3 劃分 train/val先比對文件名再隨機切劃分數(shù)據(jù)集之前務必先確認圖像和標簽文件一一對應。下面這段腳本用文件主鍵比對兩個目錄import os img_dir images label_dir labels imgs {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith((.jpg, .png))} labels {os.path.splitext(f)[0] for f in os.listdir(label_dir) if f.endswith(.txt)} missing imgs - labels print(f圖像數(shù): {len(imgs)}, 標簽數(shù): {len(labels)}, 缺標簽: {len(missing)}) if missing: print(缺標簽示例:, list(missing)[:5])這里用os.path.splitext取主鍵而不是拿整個文件名匹配是因為 zip 解壓后常見一種情況圖像是.png標簽卻在生成時寫成了.jpg完整文件名比對會誤判成缺標簽。比對完如果缺標簽超過 5%要么補標要么直接把這部分圖像移出訓練目錄留著只會讓訓練集數(shù)量虛高、實際學習不到完整信號。劃分 train/val 我習慣按 8:2 隨機分。6000 張四類任務隨機劃分足夠不需要太復雜的分層抽樣。腳本如下import os, random, shutil random.seed(42) imgs [f for f in os.listdir(images) if f.endswith((.jpg, .png))] random.shuffle(imgs) val_ratio 0.2 val_count int(len(imgs) * val_ratio) os.makedirs(images/train, exist_okTrue) os.makedirs(images/val, exist_okTrue) os.makedirs(labels/train, exist_okTrue) os.makedirs(labels/val, exist_okTrue) for i, img in enumerate(imgs): stem os.path.splitext(img)[0] src_img os.path.join(images, img) src_lbl os.path.join(labels, stem .txt) if i val_count: shutil.move(src_img, images/val/) shutil.move(src_lbl, labels/val/) else: shutil.move(src_img, images/train/) shutil.move(src_lbl, labels/train/)這段腳本的三個要點random.seed(42)保證每次劃分結果一致方便復現(xiàn)實驗先 shuffle 再按數(shù)量切避免原目錄按文件名排序導致的分布偏差圖像和標簽必須同步移動只移圖像會讓 2.3 的比對腳本白跑。如果你的包內(nèi)圖像文件名不是連續(xù)編號也沒關系腳本用的是字符串主鍵不依賴編號。3. 寫 data.yaml 并跑通第一次 YOLOv8 訓練3.1 data.yaml 的寫法names 順序就是訓練時的類別 idYOLOv8 和 YOLOv5 的數(shù)據(jù)配置都用 yaml 文件。假設這個包的類別順序是玻璃瓶、紙瓶、塑料瓶、塑料袋以標簽文件實際出現(xiàn)的 id 為準data.yaml 長這樣path: ~/datasets/recycle train: images/train val: images/val nc: 4 names: 0: glass_bottle 1: paper_bottle 2: plastic_bottle 3: plastic_bag這里最大的坑是names的順序必須和標簽文件里的 class id 一致。yaml 里寫錯順序loss 照樣收斂但推理結果會張冠李戴——玻璃瓶被叫成塑料瓶屬于訓練過程一點異常都看不出來的沉默錯誤。所以寫完 yaml 之后別急著訓練先跑一段腳本從標簽文件反推實際的類別 id 全集import os ids set() for root, _, files in os.walk(labels/train): for f in files: if not f.endswith(.txt): continue with open(os.path.join(root, f)) as fp: for line in fp: ids.add(int(line.split()[0])) print(實際出現(xiàn)的類別 id:, sorted(ids))遍歷所有標簽文件收集出現(xiàn)的 class id。如果打印出來是[0, 1, 2, 3]說明四類齊全且編號連續(xù)和 yaml 的 names 順序可以一一對上。如果出現(xiàn) 5、6 這類超出標題范圍的編號說明包里混了沒寫進標題的類別需要單獨抽出來看是刪還是保留。這個腳本建議每次換數(shù)據(jù)集都跑一次是性價比最高的防呆手段。3.2 最小訓練命令Ultralytics 一行起跑環(huán)境這塊我一般用 PyCharm 建一個虛擬環(huán)境來裝 ultralytics避免污染系統(tǒng) Python也方便換版本后回滾。安裝就一條命令pip install ultralytics裝完先不急著訓練跑一個極小的探測任務確認環(huán)境通yolo predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg能出檢測結果說明 CUDA 和模型下載鏈路都沒問題。然后開始正式訓練yolo detect train datarecycle.yaml modelyolov8s.pt epochs100 imgsz640 batch16這條命令的參數(shù)含義拆開說modelyolov8s.pt會從官方倉庫自動下載 COCO 預訓練權重用它做遷移學習6000 張圖能比隨機初始化快幾倍收斂如果下載超時手動下載 yolov8s.pt 放到項目目錄參數(shù)改成model./yolov8s.pt即可。epochs100對四類 6000 張的量是合理的起點跑完看 val 曲線再決定加不加。batch取決于顯存我從 16 開始OOM 就降到 8。imgsz640是通用默認值如果你的圖像里瓶子占畫面比例很小可以試 960代價是訓練時間明顯變長。關鍵參數(shù)速查參數(shù)建議值什么時候調(diào)modelyolov8s.pt顯存小用 n精度不夠再上 mepochs100val loss 還在降就加到 150batch16OOM 時降到 8 或 4imgsz640小目標多、顯存夠時改 960注意訓練前關掉其他占顯存的程序。Windows 上常見問題是中途CUDA out of memory崩掉先降 batch別一上來就換大模型。3.3 訓練曲線怎么讀損失、mAP 和數(shù)據(jù)質量的對應關系ultralytics 訓練結束后runs/detect/train 目錄下會輸出 results.png、confusion_matrix.png 和一批驗證圖。results.png 第一行是 box loss 和 cls loss第二行是 mAP50 和 mAP50-95。讀這些曲線時我關注的不是絕對數(shù)值而是三個信號。第一個信號box loss 在 50 epoch 后還在穩(wěn)定下降、沒有平臺期說明 100 epoch 不夠加到 150。第二個信號mAP50 很高0.95 上下但 mAP50-95 很低0.5 左右說明框的位置大致對、但和真值重疊不夠常見原因是標注框沒貼緊目標邊緣——比如瓶子標注時把瓶蓋和陰影都框進去了。第三個信號val loss 在某輪后開始回升說明過擬合。6000 張四類任務一般不太會太早過擬合真出現(xiàn)了通常是 batch 太小或模型選太大誤用了 yolov8x。這里和 yolo 損失函數(shù)直接相關的一點box loss 反映的是框回歸的質量cls loss 反映類別預測的置信度。如果 cls loss 降得很快但 box loss 拖后腿問題出在標注框的 IoU 一致性上而不是模型學不會——這時候去調(diào)學習率沒用回頭清洗標注才是正解。我習慣訓練時開著終端每隔一段時間瞄一眼 runs/detect/train 下有沒有新生成的曲線圖30 epoch 時就能看出趨勢省得跑完一輪才發(fā)現(xiàn)數(shù)據(jù)有問題。4. 訓練前的數(shù)據(jù)清洗與樣本均衡標注質量決定模型上限4.1 用腳本找出面積過小和越界的標注框可回收廢物數(shù)據(jù)集里最典型的標注問題有兩類一類是瓶子在畫面里特別小只有幾十個像素高這類目標在 imgsz640 下幾乎學不到有效特征另一類是標注框越界YOLO 格式下表現(xiàn)為歸一化坐標大于 1 或小于 0。檢查腳本如下import os from PIL import Image bad_files [] for f in sorted(os.listdir(labels/train)): if not f.endswith(.txt): continue stem os.path.splitext(f)[0] img_path os.path.join(images/train, stem .jpg) if not os.path.exists(img_path): img_path os.path.join(images/train, stem .png) if not os.path.exists(img_path): continue w, h Image.open(img_path).size with open(os.path.join(labels/train, f)) as fp: for line in fp: parts line.split() if len(parts) ! 5: bad_files.append((f, 字段數(shù)異常)) break _, cx, cy, bw, bh map(float, parts) x1 (cx - bw / 2) * w y1 (cy - bh / 2) * h x2 (cx bw / 2) * w y2 (cy bh / 2) * h if x1 0 or y1 0 or x2 w or y2 h: bad_files.append((f, 坐標越界)) break if bw * w 10 or bh * h 10: bad_files.append((f, 目標過小)) break print(len(bad_files), 個文件可能需要處理) print(bad_files[:10])邏輯說明先把 YOLO 歸一化坐標還原成像素坐標檢查是否落在圖像范圍內(nèi)再用框的像素寬高判斷目標是否小到?jīng)]法學。還原坐標這步是核心很多人直接比較歸一化坐標和 1 的大小忽略了中心點加寬高一半可能越界的情況。10 像素是我自己的閾值可以在 816 之間調(diào)判斷依據(jù)是 imgsz640 時一個 10 像素寬的目標只占整圖寬度的 1.5%檢測頭很難穩(wěn)定回歸。這些壞樣本我的處理原則是越界的直接刪掉對應標簽行數(shù)量少不影響大局目標過小的先統(tǒng)計占比如果超過 5% 說明采集時拍攝距離太遠或圖像分辨率不夠這批數(shù)據(jù)對瓶子的召回率不會有保障與其硬扛不如直接放棄過小樣本把標注精力留給中等尺寸目標。4.2 類別不均衡和背景單一的應對思路玻璃瓶、紙瓶、塑料瓶、塑料袋四類如果數(shù)量差距大比如玻璃瓶 3000 張、塑料袋只有 500 張訓練時 loss 會被樣本多的類別主導塑料袋的 recall 會明顯掉隊。處理手段按優(yōu)先級排先改損失權重再對少數(shù)類做復制增強最后才考慮生成合成數(shù)據(jù)。合成瓶子圖像容易把紋理和反光特征做假塑料瓶那一類在驗證集上 mAP 高一上現(xiàn)場就翻車的情況我見過不少——數(shù)據(jù)增強的教訓有一條算一條寧可少補不要亂補。背景單一是另一個容易被忽略的問題。拿礦泉水瓶做例子如果訓練集里 60% 的背景是白墻和桌面現(xiàn)場放到深色傳送帶上檢測模型的泛化能力立刻見底??苫厥諒U物數(shù)據(jù)集如果全部在室內(nèi)固定背景拍攝建議訓練時打開 Ultralytics 的 mosaic 增強它會把四張圖拼成一張訓練樣本相當于變相擴充背景多樣性。再配合一點 HSV 擾動讓瓶子的顏色在合理范圍內(nèi)波動能明顯提升透明瓶和深色瓶的區(qū)分度。mosaic 在 ultralytics 里默認開啟只要確認沒被手動關掉就行HSV 參數(shù)通過命令行傳入hsv_h0.015 hsv_s0.7 hsv_v0.4是實用起點在這個基礎上微調(diào)即可。4.3 處理數(shù)據(jù)時的自我校驗清單數(shù)據(jù)清洗和增強做完訓練前再過一遍清單各類別樣本數(shù)是否接近均衡驗證集里是否覆蓋了不同背景和光照標簽坐標是否全部落在圖像范圍內(nèi)類別 id 是否與 yaml 的 names 順序一致。這套清單我每次都會走一遍血淚經(jīng)驗是數(shù)據(jù)問題在訓練前暴露代價是一小時訓練后才暴露代價是一整天。第 5 章里寫的幾個翻車現(xiàn)場根源幾乎都在這一步漏檢。5. 避坑指南可回收廢物數(shù)據(jù)集訓練常見的四個翻車現(xiàn)場5.1 缺標簽的圖像被靜默跳過val 指標虛高現(xiàn)象訓練日志顯示數(shù)據(jù)集有 6000 張圖但每個 epoch 實際處理的圖像明顯少于這個數(shù)val 的 mAP 卻高得反常。原因YOLO 對沒有對應 txt 標簽的圖像會靜默跳過不報錯也不警告。這個 zip 解壓后標簽缺失多半是文件名編碼問題導致配對失敗或者圖像是 png、標簽卻在生成時以 jpg 為后綴命名主鍵匹配斷開。解決訓練前跑 2.3 節(jié)的比對腳本把缺標簽的圖像統(tǒng)計出來。文件擴展名不一致是最隱蔽的情況務必用os.path.splitext取主鍵比對別拿完整文件名直接相等判斷。5.2 類別順序和標簽 id 對不上模型識別張冠李戴現(xiàn)象訓練日志正常loss 正常收斂驗證集上玻璃瓶被成批識別成塑料瓶且置信度還很高看起來像模型「學會了但學錯了」。原因data.yaml 里 names 的順序和標簽文件里的 class id 不一致。很多數(shù)據(jù)集打包時 categories 信息寫在子目錄里或者根本沒附全憑猜。解決先跑 3.1 的反推腳本收集標簽文件里實際出現(xiàn)的 id 全集和每個 id 的樣本數(shù)再對照 yaml 的 names 順序逐一核對。不要信目錄名目錄名和標簽 id 不一致的情況我碰到過不止一次——目錄叫 paper_bottle標簽里 id 2 代表的可能是塑料瓶。5.3 mAP50 很高但現(xiàn)場實時檢測框亂飄現(xiàn)象驗證集 mAP50 0.9 以上跑攝像頭實時檢測時塑料瓶的檢測框在目標附近抖動置信度忽高忽低甚至同一瓶子相鄰兩幀一類識別成玻璃瓶、一類識別成塑料瓶。原因訓練圖像全是一個角度、一個距離拍的缺少橫拍、斜拍和遠近變化或者標注框沒有貼緊目標邊緣模型學到的框始終比瓶子大一圈。透明玻璃瓶和塑料瓶在邊緣和背景融為一體時標注員很容易把框畫大。解決先看 runs/detect/train 里的驗證樣本圖和 confusion matrix確認模型學的是瓶子本身而不是背景。透明瓶類別的邊緣模糊問題可以在標注階段要求標注員貼著高光邊緣畫框陰影區(qū)域一律不框進。這個修正是提升 mAP50-95 最直接的手段。5.4 換大模型救不了數(shù)據(jù)集只會更早過擬合現(xiàn)象從 yolov8s 換到 yolov8m、yolov8x訓練時間翻倍甚至翻三倍mAP 只漲零點幾個點val loss 反而提前回升。原因6000 張四類目標檢測任務的瓶頸通常不在模型容量而在標注質量和樣本多樣性。模型參數(shù)量變大只會更快記住訓練集的噪聲。解決先用 yolov8s 跑通拿 baseline。如果 mAP50 已經(jīng)在 0.9 以上下一步是補數(shù)據(jù)、清洗標注、加數(shù)據(jù)增強而不是升級模型。這也是為什么我堅持把第 4 章的清洗腳本放在調(diào)參前面——數(shù)據(jù)問題暴露得越早后面越省事模型選型這種事放到數(shù)據(jù)干凈之后再做才有效。6. 用混淆矩陣和單類召回率決定下一批數(shù)據(jù)補什么訓練完第一版先別急著調(diào)參。ultralytics 會在 runs/detect/train 下生成 confusion_matrix.png這張圖是決定「下一批數(shù)據(jù)補什么」最直接的工具比盯著 mAP 均值有用得多。對可回收廢物四類來說最常見的混淆就是對角線之外的高亮格玻璃瓶和塑料瓶因為透明材質的反光特征在圖像上高度重疊紙瓶和塑料袋因為兩者都是可折疊、輪廓不規(guī)則的形態(tài)。如果混淆矩陣里玻璃瓶被大量判成塑料瓶說明訓練集里欠缺能區(qū)分這兩類的樣本——比如帶高光的磨砂玻璃和啞光塑料的對比圖像。補數(shù)據(jù)時應該精準補這一類而不是四類均勻加量。另一種做法是加載訓練好的模型對 val 集逐類算精度和召回率from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) metrics model.val(datarecycle.yaml) print(metrics.results_dict)metrics.results_dict里同時包含各類的召回率哪類 recall 低哪類就是下一輪重點補樣本的對象。別只看四類加權 mAP均值會掩蓋單類掉隊的真相。我自己踩過一個印象很深的坑第一版模型 mAP50 0.93看起來不錯但塑料袋 recall 只有 0.62——訓練集里塑料袋大多是團著的深色袋子現(xiàn)場遇到淺色展開的袋子就認不出。后來補了 300 張展開狀態(tài)的塑料袋圖像recall 直接到 0.85。從那以后我養(yǎng)成了一個習慣每次訓練完先看混淆矩陣和單類 recall再決定要不要繼續(xù)調(diào)參。數(shù)據(jù)問題不解決調(diào)參就是浪費時間。希望幫到你。本文還有配套的精品資源點擊獲取