據(jù)集:從圖片到可用權重的完整實踐)
簡介面向目標檢測初學者的YOLOv8自定義數(shù)據(jù)集訓練完整筆記內(nèi)容覆蓋環(huán)境安裝、圖片與標簽文件整理、數(shù)據(jù)集切分與格式轉換、模型訓練及斷點續(xù)訓等關鍵環(huán)節(jié)。整套資源僅包含一份Worddocx格式文檔大小約2.18MB以步驟化敘述和命令示例組織便于對照實操當前已有448人學習。文檔詳細說明安裝依賴包和ultralytics庫的指令演示將標注好的圖片與XML文件分別放入images與xml目錄、運行腳本劃分訓練集和驗證集、再轉換為YOLO訓練所需格式的做法同時逐一解釋task、mode、model、data、epochs、batch等訓練參數(shù)的含義并介紹預訓練模型下載與訓練命令寫法。此外針對訓練中可能出現(xiàn)的Arial字體下載失敗問題給出了下載并放置到項目根目錄的解決辦法也講解了修改default.yaml或使用resume參數(shù)實現(xiàn)斷點續(xù)訓的方式能夠幫助讀者避開常見坑點按流程完成自定義數(shù)據(jù)集的YOLOv8訓練。1. YOLOv8訓練自定義數(shù)據(jù)集把“別人家的模型”變成自己的檢測器做目標檢測的人多半經(jīng)歷過這種尷尬對著COCO上表現(xiàn)亮眼的YOLOv8權重跑demo一切正常一旦換成自己拍的安全帽、工件或者遙感圖精度直接垮掉。原因不復雜——預訓練權重沒見過你的數(shù)據(jù)分布遷移學習也得按規(guī)矩喂數(shù)據(jù)、調(diào)參數(shù)、看損失曲線才能收斂出能用的模型。這份《YOLOv8訓練自定義數(shù)據(jù)集》筆記就是把從原始圖片到可用權重的全過程拆開環(huán)境怎么搭、目錄怎么擺、標注怎么轉、超參怎么改、報錯怎么查適合手里有數(shù)據(jù)集但沒完整跑通過自訓練流程的從業(yè)者也適合剛接觸YOLOv8想復現(xiàn)一套標準pipeline的新手。下面按我實際跑項目的順序來寫每一節(jié)都是踩過坑之后的固定動作。2. 環(huán)境與工程骨架先把訓練環(huán)境裝成“不折騰”的樣子2.1 版本選型為什么我鎖在YOLOv8.1.0附近YOLOv8的ultralytics倉庫更新很頻繁幾個月不用可能API就變了。早年跑通一套流程過陣子換新版本model.train的參數(shù)表和回調(diào)接口可能已經(jīng)改了名網(wǎng)上教程對不上號。所以我一般建議鎖一個相對穩(wěn)定的版本而不是追最新。常見做法是pip install ultralytics8.1.0 pip list | grep torch邏輯說明ultralytics這個包自帶YOLOv8的模型定義、訓練器和數(shù)據(jù)集工具版本鎖住之后復現(xiàn)成本低。torch版本建議2.0以上因為YOLOv8的某些增強操作依賴新版CUDA算子老torch可能跑不起來。參數(shù)說明如果你用的是GTX 1660 Ti這類6GB顯存的顯卡torch別裝太高版本CUDA 11.8對應的torch 2.0.x就夠用。顯存不夠時后面訓練只能開小batch這個在第4章會細說。2.2 目錄約定一張圖理清數(shù)據(jù)、權重和輸出有了訓練環(huán)境下一步是搭目錄。YOLOv8對數(shù)據(jù)集路徑要求不算嚴但目錄結構清晰能讓你少踩很多“找不到文件”的坑。我習慣這樣建yolov8-custom ├── data │ ├── images │ │ ├── train │ │ └── val │ └── labels │ ├── train │ └── val ├── weights ├── runs └── config.yaml邏輯說明data/images/train放訓練圖片data/images/val放驗證圖片labels下是對應的標注txt文件。weights放預訓練權重runs放每次訓練的輸出目錄config.yaml是數(shù)據(jù)集配置。參數(shù)說明圖片和標注的txt必須同名比如img001.jpg對應img001.txt否則訓練時YOLOv8會直接跳過這張圖。這是新手最容易翻車的地方文件名對不上訓練半天損失不降一看日志全是“WARNING: 0 labels found”。2.3 config.yaml寫法類別數(shù)錯了訓練就是玄學數(shù)據(jù)集配置是訓練入口內(nèi)容不多但每個字段都關鍵。按YOLOv8的約定path: ./data train: images/train val: images/val names: 0: helmet 1: person邏輯說明path是數(shù)據(jù)集根目錄的路徑可以用相對路徑但建議在config.yaml被調(diào)用的那個目錄下啟動訓練避免相對路徑找不到。train和val填圖片目錄的相對路徑YOLOv8會自動拼接。names是類別名與索引的映射順序必須和標注txt里的類別ID一一對應。參數(shù)說明類別ID從0開始不是1。如果標注文件里寫了1而你的names里0對應的才是helmet那模型訓練時會把helmet當背景損失曲線看著正常實際學了個寂寞。3. 數(shù)據(jù)準備把VOC轉成YOLO格式轉換腳本與四個邊界坑3.1 為什么非轉不可YOLO要的是歸一化坐標YOLOv8要求的標注是txt格式每行一個目標格式是class x_center y_center width height四個坐標值都是相對于圖片寬高的歸一化結果。而我們拿到手的標注數(shù)據(jù)最常碰到的兩種格式是VOC的XML和LabelImg導出的XML里面存的是xmin ymin xmax ymax絕對像素坐標。直接用絕對坐標喂給YOLOv8訓練會出問題因為縮放和增強時坐標體系對不上。轉換方式不復雜核心就一步import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_path, class_map): tree ET.parse(xml_path) 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 if cls_name not in class_map: continue cls_id class_map[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) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / 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}) with open(out_path, w) as f: f.write(\n.join(lines)) if __name__ __main__: class_map {helmet: 0, person: 1} xml_dir xmls out_dir labels os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if xml_file.endswith(.xml): voc_to_yolo(os.path.join(xml_dir, xml_file), os.path.join(out_dir, xml_file.replace(.xml, .txt)), class_map)邏輯說明遍歷XML目錄把每個XML里的object信息解析出來計算出歸一化的中心點和寬高寫成一行一目標的txt。class_map控制類別到ID的映射和config.yaml里的names必須一致。參數(shù)說明坐標輸出保留了6位小數(shù)夠用。歸一化計算時除以的是圖片原始寬高不是縮放后的。如果你的數(shù)據(jù)集是直接用ROI截出來的圖注意核對XML里size字段和實際圖片尺寸是否一致不一致時轉換出的坐標全是錯的。3.2 邊界坑一類別不在映射表里轉換時如果XML里有names之外的類別比如背景、未知腳本默認continue跳過。但訓練時這類目標就完全不會被學習。我的習慣是把這些類別單獨導出一個ignore列表方便回頭統(tǒng)計而不是直接丟。3.3 邊界坑二零面積框和超界框標注軟件有時會標出xmin等于xmax的框歸一化后w就是0訓練時YOLOv8的loss計算會崩。常見解決是在轉換腳本里加一個過濾if w 0 or h 0: continue3.4 邊界坑三中文路徑和中文類名Windows下如果數(shù)據(jù)集路徑帶中文ultralytics內(nèi)部讀圖或寫日志時容易報編碼錯誤。類名更直接names里如果用中文訓練日志和輸出權重都能正常出但做部署推理時標簽回顯會亂碼。建議所有類名只用英文字母和下劃線路徑保持ASCII。3.5 邊界坑四數(shù)據(jù)劃分別在腳本里隨機做常見做法是先把所有圖片放一個文件夾腳本按比例隨機劃分到train和val。這個思路沒錯但要注意隨機種子問題。我見過有人跑兩次轉換同一張圖一次在train一次在val導致模型過擬合評估失真。正確做法是轉換前先把圖片清單寫好按清單復制圖片和對應的txt不做多次隨機。4. 訓練參數(shù)與啟動從命令行到損失曲線一次說清4.1 訓練入口為什么我推薦命令行而不是Python腳本YOLOv8支持兩種訓練方式y(tǒng)olo train命令行和from ultralytics import YOLO的Python腳本。兩種本質(zhì)跑的是同一套東西但命令行更適合做實驗記錄參數(shù)直接打在shell里每改一次就是一個可追溯的版本。我的固定寫法是yolo train modelyolov8s.pt dataconfig.yaml epochs100 imgsz640 batch8 device0 projectruns/helmet_2024 nameexp1邏輯說明model填預訓練權重的路徑data是數(shù)據(jù)集配置epochs是訓練輪數(shù)imgsz是訓練輸入尺寸batch是每個batch的圖片數(shù)device表示用哪張GPU。這行命令跑完模型權重、損失曲線、驗證指標全在runs/helmet_2024/exp1里。參數(shù)說明imgsz默認640如果你的目標是小物體比如遠處的安全帽可以嘗試896或1280但顯存占用會明顯上漲。batch在6GB顯存的卡上最多開到8到16根據(jù)顯存動態(tài)調(diào)爆顯存就先減半。4.2 batch大小與顯存的博弈batch不是越大越好小顯存硬開大batch會導致OOM訓練中斷。更隱蔽的問題是過小的batch加默認的增強策略可能出現(xiàn)類別不均衡放大某些類別收斂慢。我一般這么測yolo train modelyolov8s.pt dataconfig.yaml epochs3 imgsz640 batch16 device0邏輯說明先用3個epoch跑通流程觀察顯存占用接近上限還是有余量再決定正式訓練時batch的檔位。參數(shù)說明OOM時報錯信息通常是CUDA out of memory看到這個直接調(diào)小batch。如果用了batch-1YOLOv8會自動根據(jù)顯存算最大batch但實測這個自動值偏激進我會手動減2再跑。4.3 損失曲線怎么看何時加epoch何時該停訓練結束后乍一看results.png幾條下降曲線訓練集和驗證集分開長。新手容易犯的錯誤是只看train的loss忽略val的指標。實際判斷標準是import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/helmet_2024/exp1/results.csv) plt.plot(df[epoch], df[train/box_loss], labeltrain box) plt.plot(df[epoch], df[val/box_loss], labelval box) plt.legend() plt.show()邏輯說明results.csv記錄每一項指標包括三類loss、精度、召回率、mAP50和mAP50-95。訓練過程中如果val/box_loss連續(xù)20個epoch不降或反升說明過擬合早停更合理不用硬跑100輪。參數(shù)說明如果前10個epoch訓練loss就降到很低但val的mAP50不到0.3大概率是數(shù)據(jù)集類別不均衡或標注質(zhì)量有問題先回去查數(shù)據(jù)不是調(diào)參能解決的。5. 避坑常見問題排查五條血淚經(jīng)驗5.1 訓練日志一堆WARNINGloss不降現(xiàn)象訓練時日志滾動輸出WARNING: 0 labels found in ...loss數(shù)值變化不大。原因圖片文件名和標注txt文件名不一致最常見的是圖片是.jpgtxt是.txt但大小寫不匹配或者標注目錄下存在沒有對應txt的圖。解決寫個腳本核對images/train和labels/train下的同名文件數(shù)量不一致的分出來處理。常見做法是for f in data/images/train/*.jpg; do base$(basename $f .jpg) if [ ! -f data/labels/train/$base.txt ]; then echo missing label: $f fi done5.2 顯存爆了但減小batch還是報錯現(xiàn)象CUDA out of memory反復出現(xiàn)batch從16降到8仍然報錯。原因除了batchimgsz和workers也會影響顯存。輸入圖越大特征圖越占顯存workers開太高會導致CPU/GPU數(shù)據(jù)搬運排隊顯存空不出來。解決先降imgsz到416跑通后再逐步提回640。workers適中調(diào)整比如workers4。5.3 訓練正常但驗證結果全黑現(xiàn)象訓練跑完驗證集上mAP為0val_batch_labels.jpg里沒有框。原因類別映射和標注類別ID對不上或者驗證集中的圖本身就沒有目標。解決檢查config.yaml的names數(shù)量和順序確認轉換腳本里class_map完全一致。用打開一張驗證圖和對應的txt目測坐標是否在圖片范圍內(nèi)。5.4 預訓練權重加載報錯現(xiàn)象Error loading pretrained weight但權重文件明明存在。原因下載的權重文件不完整或者權重版本和ultralytics版本不匹配。解決刪除權重文件重新下或換用YOLOv8官方提供的yolov8s.pt不要用第三方轉換的中間格式。5.5 數(shù)據(jù)集大但訓練非常慢現(xiàn)象GPU利用率只有30%左右訓練一個epoch耗時過長。原因數(shù)據(jù)加載瓶頸workers太低圖片存儲在高延遲設備上或者圖像解碼消耗CPU。解決把圖片壓成較小尺寸長邊不超過1280再訓練減少解碼負擔確認workers至少不低于4如果內(nèi)存足夠可以先將小數(shù)據(jù)集整體緩存到內(nèi)存中。但更推薦的方案是保持原圖分辨率先用一半的epoch觀察收斂趨勢再決定是否增補數(shù)據(jù)。6. 進階技巧用驗證集輸出反向查漏訓練收斂之后第一件事不是直接部署,而是把驗證集的預測結果導出來用框疊在原圖上肉眼檢查一遍。這一步能發(fā)現(xiàn)指標上看不出來的問題比如小目標漏檢、同類目標緊貼時被合并框。我的習慣是跑一次model.val再把驗證輸出目錄里的val_batch_pred.jpg逐張過一遍重點看置信度低于0.5的漏檢框。具體做法是from ultralytics import YOLO model YOLO(runs/helmet_2024/exp1/weights/best.pt) results model.val(dataconfig.yaml, conf0.25, iou0.6, save_jsonTrue) results.save_dir邏輯說明conf控制置信度閾值iou控制NMS的IoU閾值save_jsonTrue會導出COCO格式的預測結果方便后續(xù)做誤差分析。results.save_dir是可視化輸出的目錄所有預測圖都在里面。參數(shù)說明conf0.25是驗證時的常用默認值但實際業(yè)務場景如果要求低漏檢率可以降到0.1再看這時候能找出哪些目標確實沒被訓練好而不是被置信度閾值過濾掉。驗證通過后下一步才是導出部署格式。如果你要部署到RK3588這類邊緣設備那邊接收的格式和PC端推理不一樣建議在導出ONNX之前先用yolo export modelbest.pt formatonnx imgsz640走一遍確認輸出層的shape符合預期。在這之前先回到訓練配置里核對類別名和預處理尺寸保證導出時用的參數(shù)和訓練時完全一致。從那以后我每次訓練完都強制走一遍“驗證集視覺檢查 低置信度漏檢分析”再決定要不要調(diào)數(shù)據(jù)或加訓練輪數(shù)。這套習慣幫我篩出過不少指標漂亮但實際不能用的模型。希望這份筆記能幫你在YOLOv8自訓練這條路上少翻幾次車。本文還有配套的精品資源點擊獲取