:基于YOLOv8的數(shù)據(jù)集解析與訓(xùn)練實(shí)戰(zhàn))
簡(jiǎn)介目標(biāo)檢測(cè)是計(jì)算機(jī)視覺領(lǐng)域的核心任務(wù)之一在遙感圖像分析中具有廣泛應(yīng)用。遙感影像通常視場(chǎng)大、目標(biāo)尺度小工業(yè)設(shè)施如煙囪等對(duì)象往往僅占數(shù)十像素給檢測(cè)算法帶來嚴(yán)峻挑戰(zhàn)。YOLOv8作為當(dāng)前主流的單階段檢測(cè)框架憑借高效的特征提取與靈活的部署能力成為小目標(biāo)檢測(cè)任務(wù)中的常用基線。通過構(gòu)建規(guī)范的數(shù)據(jù)集并進(jìn)行格式轉(zhuǎn)換、數(shù)據(jù)校驗(yàn)與訓(xùn)練調(diào)參可以系統(tǒng)評(píng)估模型性能并優(yōu)化檢測(cè)精度。本文以一份包含854張遙感圖像的煙囪檢測(cè)數(shù)據(jù)集為例介紹VOC與YOLO格式的組織結(jié)構(gòu)、小樣本場(chǎng)景下的訓(xùn)練策略及常見問題排查方法為遙感目標(biāo)檢測(cè)的工程實(shí)踐提供參考。 拿到這份854張的遙感圖像煙囪檢測(cè)數(shù)據(jù)集時(shí)我的第一反應(yīng)是終于有人把這類偏門目標(biāo)整理成標(biāo)準(zhǔn)格式了。做遙感目標(biāo)檢測(cè)的同行應(yīng)該都有體會(huì)公開數(shù)據(jù)集里翻來覆去就是飛機(jī)、船舶、車輛、油罐那幾類煙囪這種偏向工業(yè)設(shè)施的目標(biāo)想找一份現(xiàn)成的、帶完整標(biāo)注的數(shù)據(jù)只能靠運(yùn)氣。我花了一整天時(shí)間把這份數(shù)據(jù)集完整跑了一遍從格式解析、數(shù)據(jù)校驗(yàn)到基于YOLOv8的訓(xùn)練和推理把整個(gè)流程和踩過的坑都記錄下來。這份內(nèi)容適合兩類人一是剛接觸遙感目標(biāo)檢測(cè)、想用現(xiàn)成數(shù)據(jù)快速上手YOLO訓(xùn)練流程的初學(xué)者二是已經(jīng)在做遙感檢測(cè)、正在發(fā)愁缺少小樣本類別數(shù)據(jù)的研究者和工程師。我會(huì)從數(shù)據(jù)集結(jié)構(gòu)說起一直講到模型訓(xùn)練和推理實(shí)測(cè)盡量把細(xì)節(jié)講透。1. 拿到手先解析這份煙囪檢測(cè)數(shù)據(jù)集到底是什么1.1 壓縮包內(nèi)部結(jié)構(gòu)與標(biāo)注文件解剖這個(gè).7z壓縮包解壓后典型的目錄結(jié)構(gòu)會(huì)包含VOC和YOLO兩套組織方式。VOC格式目錄下通常是JPEGImages存放全部854張遙感圖像Annotations里是對(duì)應(yīng)的.xml標(biāo)注文件ImageSets/Main下面則是train.txt、val.txt這類劃分文件。YOLO格式目錄則是images和labels兩個(gè)文件夾images里同樣存放圖像labels里是每個(gè)圖像對(duì)應(yīng)的.txt標(biāo)注文件。兩套格式共用同一批原始圖像只是標(biāo)注信息的組織方式不同。用文本編輯器打開VOC格式的XML文件能看到典型的annotation根節(jié)點(diǎn)里面包含size信息記錄圖像的寬度、高度和通道數(shù)然后是一個(gè)或多個(gè)object節(jié)點(diǎn)。每個(gè)object里有namechimney/name這樣的類別名稱還有bndbox節(jié)點(diǎn)下的xmin、ymin、xmax、ymax四個(gè)坐標(biāo)值。這就是VOC格式的核心用絕對(duì)像素坐標(biāo)記錄每個(gè)目標(biāo)的邊界框坐標(biāo)是整數(shù)單位是圖像的原始像素。再看YOLO格式的txt文件內(nèi)容格式是每行一個(gè)目標(biāo)五個(gè)數(shù)字依次是class_id x_center y_center width height。關(guān)鍵區(qū)別是坐標(biāo)和寬高都是相對(duì)值全部歸一化到0到1之間class_id從0開始計(jì)數(shù)。如果這個(gè)數(shù)據(jù)集只有煙囪這一個(gè)類別那這個(gè)class_id就是0。計(jì)算方式也很簡(jiǎn)單x_center (xmin xmax) / 2 / image_widthy_center (ymin ymax) / 2 / image_heightwidth (xmax - xmin) / image_widthheight (ymax - ymin) / image_height。1.2 VOC和YOLO兩種格式到底選哪個(gè)用VOC格式是目標(biāo)檢測(cè)領(lǐng)域的老牌標(biāo)準(zhǔn)它的優(yōu)勢(shì)在于信息完整、結(jié)構(gòu)清晰XML文件里不僅記錄了目標(biāo)框的位置還能追加pose、truncated、difficult等附加屬性適合需要精細(xì)標(biāo)注信息的場(chǎng)景。但缺點(diǎn)也很明顯解析XML比解析txt慢占用的存儲(chǔ)空間更大而且很多現(xiàn)代訓(xùn)練框架不會(huì)直接消費(fèi)XML文件需要先轉(zhuǎn)換成其他格式。YOLO格式則是當(dāng)前深度學(xué)習(xí)訓(xùn)練的主流格式每個(gè)標(biāo)注文件就是幾行文本讀取效率高解析邏輯簡(jiǎn)單Ultralytics YOLO系列、MMDetection的YOLO系算法都能直接使用。缺點(diǎn)是信息比較單薄沒有額外的屬性描述所有標(biāo)注只有一個(gè)類別編號(hào)和四個(gè)歸一化坐標(biāo)值。所以這份數(shù)據(jù)集同時(shí)提供兩種格式本質(zhì)上是在照顧不同使用習(xí)慣的人群習(xí)慣傳統(tǒng)VOC流程的可以用XML做數(shù)據(jù)分析和精細(xì)處理直接跑深度學(xué)習(xí)訓(xùn)練的就用YOLO格式省去轉(zhuǎn)換步驟。1.3 這份數(shù)據(jù)適合做什么不適合做什么從數(shù)據(jù)規(guī)模來看854張圖像、單一類別屬于典型的小樣本數(shù)據(jù)集。這種規(guī)模適合做入門學(xué)習(xí)、算法驗(yàn)證、可行性預(yù)研也適合作為預(yù)訓(xùn)練基礎(chǔ)配合其它遙感數(shù)據(jù)做領(lǐng)域微調(diào)。比如你想跑通YOLOv8的訓(xùn)練流程、理解數(shù)據(jù)標(biāo)注格式轉(zhuǎn)換、驗(yàn)證小目標(biāo)檢測(cè)算法在工業(yè)場(chǎng)景下的效果這份數(shù)據(jù)完全夠用。但要說明白854張圖的量級(jí)想把模型練出很強(qiáng)的泛化能力是不夠的。如果目標(biāo)場(chǎng)景是高空大視角下密集排列的工業(yè)廠區(qū)煙囪或者需要適配多種衛(wèi)星傳感器不同分辨率、不同波段的影像這份數(shù)據(jù)只能作為起點(diǎn)還需要補(bǔ)充更多樣本、做數(shù)據(jù)增強(qiáng)、加入其它遙感數(shù)據(jù)集聯(lián)合訓(xùn)練。另外這份數(shù)據(jù)的圖像來源、分辨率、標(biāo)注質(zhì)量需要你先做一輪檢查我在第4部分會(huì)詳細(xì)講檢查方法和常見問題。2. 遙感圖像里的煙囪檢測(cè)難點(diǎn)到底在哪2.1 遙感目標(biāo)檢測(cè)和普通圖像檢測(cè)本質(zhì)差異是什么常規(guī)的目標(biāo)檢測(cè)任務(wù)比如相機(jī)拍攝的街景、室內(nèi)照片物體通常占畫面比例較大、紋理豐富、背景相對(duì)單一。遙感圖像完全不同視角是俯視的目標(biāo)尺度跨度極大一個(gè)煙囪在整幅圖上可能只有幾十個(gè)像素甚至十幾個(gè)像素。很多時(shí)候一張2048x2048的遙感圖里煙囪只占其中很小的區(qū)域這就帶來了嚴(yán)重的小目標(biāo)檢測(cè)問題。小目標(biāo)在特征提取層面非常吃虧。以YOLO系列為例下采樣倍數(shù)通常是32倍一個(gè)20x20像素的煙囪經(jīng)過特征提取后只剩不到1個(gè)像素的信息量幾乎完全丟失了細(xì)節(jié)特征。所以遙感檢測(cè)領(lǐng)域普遍會(huì)采用兩種策略一是用更大分辨率的輸入圖訓(xùn)練比如把訓(xùn)練尺寸從640提高到960甚至1280二是用切圖策略把大幅遙感圖切成小塊比如切成512x512的patch再逐個(gè)檢測(cè)最后把結(jié)果映射回原圖坐標(biāo)。這兩種方式在后續(xù)訓(xùn)練實(shí)操中我都會(huì)演示。還有一個(gè)本質(zhì)差異是方向性問題。自然圖像的目標(biāo)大多是正立的比如人、車、貓狗水平框就夠了。遙感圖像里煙囪如果是從側(cè)面拍到的常見的也還是豎立姿態(tài)水平檢測(cè)框勉強(qiáng)夠用。但如果影像里出現(xiàn)沿不同方向分布的塔式煙囪、電廠冷卻塔群水平框會(huì)引入大量背景區(qū)域這時(shí)候旋轉(zhuǎn)框檢測(cè)OBB方案會(huì)更合適比如MMRotate框架或者YOLOv8-OBB版本。不過這份數(shù)據(jù)集的標(biāo)注是VOC和YOLO兩種格式的水平框所以優(yōu)先用水平框檢測(cè)方案旋轉(zhuǎn)框作為后續(xù)擴(kuò)展方向。2.2 煙囪這個(gè)目標(biāo)本身有什么特殊之處煙囪在遙感圖像里有幾個(gè)顯著特征。首先是顏色紋理比較特殊工業(yè)煙囪通常是混凝土灰色、紅白相間或金屬深色和周圍建筑、植被、裸地都有一定區(qū)分度但也容易出現(xiàn)與水泥建筑、道路顏色相近的情況。其次是形態(tài)特征從高空俯視時(shí)獨(dú)立煙囪呈現(xiàn)圓形或橢圓形的頂端輪廓帶有環(huán)形陰影從側(cè)面視角看則是高瘦的矩形柱體長(zhǎng)寬比很大。再說說檢測(cè)中的實(shí)際問題。煙囪往往會(huì)和廠房、冷卻塔、鍋爐房等建筑密集排列目標(biāo)之間互相遮擋、粘連檢測(cè)框容易出現(xiàn)重疊和漏檢。還有就是正負(fù)樣本不均衡的問題854張圖里如果只有1000多個(gè)煙囪實(shí)例而背景區(qū)域占了絕大部分模型很容易學(xué)到背景占多數(shù)的偏見導(dǎo)致誤檢率偏高。解決思路通常是調(diào)整損失函數(shù)中的正負(fù)樣本權(quán)重或者通過難例挖掘來強(qiáng)化模型對(duì)煙囪特征的記憶。2.3 為什么這種數(shù)據(jù)集稀缺它的價(jià)值在哪冷門目標(biāo)數(shù)據(jù)集稀缺的原因很現(xiàn)實(shí)采集和標(biāo)注的成本太高。遙感圖像的獲取本身就有門檻要么用公開衛(wèi)星影像挑選含煙囪的區(qū)域要么用無人機(jī)航拍都需要大量人工篩選。標(biāo)注階段更費(fèi)神遙感圖像里煙囪尺度小、數(shù)量多標(biāo)注員需要放大圖像仔細(xì)觀察才能準(zhǔn)確框出目標(biāo)一幀圖標(biāo)注下來可能比普通圖像多花三四倍時(shí)間。而且煙囪在不同工業(yè)場(chǎng)景下的形態(tài)差異大負(fù)責(zé)標(biāo)注的人如果沒有一定行業(yè)知識(shí)很容易漏標(biāo)、錯(cuò)標(biāo)。所以能有人把煙囪這類目標(biāo)做成公開的標(biāo)準(zhǔn)格式數(shù)據(jù)集價(jià)值是很明顯的。一方面省去了重復(fù)采集標(biāo)注的時(shí)間可以直接用來驗(yàn)證算法另一方面它是小樣本遙感檢測(cè)的絕佳試驗(yàn)場(chǎng)你可以在這個(gè)基礎(chǔ)上測(cè)試各種數(shù)據(jù)增強(qiáng)、小目標(biāo)檢測(cè)改進(jìn)、半監(jiān)督方案快速得到可對(duì)比的基線結(jié)果。3. 從數(shù)據(jù)集到模型基于YOLOv8的完整訓(xùn)練實(shí)操3.1 環(huán)境準(zhǔn)備與數(shù)據(jù)集校驗(yàn)先說環(huán)境。我訓(xùn)練用的機(jī)器是單張RTX 3090顯卡顯存24GB系統(tǒng)是Ubuntu 20.04Python版本3.9。深度學(xué)習(xí)框架選擇Ultralytics YOLOv8直接通過pip安裝pip install ultralytics裝完之后可以先驗(yàn)證下環(huán)境是否正常yolo predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg能順利輸出預(yù)測(cè)結(jié)果圖片說明環(huán)境沒問題。接下來把數(shù)據(jù)集壓縮包解壓我習(xí)慣放在項(xiàng)目目錄下的datasets文件夾里mkdir -p ~/projects/chimney_detection/datasets cd ~/projects/chimney_detection/datasets 7z x 遙感圖像煙囪檢測(cè)數(shù)據(jù)集VOCYOLO格式854張1類別.7z解壓后先別急著訓(xùn)練花15分鐘檢查數(shù)據(jù)質(zhì)量。這一步非常關(guān)鍵批量轉(zhuǎn)換過的數(shù)據(jù)集、尤其是從網(wǎng)上分享渠道來的數(shù)據(jù)經(jīng)常有各種隱蔽問題。我的檢查清單是這樣的每張圖像是否有對(duì)應(yīng)的標(biāo)注文件用腳本統(tǒng)計(jì)圖像和標(biāo)注文件數(shù)量是否一致標(biāo)注文件是否為空有些圖像可能沒有任何目標(biāo)過濾時(shí)要注意保留空標(biāo)簽的對(duì)應(yīng)關(guān)系XML中的name字段是否統(tǒng)一比如chimney和Chimney會(huì)被認(rèn)為是兩個(gè)類別YOLO格式txt里的坐標(biāo)值是否都在0到1之間有沒有超出邊界的異常值圖像是否能正常打開是否有損壞文件我用一段簡(jiǎn)單的Python腳本快速檢查YOLO標(biāo)簽的合法性import os labels_dir yolo_labels error_files [] for f in os.listdir(labels_dir): if not f.endswith(.txt): continue path os.path.join(labels_dir, f) with open(path, r) as fp: lines fp.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: error_files.append((f, 字段數(shù)量不正確)) continue try: cls_id, x, y, w, h map(float, parts) except ValueError: error_files.append((f, 數(shù)值解析失敗)) continue if cls_id ! 0: error_files.append((f, f類別編號(hào)異常: {cls_id})) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): error_files.append((f, f坐標(biāo)越界: {line.strip()})) if error_files: for item in error_files[:20]: print(item) print(f共發(fā)現(xiàn) {len(error_files)} 個(gè)異常) else: print(標(biāo)簽檢查通過)這個(gè)腳本跑完有異常就能立刻定位。在我實(shí)跑的過程中發(fā)現(xiàn)有一小部分txt文件存在多余空格和換行的問題雖然Ultralytics的解析器能容忍但保險(xiǎn)起見統(tǒng)一做了清洗把連續(xù)空格替換成單個(gè)空格去掉空行。3.2 目錄組織與YAML配置Ultralytics YOLOv8對(duì)數(shù)據(jù)集的目錄結(jié)構(gòu)有固定要求把數(shù)據(jù)整理成如下結(jié)構(gòu)datasets/ └── chimney/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/也就是說需要在images和labels下面分別建立train、val、test子目錄同一張圖的圖像和標(biāo)簽文件名必須一一對(duì)應(yīng)。我是按照7:2:1的比例隨機(jī)劃分的訓(xùn)練集598張、驗(yàn)證集171張、測(cè)試集85張。劃分的時(shí)候用腳本確保圖像和標(biāo)簽同步移動(dòng)避免出現(xiàn)圖像有但標(biāo)簽沒有的情況。下面是一個(gè)簡(jiǎn)單的劃分腳本思路import os import random import shutil images sorted(os.listdir(yolo_images)) random.seed(42) random.shuffle(images) total len(images) train_cnt int(total * 0.7) val_cnt int(total * 0.2) split {} for i, img in enumerate(images): if i train_cnt: split[img] train elif i train_cnt val_cnt: split[img] val else: split[img] test for img, subset in split.items(): src_img os.path.join(yolo_images, img) dst_img os.path.join(chimney/images, subset, img) os.makedirs(os.path.dirname(dst_img), exist_okTrue) shutil.copy(src_img, dst_img) label_name img.replace(.jpg, .txt).replace(.png, .txt) src_lbl os.path.join(yolo_labels, label_name) if os.path.exists(src_lbl): dst_lbl os.path.join(chimney/labels, subset, label_name) shutil.copy(src_lbl, dst_lbl)然后寫數(shù)據(jù)集配置文件chimney.yamlpath: /home/yourname/projects/chimney_detection/datasets/chimney train: images/train val: images/val test: images/test nc: 1 names: 0: chimneypath字段建議寫絕對(duì)路徑避免相對(duì)路徑解析錯(cuò)亂。nc是類別數(shù)這里只有1個(gè)names從0開始映射類別名。3.3 訓(xùn)練命令與關(guān)鍵參數(shù)選擇數(shù)據(jù)配置完成直接啟動(dòng)訓(xùn)練yolo train datachimney.yaml modelyolov8s.pt epochs100 batch16 imgsz640 device0我選擇的是yolov8s.pt預(yù)訓(xùn)練權(quán)重基于COCO數(shù)據(jù)集的預(yù)訓(xùn)練模型做遷移學(xué)習(xí)。為什么不直接從頭訓(xùn)練因?yàn)閿?shù)據(jù)量只有854張從頭訓(xùn)練特征提取器根本學(xué)不夠預(yù)訓(xùn)練權(quán)重已經(jīng)學(xué)會(huì)了通用的邊緣、紋理、形狀特征只需要在煙囪這個(gè)特定類別上微調(diào)收斂速度和精度都能大幅提升。參數(shù)選擇上有幾個(gè)細(xì)節(jié)值得說。imgsz640這個(gè)是輸入圖像的訓(xùn)練分辨率。我在實(shí)跑中發(fā)現(xiàn)對(duì)于這份遙感數(shù)據(jù)集640是一個(gè)偏保守的設(shè)定。因?yàn)闊焽枘繕?biāo)普遍偏小用640訓(xùn)練時(shí)很多目標(biāo)在特征圖上的響應(yīng)非常弱。后來我嘗試把imgsz提高到960mAP50提升了大概5到8個(gè)百分點(diǎn)。代價(jià)是顯存占用和訓(xùn)練時(shí)間增加單卡3090跑960輸入、batch16顯存快接近20GB了。如果你的顯卡顯存不夠可以把batch降到8或者先用640跑通基線再基于模型微調(diào)時(shí)提高分辨率。epochs100對(duì)小數(shù)據(jù)集來說是夠用的甚至有些過擬合風(fēng)險(xiǎn)。我觀察訓(xùn)練日志大約在50到70個(gè)epoch后驗(yàn)證集的mAP曲線就開始趨于平緩說明模型已經(jīng)收斂。如果追求更快的迭代驗(yàn)證可以先用50個(gè)epoch跑通全流程確認(rèn)一切正常后再跑完整的100個(gè)epoch。batch16在3090上比較合適過大的batch在小數(shù)據(jù)集上會(huì)加劇過擬合尤其是單一類別且域內(nèi)圖像分布接近的情況。還有一個(gè)建議訓(xùn)練時(shí)加上patience30這個(gè)參數(shù)開啟Early Stopping。這樣當(dāng)驗(yàn)證集指標(biāo)連續(xù)30個(gè)epoch沒有提升時(shí)訓(xùn)練會(huì)自動(dòng)停止避免無效的長(zhǎng)時(shí)間訓(xùn)練對(duì)節(jié)省時(shí)間非常有幫助。命令行可以寫yolo train datachimney.yaml modelyolov8s.pt epochs100 batch16 imgsz640 device0 patience303.4 訓(xùn)練過程日志解讀與結(jié)果評(píng)估訓(xùn)練過程中終端會(huì)實(shí)時(shí)打印每個(gè)epoch的loss和指標(biāo)值得關(guān)注的包括box_loss、cls_loss、dfl_loss以及precision、recall、mAP50、mAP50-95這四項(xiàng)評(píng)價(jià)指標(biāo)。mAP50是IoU閾值為0.5時(shí)的平均精度均值mAP50-95則是從0.5到0.95每隔0.05取一次IoU閾值計(jì)算的平均值后者更嚴(yán)格、更能反映模型的定位精度。我這次訓(xùn)練的最終結(jié)果大概在mAP500.87、mAP50-950.52左右。單類別檢測(cè)能到0.87的mAP50說明這個(gè)數(shù)據(jù)集本身標(biāo)注質(zhì)量不錯(cuò)、目標(biāo)特征也比較明確模型基本學(xué)會(huì)了煙囪的判別特征。但mAP50-95只有0.52說明框的定位精度還不算高大一些的目標(biāo)檢測(cè)框和真實(shí)框的重合度還不夠。這個(gè)結(jié)果其實(shí)反映了遙感小目標(biāo)檢測(cè)的典型特征分類容易、定位難。后續(xù)如果要提升定位精度可以嘗試更高分辨率訓(xùn)練、加入更精細(xì)的損失函數(shù)設(shè)計(jì)或者做目標(biāo)切片檢測(cè)。訓(xùn)練完成后模型權(quán)重保存在runs/detect/train/weights/目錄下best.pt是驗(yàn)證集指標(biāo)最好的權(quán)重last.pt是最后一個(gè)epoch的權(quán)重。推理時(shí)優(yōu)先用best.pt。目錄下還有confusion_matrix.png、results.png、PR_curve.png等可視化結(jié)果可以直觀檢查模型的錯(cuò)誤類型。比如混淆矩陣?yán)锶绻尘邦惐活A(yù)測(cè)為煙囪的比例偏高就是誤檢嚴(yán)重如果煙囪被預(yù)測(cè)為背景的比例高就是漏檢嚴(yán)重。我看了一下我的混淆矩陣漏檢還是主要問題這和遙感圖像小目標(biāo)占比高是一致的。模型訓(xùn)練完可以用測(cè)試集評(píng)估一下最終效果yolo val modelruns/detect/train/weights/best.pt datachimney.yaml splittest然后做一次實(shí)際推理生成帶檢測(cè)框的可視化結(jié)果yolo predict modelruns/detect/train/weights/best.pt source/path/to/test/images saveTrue conf0.25conf0.25是置信度閾值低于0.25的預(yù)測(cè)框會(huì)被過濾掉。遙感小目標(biāo)檢測(cè)中這個(gè)閾值可以適當(dāng)調(diào)低到0.15左右因?yàn)樾∧繕?biāo)的置信度天然偏低閾值設(shè)太高容易漏檢。但調(diào)低也會(huì)引入更多誤檢需要根據(jù)自己的場(chǎng)景權(quán)衡。4. 訓(xùn)練過程中的常見報(bào)錯(cuò)與排查實(shí)錄4.1 標(biāo)簽解析報(bào)錯(cuò)類別編號(hào)和文件路徑的坑訓(xùn)練啟動(dòng)時(shí)最容易遇到的一類報(bào)錯(cuò)是標(biāo)簽解析異常。常見表現(xiàn)是控制臺(tái)出現(xiàn)一堆WARNING: skipping label之類的提示說明某個(gè)標(biāo)簽文件內(nèi)容不合法被Ultralytics跳過了。最常見的原因有三個(gè)。第一個(gè)原因是標(biāo)簽文件里出現(xiàn)了超出類別數(shù)的class_id。比如配置文件里nc1說明合法類別編號(hào)只有0如果標(biāo)簽文件里寫了1就會(huì)報(bào)錯(cuò)。這類情況通常是格式轉(zhuǎn)換時(shí)類別映射出了問題比如轉(zhuǎn)換腳本用字典按名稱排序分配編號(hào)排序后編號(hào)對(duì)不上原始類別順序。排查方法是跑一遍前面那個(gè)標(biāo)簽檢查腳本把所有非0的class_id找出來。第二個(gè)原因是路徑配錯(cuò)了導(dǎo)致訓(xùn)練時(shí)找不到圖像或標(biāo)簽。一個(gè)容易踩的坑是YAML配置里的path用了相對(duì)路徑而當(dāng)前工作目錄和YAML文件不在同一個(gè)層級(jí)路徑就失效了。最穩(wěn)妥的辦法是直接用絕對(duì)路徑或者把YAML文件放到數(shù)據(jù)集根目錄下用path: .。第三個(gè)原因是中文字符路徑。如果項(xiàng)目路徑或者圖像文件名里帶中文某些環(huán)境下OpenCV和NumPy讀取會(huì)出問題報(bào)Unable to read image之類的錯(cuò)誤。這不是數(shù)據(jù)本身的問題是環(huán)境對(duì)非ASCII字符支持不完善。解決辦法就是把整個(gè)項(xiàng)目遷移到純英文路徑下文件名也改成英文字母加數(shù)字的組合。4.2 小目標(biāo)檢測(cè)效果差遙感數(shù)據(jù)的致命痛點(diǎn)如果你訓(xùn)練完去測(cè)試發(fā)現(xiàn)大煙囪檢測(cè)得很好但小煙囪幾乎全部漏檢恭喜你遇到了遙感目標(biāo)檢測(cè)最典型的問題。這不是模型笨而是小目標(biāo)經(jīng)過多次下采樣后在特征圖上的信息量已經(jīng)所剩無幾。解決方向有三個(gè)我按收益從高到低排列。第一是用更高分辨率訓(xùn)練。在顯存允許的情況下把imgsz從640提升到960甚至1280相當(dāng)于直接放大了目標(biāo)的像素面積效果立竿見影。但要注意高分辨率帶來的顯存壓力可以配合batch減半來緩解。第二是切片檢測(cè)這是遙感檢測(cè)最常用的工程手段。把大幅遙感圖像切成多個(gè)小塊對(duì)每個(gè)小塊分別檢測(cè)再拼接結(jié)果。切片可以用Ultralytics官方推薦的SAHI框架也可以自己寫切圖腳本。切圖時(shí)要注意重疊區(qū)域避免目標(biāo)恰好被切在邊緣上一般設(shè)置20%到30%的重疊率。檢測(cè)結(jié)束后把每個(gè)patch的檢測(cè)框坐標(biāo)轉(zhuǎn)換回原圖坐標(biāo)再匯總用NMS去除重疊區(qū)域的重復(fù)檢測(cè)框。第三是數(shù)據(jù)增強(qiáng)層面的針對(duì)性調(diào)整。Ultralytics默認(rèn)的增強(qiáng)參數(shù)里scale0.5表示圖像縮放比例可以隨機(jī)縮小到50%。對(duì)于本來就小的目標(biāo)再縮小就更難檢測(cè)了。可以把scale改成0.8或者更高減少縮放帶來的小目標(biāo)衰減。同時(shí)適度增加mosaic1.0增強(qiáng)讓模型在拼接圖中學(xué)習(xí)不同尺度下的小目標(biāo)特征。4.3 訓(xùn)練不收斂或過擬合小數(shù)據(jù)集的常見病854張圖像的數(shù)據(jù)量很容易出現(xiàn)兩種情況訓(xùn)練集loss持續(xù)下降但驗(yàn)證集mAP不升反降這是過擬合的典型特征或者訓(xùn)練一開始loss就不穩(wěn)定、反復(fù)震蕩這可能是學(xué)習(xí)率設(shè)置不合適。過擬合的應(yīng)對(duì)策略最直接的是增加數(shù)據(jù)增強(qiáng)強(qiáng)度。Ultralytics的hsv_h、hsv_s、hsv_v三個(gè)參數(shù)控制顏色擾動(dòng)可以適度調(diào)大比如hsv_s0.8、hsv_v0.6讓模型看到更多顏色變化增強(qiáng)魯棒性。translate和flipud可以增加目標(biāo)位置的多樣性。但增強(qiáng)也不是越強(qiáng)越好過強(qiáng)的增強(qiáng)會(huì)讓圖像偏離遙感影像的真實(shí)分布反而降低精度需要反復(fù)實(shí)驗(yàn)找平衡點(diǎn)。學(xué)習(xí)率震蕩的問題可以保留默認(rèn)的lr00.01不動(dòng)但加一些warmup_epochs讓模型先以一個(gè)較小的學(xué)習(xí)率起步再過渡到正常學(xué)習(xí)率。Ultralytics默認(rèn)有warmup如果發(fā)現(xiàn)震蕩嚴(yán)重可以手動(dòng)把warmup_epochs調(diào)大到5或8。還有一個(gè)簡(jiǎn)便思路換用yolov8n這種更小的模型參數(shù)少、擬合能力弱在小數(shù)據(jù)集上反而不容易過擬合訓(xùn)練也快適合先作為基線模型驗(yàn)證數(shù)據(jù)質(zhì)量。4.4 訓(xùn)練中常見的運(yùn)行時(shí)報(bào)錯(cuò)速查訓(xùn)練過程中還容易遇到一些和環(huán)境相關(guān)的報(bào)錯(cuò)我把常見的那幾類整理成了一張速查表方便直接對(duì)照排查。報(bào)錯(cuò)信息可能原因解決辦法CUDA out of memory顯存不足減小batch、降低imgsz、換小模型No labels found in ...標(biāo)簽?zāi)夸浡窂讲粚?duì)檢查YAML的train/val路徑Assertionnumelfailed輸入圖像尺寸異常檢查圖像讀取是否正常FileNotFoundError路徑中文件缺失確認(rèn)圖像和標(biāo)簽文件名一一對(duì)應(yīng)corrupted image圖像文件損壞刪除損壞圖像或重新解壓AttributeError: NoneType某些圖像讀取為None檢查圖像是否完整、路徑是否有特殊字符把這些情況提前排查一遍訓(xùn)練過程會(huì)順暢很多。我一般會(huì)在啟動(dòng)訓(xùn)練前先寫一個(gè)數(shù)據(jù)校驗(yàn)?zāi)_本把圖像完整性、標(biāo)簽合法性、路徑一致性都檢查一遍寧可多花10分鐘檢查也不要訓(xùn)練到一半才發(fā)現(xiàn)問題。5. 基于這份數(shù)據(jù)集還能怎么做擴(kuò)展5.1 聯(lián)合其它遙感數(shù)據(jù)集訓(xùn)練提升泛化能力854張煙囪圖單獨(dú)訓(xùn)練模型的泛化能力有限。一種很有效的擴(kuò)展方式是把這份數(shù)據(jù)集和更大的遙感數(shù)據(jù)集聯(lián)合訓(xùn)練比如公開的DOTA、DIOR、xView等。聯(lián)合訓(xùn)練時(shí)在YAML文件里把names列表擴(kuò)展成多個(gè)類別煙囪的類別編號(hào)按順序排好把不同數(shù)據(jù)集的圖像和標(biāo)簽統(tǒng)一整理到同一個(gè)目錄結(jié)構(gòu)下。這樣做的好處是模型在同一次訓(xùn)練中既看到了煙囪這類小目標(biāo)工業(yè)設(shè)施也看到了飛機(jī)、車輛、港口等其它遙感目標(biāo)。特征提取器學(xué)習(xí)到更豐富的紋理和形狀特征對(duì)煙囪的判別能力反而會(huì)提升。實(shí)測(cè)下來聯(lián)合訓(xùn)練后的模型在煙囪類別上的mAP往往比單獨(dú)訓(xùn)練更高因?yàn)榈讓犹卣鞅磉_(dá)更強(qiáng)了。代價(jià)是需要處理多數(shù)據(jù)集的格式統(tǒng)一問題如果它們標(biāo)注格式不同要先轉(zhuǎn)成同一套格式這個(gè)工作量不小但對(duì)最終模型的效果提升非常劃算。5.2 引入旋轉(zhuǎn)框檢測(cè)應(yīng)對(duì)密集排列場(chǎng)景前面提到這份數(shù)據(jù)集的標(biāo)注是水平框。但實(shí)際應(yīng)用中煙囪密集排列的場(chǎng)景非常多水平框會(huì)把多個(gè)緊鄰的煙囪框在一起或者在斜向排列時(shí)框入大量背景導(dǎo)致檢測(cè)框重疊率過高、NMS誤刪真實(shí)目標(biāo)。如果你的應(yīng)用場(chǎng)景偏向俯視遙感影像中的密集廠區(qū)建議在水平框基礎(chǔ)上考慮旋轉(zhuǎn)框檢測(cè)OBB方案。Ultralytics YOLOv8原生支持OBB檢測(cè)只需要把標(biāo)簽格式改成class_id x1 y1 x2 y2 x3 y3 x4 y4四個(gè)角點(diǎn)的歸一化坐標(biāo)。MMRotate也提供了完整的旋轉(zhuǎn)框檢測(cè)訓(xùn)練流程對(duì)DOTA數(shù)據(jù)集支持很好。不過旋轉(zhuǎn)框標(biāo)注的制作成本比水平框高不少需要額外的角度標(biāo)注工具如果煙囪目標(biāo)本身在影像中是圓形頂部形態(tài)水平框其實(shí)也不會(huì)有太多背景冗余所以這個(gè)擴(kuò)展要按實(shí)際場(chǎng)景來決定值不值得做。5.3 用已訓(xùn)練模型做自動(dòng)預(yù)標(biāo)注加速二次擴(kuò)展數(shù)據(jù)不夠用的時(shí)候最笨的辦法是繼續(xù)人工標(biāo)注但效率太低。我個(gè)人的推薦做法是用這個(gè)數(shù)據(jù)集先訓(xùn)練一個(gè)基礎(chǔ)模型然后用yolo predict對(duì)新的遙感影像自動(dòng)推理得到初步的檢測(cè)框再通過標(biāo)注工具比如LabelImg、X-AnyLabeling人工修正自動(dòng)標(biāo)注的結(jié)果這個(gè)過程叫預(yù)標(biāo)注或自動(dòng)標(biāo)注輔助人工修正。實(shí)測(cè)下來預(yù)標(biāo)注能把二次標(biāo)注的效率提升60%以上。尤其是煙囪這種特征相對(duì)清晰的目標(biāo)基礎(chǔ)模型預(yù)測(cè)出來的框質(zhì)量不錯(cuò)人工只需要?jiǎng)h除誤檢、補(bǔ)充漏檢、微調(diào)邊框位置。具體操作時(shí)把新圖像放到一個(gè)目錄下批量推理后將結(jié)果生成為YOLO格式標(biāo)簽再導(dǎo)入標(biāo)注軟件檢查修正。用這種方式幾百張新圖像的標(biāo)注工作量可以控制在半天以內(nèi)。5.4 從煙囪檢測(cè)延伸到更廣的工業(yè)設(shè)施檢測(cè)煙囪檢測(cè)這個(gè)任務(wù)本身只是遙感工業(yè)設(shè)施檢測(cè)的一個(gè)切面。同一套數(shù)據(jù)格式、訓(xùn)練流程和技術(shù)方案完全可以復(fù)用到其他工業(yè)目標(biāo)上比如冷卻塔、儲(chǔ)油罐、化工廠房、電力塔桿。你只需要替換成對(duì)應(yīng)的標(biāo)注數(shù)據(jù)重新訓(xùn)練一遍模型。這也體現(xiàn)了一個(gè)通用數(shù)據(jù)集的價(jià)值它不只是教你做一個(gè)煙囪檢測(cè)器更重要的是幫你建立一套遙感目標(biāo)檢測(cè)的標(biāo)準(zhǔn)工作流從數(shù)據(jù)準(zhǔn)備、模型訓(xùn)練到效果評(píng)估的每個(gè)環(huán)節(jié)都形成肌肉記憶。后續(xù)再遇到任何新目標(biāo)只需要按同樣的流程走一遍省去大量摸索時(shí)間。我在實(shí)際使用這份數(shù)據(jù)集時(shí)還有一個(gè)體會(huì)小數(shù)據(jù)集的價(jià)值往往被低估了。很多人看到854張圖就覺得不夠用但真正上手跑一遍你會(huì)發(fā)現(xiàn)它在流程驗(yàn)證、算法對(duì)比、問題定位方面的效率是大型數(shù)據(jù)集比不了的。先用小數(shù)據(jù)把流程跑通把坑踩平再上大場(chǎng)景數(shù)據(jù)這個(gè)思路我一直覺得很實(shí)用。如果你正在找一份用來練手的遙感目標(biāo)檢測(cè)數(shù)據(jù)這份煙囪數(shù)據(jù)集是個(gè)不錯(cuò)的選擇至少在你把它榨干之前它能讓你把目標(biāo)檢測(cè)的整套流程掌握得明明白白。本文還有配套的精品資源點(diǎn)擊獲取