據(jù)集實(shí)戰(zhàn):從數(shù)據(jù)標(biāo)注到Y(jié)OLO檢測的完整指南)
簡介面向鐵路基礎(chǔ)設(shè)施維護(hù)與計算機(jī)視覺研究的鐵軌裂紋數(shù)據(jù)集第一部分重點(diǎn)解決軌道裂紋、缺陷的自動識別與定位問題適合從事目標(biāo)檢測、智能巡檢和軌道安全監(jiān)測的研究者用于模型訓(xùn)練與驗證。資源采用VOC2007標(biāo)準(zhǔn)標(biāo)注格式所有XML注釋文件均由LabelImg工具人工生成詳細(xì)標(biāo)出每個裂紋和缺陷的位置、大小與類別可直接作為深度學(xué)習(xí)模型的輸入。壓縮包共包含2000個文件以XML標(biāo)注文件與JPG原圖為主整體約252.69MB已有4815人學(xué)習(xí)下載。依托這份數(shù)據(jù)集使用者能夠系統(tǒng)開展圖像預(yù)處理、特征提取、模型訓(xùn)練與效果驗證等完整流程還能通過閱讀XML了解VOC格式的目錄組織方式后續(xù)若結(jié)合第二部分?jǐn)?shù)據(jù)可進(jìn)一步增強(qiáng)模型的泛化能力與魯棒性為鐵路安全自動化檢測提供扎實(shí)的數(shù)據(jù)支撐。1. 鐵軌裂紋數(shù)據(jù)集先搞懂這份數(shù)據(jù)再談高精度檢測你花了兩周把模型結(jié)構(gòu)調(diào)得花團(tuán)錦簇一上軌檢車實(shí)拍圖漏檢率直接打回原形。這種翻車十有八九不是模型的問題而是訓(xùn)練數(shù)據(jù)本身沒吃透。鐵軌裂紋數(shù)據(jù)集第一部分就是用來補(bǔ)這門課的它把軌道表面裂紋的圖像、標(biāo)注和場景分布打包好讓做目標(biāo)檢測的人能在真實(shí)光照、真實(shí)銹蝕、真實(shí)枕木干擾下訓(xùn)練和驗證模型而不是在一套干凈得不像話的合成圖里自欺欺人。這份數(shù)據(jù)適合兩類人一是剛接觸軌檢視覺的開發(fā)者需要一套帶標(biāo)注的數(shù)據(jù)跑通檢測流程二是已經(jīng)在做鋼軌傷損識別、但對訓(xùn)練集和驗證集劃分沒有把握的工程師想用一套結(jié)構(gòu)清晰的數(shù)據(jù)檢驗自己的預(yù)處理和模型配置。你能從這份數(shù)據(jù)里得到的不是「跑起來就完事」的體驗而是把裂紋檢測當(dāng)作一個正經(jīng)目標(biāo)檢測任務(wù)來對待的完整路徑數(shù)據(jù)怎么組織、標(biāo)簽怎么解析、劃分怎么做、訓(xùn)練參數(shù)怎么定、哪些坑會導(dǎo)致指標(biāo)虛高或直接崩掉。本文按這個順序展開每一章都可以直接照著操作。2. 讀懂?dāng)?shù)據(jù)組織方式圖像、標(biāo)注與兩類常見格式拿到數(shù)據(jù)集的第一步不是訓(xùn)練是先搞清楚它內(nèi)部的目錄結(jié)構(gòu)和標(biāo)注格式。鐵軌裂紋數(shù)據(jù)集第一部分的常見組織方式是 images 目錄存原始圖像labels 目錄存標(biāo)注文件另外附帶一份類別說明。這個結(jié)構(gòu)看著簡單實(shí)際用起來有幾個容易忽視的細(xì)節(jié)。2.1 圖像內(nèi)容與裂紋形態(tài)橫裂、縱裂和網(wǎng)裂為什么不能混在一個類別里軌道表面裂紋按走向和形態(tài)大體分三類橫向裂紋垂直于鋼軌走向、縱向裂紋沿鋼軌走向延伸、網(wǎng)狀裂紋龜裂或不規(guī)則分叉。如果數(shù)據(jù)集把所有裂紋統(tǒng)一標(biāo)成一個 crack 類別訓(xùn)練出來的模型只能告訴你「這里有異?!沟F(xiàn)場工程師真正需要的是「這是什么類型的傷損」——橫裂涉及斷軌風(fēng)險縱裂可能和材質(zhì)缺陷有關(guān)網(wǎng)裂往往伴隨疲勞累積。所以拿到數(shù)據(jù)集先看類別清單確認(rèn)是否區(qū)分了多個裂紋類別這決定了后續(xù)模型是單類檢測還是多類檢測評估指標(biāo)也要跟著分開看。實(shí)際標(biāo)注中橫向裂紋的框通常窄而扁縱向裂紋的框又長又細(xì)兩者在 aspect ratio寬高比上差異極大。如果你用 COCO 預(yù)訓(xùn)練權(quán)重直接遷移學(xué)習(xí)默認(rèn)的 anchor 配置對極端長寬比目標(biāo)很不友好后面會細(xì)說。另外軌枕、扣件、銹蝕斑、油污在圖像里經(jīng)常被誤標(biāo)成裂紋或者反過來把細(xì)小裂紋漏標(biāo)了這份數(shù)據(jù)集里同樣存在屬于標(biāo)注噪聲的一部分第 5 章會專門講怎么處理。2.2 XML 與 TXT 兩種標(biāo)注格式各自的字段含義與解析要點(diǎn)鐵軌裂紋數(shù)據(jù)集常見的標(biāo)注文件有兩種格式一種是 Pascal VOC 風(fēng)格的 XML另一種是 YOLO 風(fēng)格的 TXT。XML 適合做人眼檢查因為坐標(biāo)是絕對像素值TXT 適合直接訓(xùn)練因為坐標(biāo)是相對圖像的歸一化值。兩種格式在發(fā)布包里有時候會同時提供有時候只提供一種建議先確認(rèn)拿到的是哪種再決定數(shù)據(jù)加載腳本怎么接。XML 格式的核心字段是 object 節(jié)點(diǎn)下的 name類別名和 bndboxxmin、ymin、xmax、ymax 四個絕對坐標(biāo)另外還有 width、height 記錄圖像尺寸。解析時要把坐標(biāo)轉(zhuǎn)成模型需要的格式而且注意 bndbox 的坐標(biāo)是 0 基還是 1 基——VOC 規(guī)范里 xmin/ymin 從 1 開始轉(zhuǎn)換到 YOLO 歸一化坐標(biāo)時要先減去 1 再除以寬高否則邊界框會偏移一個像素。這個偏移對粗框影響不大但對細(xì)長裂紋這種目標(biāo)一兩個像素的偏差就可能讓 IoU 掉一截。TXT 格式每一行對應(yīng)一個目標(biāo)五個數(shù)值依次是 class_id、x_center、y_center、width、height全部歸一化到 01。解析時最常出的問題有兩個一是某些標(biāo)注文件里寬度或高度算成了 0說明標(biāo)注時誤點(diǎn)了兩個重合的點(diǎn)二是坐標(biāo)值出現(xiàn)負(fù)數(shù)或大于 1 的情況多半是標(biāo)注工具導(dǎo)出時沒做裁剪目標(biāo)貼邊導(dǎo)致框超出圖像邊界。這兩種臟數(shù)據(jù)如果不提前過濾訓(xùn)練時輕則 warning 刷屏重則 loss 變成 NaN。2.3 解析前的自查腳本三分鐘找出配對缺失和坐標(biāo)越界拿到數(shù)據(jù)集后別急著開訓(xùn)先寫一個檢查腳本把下面的問題過一次。我一般把這個腳本存成 inspect_data.py每次換數(shù)據(jù)集都跑一遍。import os from glob import glob from PIL import Image img_dir images label_dir labels ext_map {.jpg: .txt, .jpeg: .txt, .png: .txt} img_files glob(os.path.join(img_dir, *)) label_files glob(os.path.join(label_dir, *.txt)) img_stems {os.path.splitext(os.path.basename(f))[0] for f in img_files} label_stems {os.path.splitext(os.path.basename(f))[0] for f in label_files} missing img_stems - label_stems orphan label_stems - img_stems print(missing labels:, sorted(missing)[:10]) print(orphan labels:, sorted(orphan)[:10]) for tf in label_files: with open(tf, r) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(bad line in, tf, :, line) else: x, y, w, h map(float, parts[1:]) if w 0 or h 0 or x 0 or y 0 or x 1 or y 1 or w 1 or h 1: print(out-of-range in, tf, :, line)這段腳本做了三件事第一把圖像文件和標(biāo)簽文件的文件名做差集比對找出有圖沒標(biāo)、有標(biāo)沒圖的文件第二檢查每一行標(biāo)注是否恰好五個數(shù)值第三檢查歸一化坐標(biāo)是否在合理區(qū)間內(nèi)。跑完如果有輸出先把這些問題文件隔離到單獨(dú)目錄不要直接刪因為你還需要它們來反向排查標(biāo)注工具的導(dǎo)出配置。常見做法是先修數(shù)據(jù)再訓(xùn)練而不是讓模型去「學(xué)會」容忍臟標(biāo)注。3. 訓(xùn)練集與驗證集的劃分策略為什么不能隨機(jī)拆分很多人在拿到數(shù)據(jù)集后直接train_test_split按 8:2 隨機(jī)拆訓(xùn)練出來的模型在驗證集上指標(biāo)不錯一到現(xiàn)場就露餡。這不是玄學(xué)而是鐵軌數(shù)據(jù)的天然特性導(dǎo)致的——同一根鋼軌的連續(xù)圖像在光照、角度、背景上高度相似隨機(jī)拆分會把同一段鋼軌的圖像同時分進(jìn)訓(xùn)練集和驗證集模型等于提前看到了答案。3.1 按場景維度劃分同一段鋼軌不要同時出現(xiàn)在訓(xùn)練集和驗證集鐵軌裂紋數(shù)據(jù)的拍攝通常來自軌檢車或手持設(shè)備的一次連續(xù)走行一次采集會得到大量連續(xù)幀。這些幀里裂紋的形態(tài)變化不大但拍攝距離、亮度、曝光在短時間內(nèi)是漸變的。如果隨機(jī)劃分驗證集里會出現(xiàn)和訓(xùn)練集幾乎一模一樣的幀最后的評估分?jǐn)?shù)會虛高幾個點(diǎn)這不代表真實(shí)泛化能力。正確做法是先按場景分組再在場景級別上劃分。比如一次采集是一個 scene一個 scene 里的所有圖像要么全進(jìn)訓(xùn)練集要么全進(jìn)驗證集。這樣才能模擬「模型見到?jīng)]走過的鋼軌段」的真實(shí)推理條件。鐵軌裂紋數(shù)據(jù)集通常會在發(fā)布時說明圖像來自哪些采集批次如果沒有說明可以通過文件名前綴或拍攝時間戳來推斷分組依據(jù)。3.2 光照與干濕狀態(tài)分層不控制分布驗證分?jǐn)?shù)就是自欺欺人除了場景維度光照條件也強(qiáng)烈影響裂紋的視覺表現(xiàn)。白天強(qiáng)光下裂紋陰影清晰陰天漫射光下裂紋對比度低夜間閃光燈下金屬表面反光可能把裂紋完全淹沒。如果訓(xùn)練集里大量是晴天白圖驗證集里也大量是晴天白圖訓(xùn)練過程會學(xué)到一個取巧的 shortcut——看到高亮金屬表面就傾向于預(yù)測裂紋。這個現(xiàn)象在視覺任務(wù)里很常見模型沒有真正學(xué)會區(qū)分裂紋亮度模式只學(xué)會了區(qū)分圖像整體亮度。分層劃分的思路是把圖像先按拍攝條件打上標(biāo)簽強(qiáng)光/陰天/夜間/雨霧然后在每個條件內(nèi)部按比例劃分保證訓(xùn)練集和驗證集里的光照分布一致。鐵軌裂紋數(shù)據(jù)集第一部分如果自帶這些 meta 信息直接利用如果沒有可以用圖像的亮度直方圖做一個粗略的區(qū)分作為分層的替代方案。3.3 分層分割腳本按場景ID和光照標(biāo)簽的劃分實(shí)現(xiàn)下面這段腳本展示了按場景分組之后再按光照條件做分層采樣的劃分邏輯。關(guān)鍵函數(shù)是train_test_split的stratify參數(shù)它保證每個光照類別在訓(xùn)練集和驗證集中的比例一致。import os import random import pandas as pd from sklearn.model_selection import train_test_split image_dir images records [] for fname in os.listdir(image_dir): if not fname.lower().endswith((.jpg, .png, .jpeg)): continue scene_id fname.split(_)[0] # 假設(shè)文件名前綴是場景ID img_path os.path.join(image_dir, fname) records.append({fname: fname, scene_id: scene_id}) df pd.DataFrame(records) # 按場景分組取每個場景第一條記錄的scene_id作為分組特征 scene_df df.groupby(scene_id).agg( count(fname, count), scene_id(scene_id, first) ).reset_index() # 在場景級別上做劃分防止同一場景的幀同時出現(xiàn)在訓(xùn)練和驗證集 train_scenes, val_scenes train_test_split( scene_df[scene_id], test_size0.2, random_state42, stratifyscene_df[scene_id].apply(lambda x: scene_light_level(x)) ) train_df df[df[scene_id].isin(train_scenes)] val_df df[df[scene_id].isin(val_scenes)] print(train frames:, len(train_df)) print(val frames:, len(val_df))這段代碼的核心思想是先按場景ID聚合再在場景上進(jìn)行劃分而不是直接對圖像做隨機(jī)拆分。stratify參數(shù)用來保證不同光照條件下的場景在訓(xùn)練集和驗證集中占比一致。這里的scene_light_level函數(shù)在實(shí)際使用時要替換成你的光照分級邏輯可以用拍攝時間戳、可以用文件名里的光照標(biāo)記、也可以用圖像亮度均值聚類。劃分完后把 train_df 和 val_df 寫出成兩個 txt 文件每行一個圖像路徑后面訓(xùn)練時直接按 list 加載。注意random_state固定為固定值是為了可復(fù)現(xiàn)。如果你做了數(shù)據(jù)增廣增廣隨機(jī)性不受它控制但數(shù)據(jù)集劃分本身每次運(yùn)行結(jié)果一致方便排查問題。4. 最小訓(xùn)練配置用 YOLO 系列工程跑通裂紋檢測劃分好數(shù)據(jù)之后就可以開始訓(xùn)練了。以目標(biāo)檢測領(lǐng)域最常用的 YOLO 系列代碼庫為例把鐵軌裂紋數(shù)據(jù)集接進(jìn)去的步驟是準(zhǔn)備 yaml 配置文件、調(diào)整圖像尺寸、改類別數(shù)、然后啟動訓(xùn)練。4.1 為什么 YOLO 系列適合起步單階段檢測對長條小目標(biāo)的平衡裂紋檢測有兩種主流路線兩階段檢測器Faster R-CNN 系精度有優(yōu)勢但訓(xùn)練慢、部署重單階段檢測器YOLO 系速度快、生態(tài)成熟、預(yù)訓(xùn)練權(quán)重好找對細(xì)長目標(biāo)的召回率通過調(diào) anchor 也能提到可用水平。鐵軌裂紋檢測的實(shí)際場景大部分是軌檢車離線分析或者手持設(shè)備的實(shí)時提示前者對速度不敏感后者要求實(shí)時。如果你只有一次訓(xùn)練資源先跑 YOLO 系拿到一個能用的 baseline再根據(jù)漏檢形態(tài)決定是否上兩階段模型。YOLO 系代碼庫通常自帶數(shù)據(jù)加載、增廣、評估腳本對新手最友好的一點(diǎn)是訓(xùn)練過程中的 loss 曲線和 PR 曲線都直接可視化。你需要改的主要是三個地方數(shù)據(jù)配置 yaml、模型配置 yaml、訓(xùn)練超參數(shù)。下面按這三個文件逐一說明。4.2 數(shù)據(jù)配置與模型配置類別數(shù)、圖像尺寸和 anchor數(shù)據(jù)配置里最重要的字段是nc類別數(shù)量和names類別名列表。鐵軌裂紋數(shù)據(jù)集第一部分如果是單類就寫nc: 1如果區(qū)分橫裂、縱裂、網(wǎng)裂等多類必須和標(biāo)注文件里的 class_id 一一對應(yīng)。類別名寫錯會導(dǎo)致訓(xùn)練正常但推理時標(biāo)簽錯位這種低級錯誤在項目交付時很容易被現(xiàn)場人員罵。# rail_crack.yaml path: ./rail_crack_dataset train: train_list.txt val: val_list.txt nc: 3 names: 0: transverse_crack 1: longitudinal_crack 2: network_crack這個 yaml 文件告訴訓(xùn)練工程三件事數(shù)據(jù)路徑、訓(xùn)練集和驗證集的文件列表、類別對應(yīng)關(guān)系。train_list.txt里面每一行是一個圖像的絕對或相對路徑對應(yīng)的標(biāo)注文件路徑由代碼庫根據(jù)擴(kuò)展名自動替換。注意不同 YOLO 代碼庫對train字段的寫法可能不同有的是目錄有的是 txt 列表看官方示例確認(rèn)一下不要套錯。圖像尺寸是另一個關(guān)鍵參數(shù)。裂紋屬于小目標(biāo)原圖如果是 1920×1080 級別的大圖直接縮放到 640×640 會把細(xì)裂紋縮得只剩幾個像素模型學(xué)不到有效紋理。常見做法是先用 1280×1280 訓(xùn)練推理時再用滑窗或原圖縮放。代價是顯存占用變大batch size 要相應(yīng)調(diào)小。如果你的卡只有 8GB 顯存1280 分辨率下 batch size 可能只能開到 4這時候?qū)幙砂?batch size 調(diào)小也不要降分辨率分辨率對裂紋檢測的影響遠(yuǎn)大于 batch size。anchor 方面細(xì)長裂紋的寬高比經(jīng)常超過 1:5甚至 1:10默認(rèn) anchor 設(shè)定基本匹配不上。YOLO 系列工程一般提供 k-means 聚類 anchor 的工具拿訓(xùn)練集的標(biāo)注框跑一遍把聚類得到的 anchor 替代默認(rèn)值召回率會有肉眼可見的回升。4.3 訓(xùn)練啟動命令與三個必調(diào)超參數(shù)啟動訓(xùn)練前還需要關(guān)注三個超參數(shù)epoch、學(xué)習(xí)率和 mosaic 增廣。epoch 從 100 起步觀察驗證集 PR 曲線在 60~80 epoch 之間是否還在上升如果上升明顯就繼續(xù)加如果已經(jīng)震蕩就提前停止。學(xué)習(xí)率用代碼庫默認(rèn)的 warmup cosine 策略即可但不要隨手開很大的初始學(xué)習(xí)率裂紋檢測的標(biāo)注噪聲一般比通用數(shù)據(jù)集高學(xué)習(xí)率太大容易讓模型過擬合到噪聲框上。mosaic 增廣在拼接四張圖時會把裂紋截斷成兩半對細(xì)長目標(biāo)反而有害我通常在訓(xùn)練后半段關(guān)閉 mosaic只保留基本的翻轉(zhuǎn)和顏色抖動。python train.py --data rail_crack.yaml --weights yolov5s.pt --img 1280 --batch 8 --epochs 100 --cache這條命令的核心參數(shù)含義拆開看--data指定 4.2 節(jié)里寫好的配置--weights用 COCO 預(yù)訓(xùn)練權(quán)重做遷移學(xué)習(xí)不要從隨機(jī)初始化開始裂紋數(shù)據(jù)量不足以支撐從零訓(xùn)練--img 1280是輸入分辨率前面提過這是小目標(biāo)任務(wù)的關(guān)鍵選擇--batch 8是顯存允許范圍內(nèi)的最大值--cache把圖像緩存到內(nèi)存里加速數(shù)據(jù)讀取第一次跑可以不開后面調(diào)參時再開。訓(xùn)練結(jié)束后在驗證集上跑val.py得到每個類別的 mAP、precision、recall以及一張 PR 曲線圖。PR 曲線右下角面積大說明模型在低置信度下也能保持高召回這對裂紋檢測很重要——漏檢的代價遠(yuǎn)高于誤報現(xiàn)場寧可多看幾個誤報也不愿放過一條裂紋。5. 鐵軌裂紋數(shù)據(jù)集的 5 個常見坑每個都是血淚經(jīng)驗這部分把我在實(shí)際使用類似數(shù)據(jù)時遇到最多的問題整理成清單每條按現(xiàn)象、原因、解決來寫。你會發(fā)現(xiàn)大部分坑不在模型而在數(shù)據(jù)和評測流程。5.1 驗證集出現(xiàn)漏標(biāo)注框指標(biāo)集體翻車現(xiàn)象訓(xùn)練 loss 正常下降驗證集 mAP 卡在 0.5 上不去PR 曲線在低 recall 區(qū)域出現(xiàn)明顯掉點(diǎn)。原因數(shù)據(jù)集里存在漏標(biāo)注——圖像里明明有裂紋標(biāo)注文件里沒有對應(yīng)框。模型有時能檢測到這些「未標(biāo)注的裂紋」但評測腳本把它算作 false positiveprecision 被拉低同時模型學(xué)到這些區(qū)域的紋理特征導(dǎo)致對訓(xùn)練集里同類區(qū)域產(chǎn)生誤檢。解決先做一輪「模型輔助標(biāo)注」清洗。用訓(xùn)練好的模型對訓(xùn)練集和驗證集做推理挑出模型置信度高但和現(xiàn)有標(biāo)注框 IoU 小于 0.1 的預(yù)測把這些區(qū)域提出來人工確認(rèn)。如果確認(rèn)是漏標(biāo)補(bǔ)上標(biāo)注然后再訓(xùn)練。這一步很費(fèi)人力但對質(zhì)量不高的數(shù)據(jù)集是必須的投入。某個模擬項目X里我僅靠補(bǔ)漏標(biāo)就把驗證集 mAP 從 0.52 提到了 0.63。5.2 細(xì)長裂紋匹配不到 anchor召回率低到懷疑人生現(xiàn)象訓(xùn)練過程正常但驗證集 recall 只有 0.3 左右查看檢測結(jié)果發(fā)現(xiàn)很多裂紋被識別成很短的碎片框或者完全沒有輸出。原因默認(rèn) anchor 是針對 COCO 數(shù)據(jù)集聚類出來的COCO 里絕大多數(shù)目標(biāo)寬高比在 1:1 到 1:3 之間。裂紋寬高比動輒 1:8 甚至 1:15默認(rèn) anchor 和 ground truth 的 IoU 低于匹配閾值導(dǎo)致這些目標(biāo)在訓(xùn)練時被標(biāo)記為「無匹配」而被忽略。解決用訓(xùn)練集標(biāo)注重新聚類 anchor。YOLO 系工程里一般有anchors.py之類的聚類腳本輸入訓(xùn)練集 label 文件輸出新的 anchor 值替換到模型配置文件里。聚類數(shù)量可以先用默認(rèn)的 9 個觀察匹配率如果匹配率仍低增加到 12 個重點(diǎn)保證長條形 anchor 有覆蓋。聚類時過濾掉異常寬高比比如寬大于圖像寬 0.9 的標(biāo)注多半是標(biāo)錯了。5.3 暗光樣本占比失衡模型學(xué)到的是亮度而不是裂紋現(xiàn)象驗證集整體 mAP 不錯但按光照分層統(tǒng)計時暗光圖像那一組的 mAP 只有正常組的 1/3。原因訓(xùn)練集中暗光圖像占比太低比如只有 5%模型沒有見過足夠多的暗光正樣本只能通過亮度特征猜測——亮圖傾向于輸出低置信度暗圖傾向于輸出高置信度或直接漏檢。解決按第 3 章的光照分層先檢查和調(diào)整分布。如果暗光圖像實(shí)在很少優(yōu)先做色彩增強(qiáng)類的增廣隨機(jī)降低亮度、提高對比度、加高斯噪聲讓模型看到更多「偽暗光」樣本。不要用循環(huán)生成對抗網(wǎng)絡(luò)之類的生成式方案成本高且容易引入偽影傳統(tǒng)光度增廣對這個任務(wù)夠用。另外可以在推理時對輸入圖像做自適應(yīng)的直方圖均衡化CLAHE把暗部紋理拉出來再進(jìn)模型這在很多軌檢實(shí)拍場景下比換模型結(jié)構(gòu)收益更大。5.4 類別不平衡橫裂只有幾十個框網(wǎng)裂有上千個框現(xiàn)象多類訓(xùn)練時總 mAP 尚可但按類別看樣本少的類別 mAP 幾乎為 0PR 曲線不穩(wěn)定。原因橫裂這類高危傷損在實(shí)際數(shù)據(jù)里本來就稀有而網(wǎng)裂分布廣、數(shù)量多。模型在訓(xùn)練時被大量網(wǎng)裂樣本主導(dǎo)對橫裂的梯度信號被稀釋。解決第一按類別統(tǒng)計框數(shù)量確認(rèn)不平衡程度。第二對樣本量少的類別做過采樣思路是訓(xùn)練時每輪多加載幾張包含該類別的圖像而不是復(fù)制粘貼同一張圖。第三調(diào)整 loss 的類別權(quán)重給稀有類別更高的權(quán)重系數(shù)。最直接的做法是把稀有類別的圖像復(fù)制幾份到訓(xùn)練集里簡單粗暴但有效注意不要導(dǎo)致數(shù)據(jù)泄漏——同一圖像的所有副本只能出現(xiàn)在訓(xùn)練集。某些代碼庫支持class_weight參數(shù)直接用也不錯。5.5 訓(xùn)練到第 1 個 epoch loss 變成 NaN標(biāo)注坐標(biāo)惹的禍現(xiàn)象模型啟動訓(xùn)練后 loss 在幾十個 iteration 內(nèi)變成 NaN訓(xùn)練進(jìn)程直接崩掉或開始輸出無意義的權(quán)重。原因最常見的是標(biāo)注文件里有class_id超出了nc的范圍或者坐標(biāo)值出現(xiàn)極端的負(fù)數(shù)和大于 1 的數(shù)。另一個原因是某些代碼庫在歸一化坐標(biāo)時除以了圖像的寬高如果寬高是 0損壞的圖像文件結(jié)果就是無窮大。解決用 2.3 節(jié)的檢查腳本先全量過濾。對于class_id越界的情況回頭查數(shù)據(jù)集附帶的類別說明文檔確認(rèn) 0 基還是 1 基索引有時發(fā)布方自己寫混了把類別 ID 從 1 開始標(biāo)而訓(xùn)練工程默認(rèn)從 0 開始需要統(tǒng)一偏移。對于損壞圖像直接排除并記錄文件名不要修修復(fù)的元數(shù)據(jù)可能帶來更多不可控問題。如果檢查完仍然 NaN再看學(xué)習(xí)率是不是設(shè)得過高把初始學(xué)習(xí)率除以 10 再試。這類問題調(diào)試時間占比最大的是定位過程——先腳本檢查再挨個排查別一上來就改網(wǎng)絡(luò)結(jié)構(gòu)。6. 最后一招在大圖上滑窗推理把細(xì)裂紋找出來再切成小圖訓(xùn)練完的模型默認(rèn)是 640×640 或 1280×1280 輸入但軌檢相機(jī)拍的原始圖經(jīng)常是 4096×4096 甚至更高。直接把大圖縮放到模型輸入尺寸細(xì)裂紋在縮放過程中就消失了。滑窗推理是應(yīng)對這個問題的最可靠方案把大圖切成有重疊的若干小塊逐塊送入模型再把檢測框映射回原圖坐標(biāo)?;暗暮诵膮?shù)是窗口大小和重疊率。窗口大小一般取模型訓(xùn)練時的分辨率不要大于 1280否則顯存不夠重疊率取 20%50%重疊的目的是讓跨越窗口邊界的裂紋至少在一個窗口內(nèi)是完整的避免裂紋被切成兩段導(dǎo)致漏檢。推理時保留每個窗口的原始坐標(biāo)偏移把檢測框換算回完整圖像坐標(biāo)系最后用 NMS非極大值抑制合并重疊窗口產(chǎn)生的重復(fù)檢測框。NMS 的 IoU 閾值設(shè) 0.5 比較合適太高會保留重復(fù)框太低會把相鄰的橫裂和縱裂合并成一個誤檢框?;巴评淼拇鷥r是速度變慢一張 4096×4096 的圖用 1280 窗口加 50% 重疊大約要跑 25 個窗口在普通辦公卡上大概花 2~4 秒。如果對實(shí)時性有要求可以先把大圖縮小到 2048 再滑窗速度提升 4 倍左右代價是小裂紋的召回率會輕微下降。實(shí)際項目中我一般是離線分析用全分辨率滑窗現(xiàn)場實(shí)時檢測用整圖縮放加更高的置信度閾值兩條線并行。偽標(biāo)簽清洗是一個值得做的收尾動作。把訓(xùn)練好的模型在無標(biāo)注的大圖上跑一遍篩選出置信度大于 0.9 的檢測框回填成新的標(biāo)注數(shù)據(jù)進(jìn)行二次訓(xùn)練能顯著提升模型在地域變化后的數(shù)據(jù)集上的表現(xiàn)。注意只回填高置信度結(jié)果且只做半次迭代——用偽標(biāo)簽訓(xùn)練出的模型再生成偽標(biāo)簽再訓(xùn)練噪聲會逐輪積累一般兩輪后就停了。我自己的習(xí)慣是每拿到一份新數(shù)據(jù)先花一個下午做檢查和劃分再花一個晚上跑 baseline永遠(yuǎn)不在沒有看過具體 bad case 的情況下調(diào)模型結(jié)構(gòu)。裂紋檢測是一個檢測精度與工程成本強(qiáng)相關(guān)的領(lǐng)域你多花一天在數(shù)據(jù)檢查上后面調(diào)試模型的效率可能省出一周。這份數(shù)據(jù)集的價值恰恰在于它暴露了足夠多的真實(shí)場景噪聲值得你從頭到尾按上面的流程走一遍。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取