數(shù)據(jù)集實(shí)戰(zhàn):從解壓體檢到Y(jié)OLOv8訓(xùn)練全流程)
簡(jiǎn)介目標(biāo)檢測(cè)是計(jì)算機(jī)視覺的重要方向,在道路智慧養(yǎng)護(hù)與自動(dòng)駕駛感知中,路面坑洼識(shí)別是典型且棘手的落地場(chǎng)景。這項(xiàng)任務(wù)的核心挑戰(zhàn)不僅在于模型結(jié)構(gòu),更在于數(shù)據(jù)質(zhì)量與工程流程,包括壓縮包解壓、文件體檢、標(biāo)注格式校驗(yàn)與訓(xùn)練環(huán)境搭建。YOLOv8作為目前廣泛應(yīng)用的實(shí)時(shí)檢測(cè)框架,為坑洼檢測(cè)提供了高效的訓(xùn)練與推理方案。圍繞數(shù)據(jù)集處理、標(biāo)注檢查、遷移學(xué)習(xí)訓(xùn)練及常見報(bào)錯(cuò)排查,完整實(shí)踐一條從zip壓縮包到可部署模型的鏈路,對(duì)道路巡檢、市政養(yǎng)護(hù)等應(yīng)用場(chǎng)景具有直接的工程參考價(jià)值。以坑洼目標(biāo)檢測(cè)數(shù)據(jù)集為例,從數(shù)據(jù)預(yù)處理到Y(jié)OLOv8訓(xùn)練的全流程梳理,能夠幫助開發(fā)者快速掌握真實(shí)數(shù)據(jù)集的落地處理方法。 這陣子在做道路病害識(shí)別手里正好過(guò)了一個(gè)坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip。這類文件名在目標(biāo)檢測(cè)圈子里太常見了——下載下來(lái)是個(gè)壓縮包里面是圖片和標(biāo)注但說(shuō)實(shí)話十個(gè)拿到這種包的人里至少有一半會(huì)卡在解壓、格式校驗(yàn)和訓(xùn)練參數(shù)這幾關(guān)上。今天就把這個(gè)數(shù)據(jù)集的完整處理過(guò)程拆開講一遍從 zip 解壓、文件體檢到用 YOLOv8 訓(xùn)練自己的坑洼檢測(cè)模型再到常見報(bào)錯(cuò)的排查全流程走一遍。這個(gè)數(shù)據(jù)集解決什么問(wèn)題一句話給路面坑洼檢測(cè)算法提供訓(xùn)練素材。適用于道路巡檢車、市政養(yǎng)護(hù)、自動(dòng)駕駛感知、無(wú)人機(jī)巡檢這幾個(gè)方向。適合誰(shuí)來(lái)參考剛?cè)腴T目標(biāo)檢測(cè)、正在做道路相關(guān)視覺項(xiàng)目、或者純粹想在真實(shí)數(shù)據(jù)集上把 YOLO 流程跑通的人都能從這里拿到可以直接復(fù)用的步驟和參數(shù)。1. 拆開壓縮包之前這個(gè)數(shù)據(jù)集里到底該有什么1.1 文件名里的信息量坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip這個(gè)文件名看著長(zhǎng)其實(shí)拆開就三部分坑洼目標(biāo)檢測(cè)數(shù)據(jù)集這是數(shù)據(jù)集的主題說(shuō)明內(nèi)容圍繞路面坑洼Pothole的檢測(cè)20251115_223705這個(gè)是打包時(shí)間戳2025 年 11 月 15 日 22 點(diǎn) 37 分 05 秒。做數(shù)據(jù)管理的人習(xí)慣在文件名里加時(shí)間戳主要是為了版本控制防止不同批次的數(shù)據(jù)集混用.zip這是壓縮格式。目標(biāo)檢測(cè)數(shù)據(jù)集通常包含大量圖片和標(biāo)注文件直接傳輸一個(gè)幾千張小圖的文件夾文件數(shù)太多、傳輸效率低打成 zip 包是最常見的分發(fā)方式。拿到這類壓縮包第一反應(yīng)不應(yīng)該是直接解壓而是先搞清楚里面是什么結(jié)構(gòu)。正常的坑洼檢測(cè)數(shù)據(jù)集解壓后應(yīng)該是這樣一個(gè)布局坑洼目標(biāo)檢測(cè)數(shù)據(jù)集/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml └── README.txtimages放原始圖片labels放對(duì)應(yīng)的標(biāo)注文件data.yaml是類別配置文件。這個(gè)結(jié)構(gòu)是 YOLO 系列任務(wù)的標(biāo)準(zhǔn)輸入格式PyTorch 生態(tài)里的多數(shù)檢測(cè)框架也認(rèn)這一套。1.2 為什么目標(biāo)檢測(cè)數(shù)據(jù)集普遍長(zhǎng)這樣有人可能會(huì)問(wèn)為什么要把圖片和標(biāo)注分開放在兩個(gè)目錄直接在一張圖上畫好框不行嗎這背后其實(shí)是目標(biāo)檢測(cè)任務(wù)的標(biāo)準(zhǔn)化邏輯。以 YOLO 格式為例每一張圖片對(duì)應(yīng)的標(biāo)注是一個(gè)同名.txt文件文件名與圖片名完全一致比如img_001.jpg對(duì)應(yīng)img_001.txt。txt 里的每一行代表一個(gè)目標(biāo)框格式是class_id x_center y_center width height其中x_center y_center width height是歸一化到 0~1 之間的相對(duì)坐標(biāo)。分開存放的好處是訓(xùn)練框架只需要按照文件名后綴去 images 和 labels 目錄各自取文件即可IO 效率高也方便對(duì)圖片做增強(qiáng)時(shí)同步修改標(biāo)注。這套命名約定很多剛?cè)腴T的人容易踩坑。也就是說(shuō)圖片是.jpg標(biāo)注是.txt但是文件名主體部分必須一模一樣不能出現(xiàn)img_001.jpg配001.txt的情況。擴(kuò)展開來(lái)看如果你以后做的是 COCO 格式的 JSON 標(biāo)注或者 VOC 格式的 XML 標(biāo)注那么目錄結(jié)構(gòu)又會(huì)不同。這個(gè)數(shù)據(jù)集既然以 YOLO 格式組織那就直接按 YOLO 的規(guī)矩來(lái)。1.3 數(shù)據(jù)集質(zhì)量的核心標(biāo)注能不能信任拿到了標(biāo)注文件先別急著訓(xùn)練。我見過(guò)不少數(shù)據(jù)集壓縮包解壓出來(lái)看著齊全但實(shí)際標(biāo)注有各種問(wèn)題坐標(biāo)越界、類別編號(hào)對(duì)不上、標(biāo)注框和物體不匹配??油輽z測(cè)尤其容易出這問(wèn)題——因?yàn)榭油莸倪吘壉旧砟:龢?biāo)注員主觀性很強(qiáng)。所以文件體檢這一步并不是走過(guò)場(chǎng)而是給后續(xù)訓(xùn)練上一個(gè)保險(xiǎn)。下一節(jié)就具體說(shuō)說(shuō)怎么在 Linux 下面完成這個(gè)過(guò)程。2. 解壓與文件體檢拿到 zip 后的第一件正事2.1 Linux 下解壓 zip 的常用操作大部分訓(xùn)練環(huán)境是 Linux 服務(wù)器所以這里以 Linux 命令為主。假設(shè)壓縮包位于/data/datasets/目錄下下面是幾個(gè)最常用的操作。先看壓縮包里有什么不用先解壓unzip -l 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip-l是 list 的意思列出壓縮包內(nèi)的文件清單可以看到目錄結(jié)構(gòu)和文件數(shù)量確認(rèn)是不是自己預(yù)期的內(nèi)容。如果文件太多可以配合less分頁(yè)查看或者用grep過(guò)濾unzip -l 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip | grep images/train | head -20確認(rèn)沒(méi)問(wèn)題之后再進(jìn)行解壓unzip 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip -d /data/datasets/pothole-d指定解壓目標(biāo)目錄。如果壓縮包文件名包含中文某些 Linux 環(huán)境下可能出現(xiàn)亂碼這時(shí)候可以試試用-O參數(shù)指定編碼unzip -O GBK 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip -d /data/datasets/pothole-O GBK這個(gè)參數(shù)在部分 unzip 版本里可用如果系統(tǒng)提示不支持也可以換成7z命令處理。如果是 Windows 上解壓直接用 WinRAR 或 7-Zip 即可注意解壓時(shí)選擇“解壓到指定文件夾”避免一堆散文件直接攤在桌面上。另外提醒一句如果是上傳到服務(wù)器先確認(rèn)文件大小再解壓。用ls -lh看一眼文件大小是否和下載頁(yè)面標(biāo)注的一致如果不一致解壓階段大概率會(huì)翻車。2.2 常見的“假 zip”與損壞問(wèn)題解壓的時(shí)候經(jīng)常遇到兩個(gè)報(bào)錯(cuò)一個(gè)是file is not a zip file一個(gè)是invalid zip archive: could not find EOCDEOCD 是 End Of Central Directory recordzip 格式記錄在文件末尾的結(jié)束標(biāo)志。這兩個(gè)問(wèn)題的本質(zhì)完全不同排查方式也不同。先說(shuō)file is not a zip file。用file命令看一眼真實(shí)文件類型file 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip如果輸出顯示是 HTML 文檔、GIF 圖片、純文本之類那說(shuō)明這個(gè)“zip”根本不是壓縮包。最常見的場(chǎng)景是你在某個(gè)網(wǎng)盤或網(wǎng)頁(yè)上下載實(shí)際得到的其實(shí)是 404 錯(cuò)誤頁(yè)或者登錄跳轉(zhuǎn)頁(yè)只是名字里帶了.zip后綴。這種情況不用想修復(fù)回去重新確認(rèn)下載鏈接。再說(shuō)could not find EOCD。zip 的中央目錄記錄Central Directory在文件末尾如果下載中斷、上傳不完整文件尾部損壞就會(huì)報(bào)這個(gè)錯(cuò)。這時(shí)候先測(cè)試一下壓縮包完整性u(píng)nzip -t 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip-t是 test 的意思會(huì)逐個(gè)讀取壓縮包內(nèi)的文件進(jìn)行校驗(yàn)。如果報(bào)錯(cuò)信息集中在后半段說(shuō)明文件尾部被截?cái)嗔?。此時(shí)可以嘗試用zip -FF進(jìn)行修復(fù)zip -FF 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip --out repaired.zip但說(shuō)實(shí)話zip -FF對(duì)文件頭完整但中央目錄損壞的情況有一定恢復(fù)概率如果文件本身就下載了一半成功率很低。最穩(wěn)妥的辦法還是重新下載并且下載后立刻做 MD5 校驗(yàn)md5sum 坑洼目標(biāo)檢測(cè)數(shù)據(jù)集_20251115_223705.zip和發(fā)布方提供的 MD5 值比對(duì)一致就說(shuō)明文件完好。這個(gè)習(xí)慣在數(shù)據(jù)集分發(fā)場(chǎng)景里非常實(shí)用尤其是大體積數(shù)據(jù)集斷點(diǎn)續(xù)傳和下載校驗(yàn)?zāi)苁〉艉芏嗦闊?.3 目錄結(jié)構(gòu)確認(rèn)與可視化抽查解壓完之后先看整體規(guī)模cd /data/datasets/pothole find . -type f | wc -l然后分別統(tǒng)計(jì)各類文件數(shù)量find images -type f | wc -l find labels -type f | wc -l正常情況下images/train里的圖片數(shù)量和labels/train里的 txt 數(shù)量應(yīng)該一致。如果數(shù)量對(duì)不上說(shuō)明有一部分圖片沒(méi)有標(biāo)注或有一部分標(biāo)注沒(méi)有對(duì)應(yīng)圖片。這時(shí)候需要寫個(gè)腳本把缺失的文件找出來(lái)。這里給一個(gè) Python 腳本檢查圖片和標(biāo)注是否一一對(duì)應(yīng)import os from pathlib import Path img_dir Path(images/train) label_dir Path(labels/train) img_files {p.stem for p in img_dir.glob(*.jpg)} label_files {p.stem for p in label_dir.glob(*.txt)} missing_labels img_files - label_files missing_images label_files - img_files extra_labels label_files - img_files print(f圖片總數(shù): {len(img_files)}) print(f標(biāo)注總數(shù): {len(label_files)}) print(f缺少標(biāo)注的圖片數(shù): {len(missing_labels)}) print(f缺少圖片的標(biāo)注數(shù): {len(missing_images)}) if missing_labels: print(示例:, list(missing_labels)[:5])如果缺少標(biāo)注的數(shù)量不多可以考慮直接把對(duì)應(yīng)圖片刪掉如果缺得很多就要回去找發(fā)布者確認(rèn)了。這一步做完再抽查幾張圖片的標(biāo)注框是否貼合目標(biāo)可以用 OpenCV 畫框可視化import cv2 img_path images/train/img_001.jpg label_path labels/train/img_001.txt img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: cls, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cls)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(check.jpg, img)抽查十幾張基本就能看出標(biāo)注質(zhì)量如何??油萑绻麡?biāo)得大而松、把周圍正常路面也框進(jìn)去或者漏標(biāo)嚴(yán)重那這個(gè)數(shù)據(jù)集訓(xùn)練出來(lái)的模型偏移和漏檢率就會(huì)高需要自行清洗。3. 坑洼檢測(cè)的本質(zhì)這不是一個(gè)“普通的目標(biāo)檢測(cè)”3.1 坑洼目標(biāo)的特殊性很多人第一次接觸坑洼檢測(cè)會(huì)以為這不就是檢測(cè)一個(gè)框嘛和檢測(cè)貓、狗沒(méi)什么區(qū)別。但實(shí)際上坑洼屬于相當(dāng)“惡心”的一類目標(biāo)它有幾個(gè)特征把算法虐得夠嗆。第一尺度變化極大。道路巡檢車拍到的坑洼可能在畫面里占 30% 的面積而車載攝像頭在遠(yuǎn)處看到的坑洼可能只占 0.5%。同一個(gè)數(shù)據(jù)集里尺度跨度非常大這對(duì)模型的尺度泛化能力要求很高。第二邊緣模糊、類內(nèi)差異巨大。坑洼不是一個(gè)形態(tài)固定、邊界清晰的目標(biāo)。有的坑邊緣銳利有的坑已經(jīng)磨得和路面幾乎齊平顏色上又有瀝青深坑、水泥淺坑、積水反光坑等不同形態(tài)。標(biāo)注員對(duì)邊界的主觀判斷直接影響訓(xùn)練標(biāo)簽質(zhì)量。第三背景干擾嚴(yán)重。路面本身紋理嘈雜裂縫、修補(bǔ)痕跡、油漬、樹影、水漬都可能被模型誤判為坑洼。這也是為什么坑洼檢測(cè)模型特別容易“誤報(bào)”很多誤檢都來(lái)自對(duì)路面陰影和水漬的敏感。第四光照和天氣影響。雨天積水讓坑洼更明顯但反光嚴(yán)重陰天對(duì)比度低坑洼邊緣很難分辨。數(shù)據(jù)集如果集中在晴天拍攝模型在雨天的泛化能力會(huì)明顯下降。3.2 數(shù)據(jù)質(zhì)量決定上限模型效果的上限不是由模型結(jié)構(gòu)決定的而是由數(shù)據(jù)質(zhì)量決定的??油輸?shù)據(jù)集常見的質(zhì)量問(wèn)題就三類漏標(biāo)率偏高一張圖里有五六個(gè)坑標(biāo)注框只有一兩個(gè)。這會(huì)導(dǎo)致訓(xùn)練時(shí)這些未標(biāo)注的區(qū)域變成“負(fù)樣本”模型會(huì)學(xué)著把坑洼當(dāng)背景漏檢率直接拉高邊界框偏大或偏小標(biāo)注框習(xí)慣性放大把非坑洼的周邊路面包進(jìn)去訓(xùn)練出來(lái)的預(yù)測(cè)框也會(huì)偏松反之標(biāo)小了預(yù)測(cè)框只覆蓋坑洼中心位置類別不均衡如果數(shù)據(jù)集同時(shí)包含多個(gè)類別比如“完好路面”“裂縫”“坑洼”那坑洼占比太低的話模型會(huì)整體偏向數(shù)量多的類別。所以我在拿到任何數(shù)據(jù)集之后都會(huì)先做一次“基準(zhǔn)確認(rèn)”——拿訓(xùn)練集里一小部分圖片看一眼標(biāo)注質(zhì)量再按類別人數(shù)統(tǒng)計(jì)一下分布做到心里有數(shù)。這一步對(duì)后面的訓(xùn)練參數(shù)選擇很有用如果坑洼目標(biāo)普遍很小就該考慮加大推理尺寸如果標(biāo)注很松就別對(duì) mAP 報(bào)太高的期望。3.3 確認(rèn)類別定義單類還是多類解壓之后一定要打開data.yaml看一眼path: /data/datasets/pothole train: images/train val: images/val names: 0: pothole如果 names 只有一個(gè)pothole那就是單類別檢測(cè)。如果還有crack、patch、manhole之類就要搞清楚各個(gè)類別的含義。這對(duì)訓(xùn)練配置很重要——多類別時(shí)損失函數(shù)計(jì)算會(huì)考慮類別維度類別數(shù)不匹配時(shí)訓(xùn)練會(huì)直接報(bào)錯(cuò)。萬(wàn)一命名對(duì)不上比如names里寫的是韓語(yǔ)或日語(yǔ)而標(biāo)注文件里的class_id映射關(guān)系又不明確那就要人工核對(duì)類別編號(hào)了。這種情況雖然少見但在從海外站點(diǎn)下載的數(shù)據(jù)集里偶發(fā)過(guò)。4. 用 YOLOv8 跑通自己的訓(xùn)練流程4.1 環(huán)境準(zhǔn)備安裝 PyTorch 與 Ultralytics數(shù)據(jù)集沒(méi)問(wèn)題之后進(jìn)入訓(xùn)練階段。現(xiàn)在主流方案是 YOLOv8來(lái)自 Ultralytics。它最大的優(yōu)勢(shì)是接口統(tǒng)一從訓(xùn)練到導(dǎo)出再到推理幾行命令就能搞定。先確認(rèn) Python 版本和 GPU 環(huán)境python --version nvidia-smi推薦 Python 3.9 以上CUDA 11.8 或 12.1 均可。然后安裝依賴pip install ultralytics安裝完成后驗(yàn)證一下版本import ultralytics ultralytics.checks()4.2 編寫數(shù)據(jù)配置文件訓(xùn)練前需要先寫一個(gè) YAML 配置文件。新建pothole.yamlpath: /data/datasets/pothole train: images/train val: images/val test: images/test nc: 1 names: 0: pothole這里最需要注意的是path、train、val三個(gè)字段的路徑。train和val既可以是絕對(duì)路徑也可以是相對(duì)于path的相對(duì)路徑。如果路徑配置錯(cuò)誤訓(xùn)練會(huì)在加載數(shù)據(jù)階段直接報(bào)錯(cuò)。如果數(shù)據(jù)集本身沒(méi)有劃分 train/val需要自己寫腳本劃分。推薦按 8:2 或 9:1 的比例隨機(jī)劃分注意要保證圖片和標(biāo)注文件同步移動(dòng)import random from pathlib import Path import shutil random.seed(42) img_dir Path(images) label_dir Path(labels) val_ratio 0.2 all_imgs list(img_dir.glob(*.jpg)) random.shuffle(all_imgs) val_count int(len(all_imgs) * val_ratio) val_imgs all_imgs[:val_count] train_imgs all_imgs[val_count:] for split, imgs in [(train, train_imgs), (val, val_imgs)]: (img_dir / split).mkdir(exist_okTrue) (label_dir / split).mkdir(exist_okTrue) for img in imgs: shutil.move(str(img), str(img_dir / split / img.name)) label label_dir / (img.stem .txt) if label.exists(): shutil.move(str(label), str(label_dir / split / label.name))跑完這個(gè)腳本目錄結(jié)構(gòu)就會(huì)變成 YOLO 需要的images/train、images/val、labels/train、labels/val的形態(tài)。4.3 訓(xùn)練命令與關(guān)鍵參數(shù)解讀環(huán)境就緒、配置寫好后執(zhí)行訓(xùn)練yolo detect train \ datapothole.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ patience20 \ projectruns/pothole \ nameexp001每個(gè)參數(shù)的作用都值得說(shuō)清楚。modelyolov8s.pt這里用的不是隨機(jī)初始化而是在 COCO 數(shù)據(jù)集上預(yù)訓(xùn)練過(guò)的權(quán)重。遷移學(xué)習(xí)的好處是模型已經(jīng)學(xué)到了通用的圖像特征我們只需要在坑洼數(shù)據(jù)集上微調(diào)。如果你的顯存緊張可以換成yolov8n.pt如果追求精度用yolov8m.pt或yolov8l.pt。epochs100訓(xùn)練輪數(shù)。坑洼數(shù)據(jù)集一般不大50~100 輪已經(jīng)足夠收斂。配合patience20可以開啟早停機(jī)制也就是說(shuō)連續(xù) 20 輪驗(yàn)證集指標(biāo)沒(méi)有提升訓(xùn)練自動(dòng)停止防止過(guò)擬合。imgsz640訓(xùn)練時(shí)的輸入尺寸。YOLOv8 默認(rèn)是 640。如果坑洼目標(biāo)偏小可以試著提高到 1280小目標(biāo)的召回率通常會(huì)明顯改善但顯存占用會(huì)成倍上漲需要根據(jù)自己的顯卡情況權(quán)衡。batch16批大小。總覽顯存來(lái)看一般imgsz640時(shí)batch16大約需要 12~16GB 顯存。顯存不夠就降到 8 或 4顯存充足也可以用更大的 batch。運(yùn)行過(guò)程中終端會(huì)輸出每個(gè) epoch 的box_loss、cls_loss、dfl_loss、precision、recall、mAP50、mAP50-95等指標(biāo)。這里簡(jiǎn)單解釋一下mAP50是 IoU 閾值為 0.5 時(shí)的平均精度直觀理解就是預(yù)測(cè)框和真實(shí)框的重疊程度達(dá)到一半以上就算檢測(cè)正確mAP50-95是 0.5 到 0.95 多個(gè)閾值下的平均更能反映框位置的精準(zhǔn)度。坑洼檢測(cè)對(duì)框的精準(zhǔn)度要求沒(méi)有工業(yè)零件檢測(cè)那么嚴(yán)苛所以mAP50是重點(diǎn)參考指標(biāo)。等待訓(xùn)練結(jié)束后結(jié)果會(huì)輸出到runs/pothole/exp001/目錄里面有weights/best.pt驗(yàn)證集上表現(xiàn)最好的權(quán)重weights/last.pt最后一次 epoch 的權(quán)重results.png損失曲線和各指標(biāo)變化曲線confusion_matrix.png混淆矩陣val_batch_pred.jpg驗(yàn)證集預(yù)測(cè)結(jié)果可視化圖。4.4 結(jié)果評(píng)估與導(dǎo)出查看results.png時(shí)重點(diǎn)關(guān)注兩點(diǎn)一是train/box_loss和val/box_loss是否同步下降如果訓(xùn)練損失降了但驗(yàn)證損失反彈說(shuō)明過(guò)擬合了二是metrics/mAP50是否還有上升趨勢(shì)如果最后的曲線仍然明顯向上說(shuō)明epochs設(shè)置少了可以增加輪次繼續(xù)訓(xùn)練。評(píng)估完成后用best.pt在單獨(dú)測(cè)試集上跑推理yolo detect predict \ modelruns/pothole/exp001/weights/best.pt \ source/data/datasets/pothole/images/test \ conf0.25 \ saveTrueconf0.25表示置信度閾值低于 0.25 的檢測(cè)結(jié)果會(huì)被過(guò)濾掉。實(shí)際部署時(shí)這個(gè)值可以根據(jù)誤報(bào)率要求調(diào)整。如果誤報(bào)多就提高閾值到 0.4~0.5如果漏檢多就降低閾值。導(dǎo)出為 ONNX 格式做邊緣部署yolo export modelruns/pothole/exp001/weights/best.pt formatonnx導(dǎo)出后可以在支持 ONNX 的推理框架里部署方便嵌入到巡檢終端或邊緣設(shè)備。5. 常見問(wèn)題與排查實(shí)錄5.1 訓(xùn)練踩坑速查表下面這個(gè)表是我實(shí)際處理數(shù)據(jù)集時(shí)攢下來(lái)的高頻問(wèn)題直接對(duì)照排查即可?,F(xiàn)象可能原因解決方法解壓報(bào)file is not a zip file文件實(shí)際是 HTML 錯(cuò)誤頁(yè)或下載不完整用file命令確認(rèn)類型重新下載解壓報(bào)could not find EOCDzip 尾部損壞、下載被截?cái)嘞萿nzip -t測(cè)試用zip -FF嘗試修復(fù)不行就重新下載解壓后文件名亂碼zip 編碼與系統(tǒng)不一致用unzip -O GBK或改用 7-Zip訓(xùn)練時(shí)報(bào)數(shù)據(jù)路徑錯(cuò)誤pothole.yaml中 path 配置不對(duì)檢查path字段是否指向數(shù)據(jù)集根目錄訓(xùn)練時(shí) loss 為 nan學(xué)習(xí)率過(guò)大或標(biāo)注存在極端值注釋學(xué)習(xí)率檢查標(biāo)簽坐標(biāo)是否超出 0~1 范圍模型漏檢小坑洼輸入尺寸太小或小目標(biāo)樣本少imgsz1280重新訓(xùn)練或?qū)π∧繕?biāo)區(qū)域做增強(qiáng)采樣誤檢率很高陰影水漬被當(dāng)成坑洼背景負(fù)樣本不夠豐富增加無(wú)坑洼的負(fù)樣本圖片提高置信度閾值驗(yàn)證集 mAP 高但實(shí)際測(cè)試效果差數(shù)據(jù)集劃分有泄漏或過(guò)擬合檢查 val 集是否與 train 集有重疊用單獨(dú)外部數(shù)據(jù)測(cè)試5.2 獨(dú)家避坑技巧這里分享三個(gè)我實(shí)際摸索出來(lái)的技巧都是常規(guī)文檔里不太會(huì)寫的。技巧一先用小模型跑通流程再換大模型。很多新手一上來(lái)就用yolov8x加imgsz1280結(jié)果顯存爆了、訓(xùn)練時(shí)間長(zhǎng)了連代碼流程問(wèn)題都還沒(méi)定位到。我建議先用yolov8n、imgsz640、epochs20快速跑一遍確認(rèn)數(shù)據(jù)加載、標(biāo)注讀取、評(píng)估環(huán)節(jié)沒(méi)問(wèn)題再換大模型和更高分辨率。這樣可以快速暴露流程問(wèn)題而不是在漫長(zhǎng)的訓(xùn)練中浪費(fèi)時(shí)間。技巧二訓(xùn)練前檢查標(biāo)注文件的坐標(biāo)是否都落在 0~1 范圍內(nèi)。YOLO 格式要求坐標(biāo)歸一化到 0~1但偶爾會(huì)有標(biāo)注文件寫出大于 1 或者負(fù)數(shù)。這種問(wèn)題不會(huì)立刻報(bào)錯(cuò)卻會(huì)污染訓(xùn)練數(shù)據(jù)讓損失函數(shù)震蕩。寫個(gè)簡(jiǎn)單腳本掃一遍from pathlib import Path bad_files [] for label_path in Path(labels/train).glob(*.txt): with open(label_path) as f: for line in f: vals line.split() if len(vals) ! 5: bad_files.append((str(label_path), 列數(shù)錯(cuò)誤)) break try: cls, xc, yc, bw, bh map(float, vals) except ValueError: bad_files.append((str(label_path), 數(shù)值解析失敗)) break if not (0 xc 1 and 0 yc 1 and 0 bw 1 and 0 bh 1): bad_files.append((str(label_path), 坐標(biāo)越界)) break print(異常文件數(shù):, len(bad_files)) for f, reason in bad_files[:20]: print(f, reason)技巧三負(fù)樣本一定要加??油輽z測(cè)最常踩的坑就是誤報(bào)。有的數(shù)據(jù)集只有“有坑洼的正樣本”沒(méi)有“無(wú)坑洼的負(fù)樣本”模型沒(méi)見過(guò)沒(méi)有坑洼的路面自然就容易把一切路面紋理當(dāng)成坑。訓(xùn)練集里加入 10%~20% 沒(méi)有坑洼的路面圖片標(biāo)注文件為空 txt能顯著降低誤報(bào)率。5.3 推理階段的效果調(diào)優(yōu)思路模型訓(xùn)練完不等于工程落地。實(shí)際部署時(shí)推理置信度閾值、NMS 參數(shù)、輸入尺寸都會(huì)影響最終效果。如果誤報(bào)高先調(diào)conf比如從 0.25 調(diào)到 0.4如果同一個(gè)坑被框出多個(gè)結(jié)果可以調(diào) NMS 的 IoU 閾值通常默認(rèn) 0.45可以調(diào)到 0.5 或 0.6 減少重疊框。還有一個(gè)小技巧如果目標(biāo)普遍很小可以在推理時(shí)把輸入尺寸增大同時(shí)配合augmentTrue開啟 Test Time AugmentationTTA雖然推理速度會(huì)變慢但小目標(biāo)的召回率會(huì)有所提升。我個(gè)人在實(shí)際操作中的體會(huì)是坑洼檢測(cè)這類數(shù)據(jù)集的處理流程80% 的時(shí)間其實(shí)花在數(shù)據(jù)準(zhǔn)備上真正訓(xùn)練模型的時(shí)間只占一小部分。數(shù)據(jù)集的解壓、校驗(yàn)、清洗、可視化這些環(huán)節(jié)看著不起眼卻直接決定了后面訓(xùn)練的上限。如果你手里恰好也有一個(gè)類似的數(shù)據(jù)集建議先把今天這套流程過(guò)一遍再開始訓(xùn)練你會(huì)發(fā)現(xiàn)在參數(shù)調(diào)優(yōu)時(shí)少走很多彎路。最后再分享一個(gè)擴(kuò)展思路拿到這個(gè)坑洼檢測(cè)數(shù)據(jù)集之后后續(xù)還可以往兩個(gè)方向走一是把訓(xùn)練好的模型導(dǎo)出到邊緣設(shè)備比如 Jetson 或樹莓派做實(shí)時(shí)巡檢二是結(jié)合道路裂縫檢測(cè)、路面修補(bǔ)檢測(cè)一起做多任務(wù)識(shí)別。這個(gè)數(shù)據(jù)集本身是第一步但后面能延伸出來(lái)的應(yīng)用空間還挺大的。本文還有配套的精品資源點(diǎn)擊獲取