別數(shù)據(jù)集構(gòu)建實(shí)戰(zhàn):600張圖從標(biāo)注到訓(xùn)練全流程)
簡(jiǎn)介本資源是一個(gè)面向計(jì)算機(jī)視覺(jué)初學(xué)者與深度學(xué)習(xí)實(shí)踐者的編織袋圖像識(shí)別專(zhuān)用數(shù)據(jù)集適用于圖像分類(lèi)模型訓(xùn)練、工業(yè)質(zhì)檢算法驗(yàn)證及自動(dòng)化倉(cāng)儲(chǔ)場(chǎng)景開(kāi)發(fā)。數(shù)據(jù)集包含600余張真實(shí)場(chǎng)景下的編織袋圖像已按類(lèi)型/用途完成精細(xì)標(biāo)注可直接用于CNN等模型的端到端訓(xùn)練與評(píng)估。壓縮包共2000個(gè)文件主體為1382個(gè)PASCAL VOC格式XML標(biāo)注文件含邊界框與類(lèi)別、615個(gè)YOLO兼容TXT標(biāo)簽文件以及3個(gè)實(shí)用Python腳本如voc_label.py用于格式轉(zhuǎn)換、split_train_val.py實(shí)現(xiàn)數(shù)據(jù)集劃分整體大小318.01MB結(jié)構(gòu)規(guī)范、開(kāi)箱即用。目前已有113人下載學(xué)習(xí)配套腳本顯著降低數(shù)據(jù)預(yù)處理門(mén)檻節(jié)省標(biāo)注解析與訓(xùn)練集構(gòu)建時(shí)間特別適合快速搭建基線模型、開(kāi)展遷移學(xué)習(xí)或參與輕量化部署實(shí)驗(yàn)。 編織袋這個(gè)東西在視覺(jué)識(shí)別里算是個(gè)“又簡(jiǎn)單又難”的目標(biāo)。簡(jiǎn)單在于它結(jié)構(gòu)規(guī)整、紋理重復(fù)度高跟背景區(qū)分度通常比較大難在于它種類(lèi)太多顏色、新舊程度、折疊狀態(tài)、光照條件一變同一個(gè)袋子看起來(lái)就像完全不同的東西。最近我剛好整理完一份600多張的編織袋圖像識(shí)別數(shù)據(jù)集標(biāo)注分類(lèi)也做完了整個(gè)過(guò)程踩了不少坑也沉淀了一些可以復(fù)用的方法這篇就把它完整拆開(kāi)講講。這篇文章適合誰(shuí)看如果你是做工業(yè)質(zhì)檢、垃圾分類(lèi)、物流分揀或者剛接觸目標(biāo)檢測(cè)、圖像分類(lèi)想用一個(gè)小體量數(shù)據(jù)集快速驗(yàn)證方案的那這篇的內(nèi)容應(yīng)該對(duì)你有參考價(jià)值。我先把核心結(jié)論放在前面600多張圖對(duì)于編織袋這種類(lèi)內(nèi)差異大、類(lèi)間差異小的目標(biāo)來(lái)說(shuō)不夠但也不是不能用關(guān)鍵是看你怎么把這600張的價(jià)值榨干。1. 項(xiàng)目整體設(shè)計(jì)與思路拆解1.1 為什么做編織袋圖像識(shí)別難點(diǎn)到底在哪編織袋的應(yīng)用場(chǎng)景比很多人想象的廣得多。水泥廠、化肥廠、飼料廠、糧食倉(cāng)庫(kù)、垃圾回收站、物流轉(zhuǎn)運(yùn)中心到處都有它的身影。在這些場(chǎng)景里識(shí)別編織袋往往不是一個(gè)孤立的算法需求而是整個(gè)自動(dòng)化流程的前置環(huán)節(jié)——比如垃圾分揀線上要先把編織袋從其他垃圾里挑出來(lái)倉(cāng)庫(kù)里要統(tǒng)計(jì)編織袋的數(shù)量和碼放情況質(zhì)檢線上要判斷編織袋表面有沒(méi)有破損或印刷缺陷。但真正動(dòng)手做的時(shí)候你會(huì)發(fā)現(xiàn)編織袋這個(gè)類(lèi)別在公開(kāi)數(shù)據(jù)集里幾乎是空白。通用目標(biāo)檢測(cè)數(shù)據(jù)集如COCO里有瓶子、椅子、貓狗就是沒(méi)有編織袋。Voc2012、ImageNet這些老牌數(shù)據(jù)集里偶爾能看到一兩張但遠(yuǎn)遠(yuǎn)不夠訓(xùn)練用。這就是為什么需要自己動(dòng)手搞一份專(zhuān)門(mén)的數(shù)據(jù)集。從技術(shù)角度看編織袋識(shí)別有幾個(gè)很典型的難點(diǎn)。第一是類(lèi)內(nèi)差異大。同是編織袋白的、灰的、黃的、藍(lán)的、綠的有干凈的、沾滿灰塵的、有破損的有平鋪的、卷起來(lái)的、捏成一團(tuán)的也有。同樣是“編織袋”這個(gè)類(lèi)別外觀跨度可能比“瓶子和杯子”之間的差異還大。第二是紋理干擾。編織袋表面的十字編織紋理在圖像里會(huì)形成高頻信號(hào)尤其是在近距離拍攝時(shí)這種紋理很容易干擾特征提取。你用肉眼覺(jué)得“這不就是密密麻麻的網(wǎng)格嘛”但CNN在淺層提取邊緣信息時(shí)這些網(wǎng)格會(huì)形成大量重復(fù)的邊緣響應(yīng)處理不好會(huì)影響收斂速度和精度。第三是背景混淆。編織袋經(jīng)常出現(xiàn)在地面、傳送帶、堆垛、廢料堆這類(lèi)復(fù)雜背景里顏色和紋理容易與周?chē)h(huán)境融合。特別是灰白色的舊編織袋放在水泥地上別說(shuō)算法人眼都得仔細(xì)看。1.2 600多張數(shù)據(jù)量的現(xiàn)實(shí)評(píng)估先說(shuō)不好的消息600多張圖如果要訓(xùn)練一個(gè)多類(lèi)別目標(biāo)檢測(cè)模型屬于典型的小樣本場(chǎng)景直接硬訓(xùn)很容易過(guò)擬合。再說(shuō)好消息編織袋這個(gè)目標(biāo)結(jié)構(gòu)規(guī)整、語(yǔ)義相對(duì)單一不是那種需要海量數(shù)據(jù)才能學(xué)出區(qū)分性特征的細(xì)粒度任務(wù)所以600張圖如果用好了完全能跑出一個(gè)可用的baseline。我做一個(gè)粗略換算假設(shè)600張圖里有大約800到900個(gè)標(biāo)注實(shí)例每個(gè)類(lèi)別平均100多個(gè)實(shí)例。對(duì)于單階段檢測(cè)器比如YOLO系列來(lái)說(shuō)這個(gè)量級(jí)意味著模型能學(xué)到基本的形狀、紋理和上下文特征但泛化能力有限——換個(gè)沒(méi)見(jiàn)過(guò)的光照條件或背景性能可能明顯下降。對(duì)于分類(lèi)網(wǎng)絡(luò)比如ResNet來(lái)說(shuō)600張圖做二分類(lèi)編織袋 vs 背景是夠的做大類(lèi)精細(xì)分類(lèi)則比較緊張。我的判斷是這份數(shù)據(jù)集的價(jià)值不在于量而在于它作為“種子數(shù)據(jù)”的作用。有了這600多張標(biāo)注好的圖你可以通過(guò)數(shù)據(jù)增強(qiáng)、主動(dòng)學(xué)習(xí)、半監(jiān)督學(xué)習(xí)等方式用比較小的成本把它擴(kuò)成幾千甚至上萬(wàn)張的實(shí)用數(shù)據(jù)集。換句話說(shuō)這不是終點(diǎn)是個(gè)起點(diǎn)。1.3 為什么選擇“標(biāo)注分類(lèi)”而不是直接做檢測(cè)題目里寫(xiě)的是“標(biāo)注分類(lèi)”這里面有個(gè)關(guān)鍵選擇到底是做圖像分類(lèi)還是目標(biāo)檢測(cè)這兩個(gè)方向的數(shù)據(jù)標(biāo)注方式和模型輸出完全不同。我給這份數(shù)據(jù)集定的方案是以分類(lèi)為基礎(chǔ)同時(shí)保留了升級(jí)到檢測(cè)的擴(kuò)展性。具體來(lái)說(shuō)每張圖的標(biāo)注先是“這張圖里有沒(méi)有編織袋、是哪個(gè)類(lèi)別”這是分類(lèi)標(biāo)簽同時(shí)我在部分圖上額外畫(huà)了邊界框這樣后續(xù)想訓(xùn)練檢測(cè)器時(shí)不需要從頭補(bǔ)標(biāo)。為什么會(huì)這樣設(shè)計(jì)原因是實(shí)際需求往往不是單一的。比如在傳送帶上判斷“當(dāng)前有沒(méi)有編織袋經(jīng)過(guò)”分類(lèi)就夠了但要定位編織袋在畫(huà)面中的位置、讓機(jī)械臂去抓取就必須檢測(cè)。分類(lèi)標(biāo)注的成本低、速度快檢測(cè)標(biāo)注的維度更多、信息量更大。先做好分類(lèi)把類(lèi)別的邊界定義清楚再補(bǔ)檢測(cè)框是非常務(wù)實(shí)的路徑。2. 數(shù)據(jù)采集與清洗實(shí)操2.1 圖像采集的六個(gè)場(chǎng)景維度數(shù)據(jù)采集是整個(gè)流程里最容易被低估的一步。很多人覺(jué)得“多拍幾張就行”但拍回來(lái)的圖如果場(chǎng)景分布不合理會(huì)直接影響模型的泛化能力。我按照下面的維度來(lái)規(guī)劃采集光照條件室內(nèi)日光燈、室外自然光、逆光、陰影、夜間補(bǔ)光。尤其是室外場(chǎng)景不同時(shí)段的色溫差異很大晨昏的橘黃色調(diào)和正午的白色日光會(huì)讓同一個(gè)編織袋拍出來(lái)像兩個(gè)類(lèi)別。拍攝角度俯拍從上方看傳送帶/地面、平拍看堆垛、斜向下45度手持拍攝。角度變化會(huì)讓編織袋的紋理走向、折疊形態(tài)產(chǎn)生顯著差異。距離尺度特寫(xiě)紋理清晰可見(jiàn)、中景可以看到完整袋子、遠(yuǎn)景袋子較小混雜在其他物體中。模型在推理時(shí)會(huì)遇到不同尺度的目標(biāo)訓(xùn)練集里必須覆蓋。袋子狀態(tài)平整展開(kāi)、隨意折疊、捏成一團(tuán)、部分破損、被踩壓變形。真實(shí)場(chǎng)景中平整展開(kāi)的袋子其實(shí)占比不高更多的是各種“不成形”的狀態(tài)。背景環(huán)境干凈地面、堆滿雜物的倉(cāng)庫(kù)、傳送帶、草地、水泥地、塑料堆。背景復(fù)雜度直接影響檢測(cè)難度。袋內(nèi)填充程度裝滿物料鼓起來(lái)的、半滿癟下去的、空袋壓平的。不同填充程度影響袋子的輪廓和褶皺形態(tài)。好這個(gè)維度劃分聽(tīng)起來(lái)比較抽象舉個(gè)具體例子如果你只拍了平整展開(kāi)的干凈白袋子模型到了實(shí)際現(xiàn)場(chǎng)看到一團(tuán)皺巴巴的臟袋子基本就傻眼了。采集時(shí)寧可每類(lèi)數(shù)量少一點(diǎn)也要讓狀態(tài)、環(huán)境、光照的覆蓋面足夠廣。2.2 圖像篩選與清洗標(biāo)準(zhǔn)采集回來(lái)的原始圖不能直接標(biāo)注需要過(guò)一遍清洗。我的篩選標(biāo)準(zhǔn)是第一清晰度。明顯失焦、運(yùn)動(dòng)模糊、壓縮過(guò)度的圖直接刪掉。這類(lèi)圖在訓(xùn)練時(shí)會(huì)造成很大的噪聲模型學(xué)到的是“模糊”而不是“編織袋”的特征。但這里有個(gè)度的問(wèn)題——稍微微糊一點(diǎn)的日志圖可以保留一部分因?yàn)閷?shí)際推理時(shí)攝像頭未必能拍到那么清晰的畫(huà)面適當(dāng)加入一些輕微模糊的樣本有助于魯棒性。這個(gè)度怎么把握我用了一個(gè)簡(jiǎn)單的經(jīng)驗(yàn)值人眼能明確辨認(rèn)出是編織袋但細(xì)節(jié)紋理看不清的圖可以留人眼都認(rèn)不出的圖必須刪。第二有效目標(biāo)大小。如果一張圖里編織袋在畫(huà)面中占比不到5%而且是在角落里這意味著標(biāo)注出來(lái)的目標(biāo)尺寸很小。小目標(biāo)學(xué)習(xí)本身是檢測(cè)器的一大難題少量小目標(biāo)樣本還好如果占了很大比例訓(xùn)練時(shí)會(huì)拉低整體性能。我的做法是統(tǒng)計(jì)每張圖里標(biāo)注框占整圖面積的比例把所有樣本算完分布后把占比小于2%的圖單列出來(lái)不作為主要訓(xùn)練樣本而是放在額外的小目標(biāo)專(zhuān)項(xiàng)集里后面用來(lái)做尺度針對(duì)性增強(qiáng)。第三重復(fù)度。連續(xù)拍攝的圖往往高度相似如果直接把相似度很高的幾十張全放進(jìn)訓(xùn)練集會(huì)造成數(shù)據(jù)冗余相當(dāng)于一個(gè)樣本在訓(xùn)練集中出現(xiàn)了幾十次讓模型對(duì)那個(gè)特定場(chǎng)景過(guò)擬合。我用了簡(jiǎn)單的感知哈希算法pHash做粗篩相似度高于0.9的只保留一張作為代表確保數(shù)據(jù)集的多樣性。清洗完之后600多張是從原始大約800張里篩出來(lái)的——可以看到篩掉的比例不算小這也說(shuō)明采集時(shí)多拍一些冗余量很有必要。2.3 數(shù)據(jù)分布統(tǒng)計(jì)避免類(lèi)別失衡清洗完之后我對(duì)數(shù)據(jù)集做了一次類(lèi)別分布統(tǒng)計(jì)這一步很重要但很多人會(huì)跳過(guò)。我這里舉例說(shuō)明如果做的是“全新白袋、舊白袋、彩色袋、受損袋”四分類(lèi)600多張圖的分布大概是這樣類(lèi)別數(shù)量張占比全新白袋18030%舊白袋24040%彩色袋13022%受損袋508%這里有幾個(gè)信息受損袋樣本量明顯不足占8%這個(gè)類(lèi)別的特征又恰恰是質(zhì)檢場(chǎng)景最關(guān)心的——破損檢測(cè)。如果直接拿這個(gè)不均衡的數(shù)據(jù)去訓(xùn)練模型大概率會(huì)把受損袋認(rèn)成舊白袋因?yàn)閮烧咄庥^接近而舊白袋樣本數(shù)量多、模型學(xué)得更充分。針對(duì)這個(gè)失衡我的做法不是盲目砍掉多數(shù)類(lèi)樣本而是給出了兩個(gè)選項(xiàng)要么在采集階段補(bǔ)充受損袋的圖片要么先把受損袋從分類(lèi)任務(wù)里拿掉第一步只做二分類(lèi)“編織袋 vs 背景”或三分類(lèi)去掉受損袋等數(shù)據(jù)量上來(lái)后再加回這個(gè)類(lèi)別。最終我選的是后者因?yàn)橛邢薜?00張沒(méi)法在保證其他類(lèi)別數(shù)量的同時(shí)把受損袋補(bǔ)夠。這個(gè)決策在后續(xù)的訓(xùn)練中也驗(yàn)證了是正確的。3. 標(biāo)注方案設(shè)計(jì)與質(zhì)量控制3.1 標(biāo)注工具的選型過(guò)程標(biāo)注工具我對(duì)比過(guò)幾個(gè)主流方案說(shuō)下我的實(shí)際體驗(yàn)LabelImg最傳統(tǒng)也最輕量純Python寫(xiě)的安裝簡(jiǎn)單開(kāi)箱即用。但界面比較老批量操作能力弱適合快速小規(guī)模打標(biāo)。600張圖用LabelImg能扛住但效率一般。Labelme支持多邊形標(biāo)注適合不規(guī)則目標(biāo)。編織袋的輪廓往往比較規(guī)整用多邊形標(biāo)注精度更高但標(biāo)注速度慢很多。除非你需要做實(shí)例分割否則沒(méi)必要。CVATComputer Vision Annotation Tool在線工具功能非常全支持視頻標(biāo)注、自動(dòng)標(biāo)注配合已有模型、多人協(xié)作。我用這個(gè)來(lái)做核心標(biāo)注因?yàn)樗邪胱詣?dòng)標(biāo)注功能——先用一個(gè)預(yù)訓(xùn)練模型跑一遍人工修正標(biāo)簽和框效率比純手工高不少。Roboflow不只是標(biāo)注工具還集成了數(shù)據(jù)集管理、預(yù)處理、增強(qiáng)、導(dǎo)出格式轉(zhuǎn)換。我推薦把標(biāo)注完的圖傳到Roboflow做數(shù)據(jù)管理后面導(dǎo)出YOLO、COCO、VOC各種格式都很方便。打個(gè)比方找標(biāo)注工具就跟找做飯的廚房一樣LabelImg是露營(yíng)用的小卡式爐能做飯但費(fèi)勁CVAT是正經(jīng)廚房的燃?xì)庠罨鹆鶆颉⒛茴嵣識(shí)oboflow是帶烤箱的集成灶烤、蒸、炒一站搞定。選哪個(gè)取決于你要做幾頓飯數(shù)據(jù)規(guī)模和要不要做大菜復(fù)雜標(biāo)注。3.2 標(biāo)注規(guī)范比想象中更關(guān)鍵標(biāo)注規(guī)范這件事直接決定了數(shù)據(jù)質(zhì)量的70%。我踩過(guò)的最大坑就是類(lèi)型定義模糊。比如“破損袋”這個(gè)類(lèi)別什么程度算破損破了一個(gè)洞算不算邊緣磨破一條線算不算還是必須大面積撕裂才算這些如果不定義清楚兩個(gè)標(biāo)注員給出的標(biāo)準(zhǔn)會(huì)完全不一樣訓(xùn)練出來(lái)的模型也會(huì)無(wú)所適從。我的做法是在正式標(biāo)注之前寫(xiě)了一份簡(jiǎn)單的標(biāo)注說(shuō)明文檔大致內(nèi)容如下類(lèi)別定義全新白袋無(wú)破損、整體顏色均勻、印刷圖案清晰的白色編織袋舊白袋無(wú)大面積破損但存在明顯使用痕跡顏色發(fā)黃、褶皺、污漬彩色袋非白色的所有編織袋以袋面主色為準(zhǔn)受損袋任何存在撕裂、破洞、邊緣磨損的編織袋不論新舊邊界框標(biāo)注規(guī)則邊界框緊貼編織袋主體輪廓不包含背景若袋子被其他物體部分遮擋邊界框應(yīng)包含被遮擋部分在內(nèi)即框住完整的最外延同一張圖中出現(xiàn)多個(gè)編織袋時(shí)全部標(biāo)注不遺漏不確定類(lèi)別時(shí)標(biāo)記為“待確認(rèn)”由標(biāo)注負(fù)責(zé)人統(tǒng)一裁決這份規(guī)范不需要多長(zhǎng)但必須有。我遇到過(guò)的問(wèn)題是標(biāo)注員對(duì)“舊白袋”的理解是“看起來(lái)有點(diǎn)臟的”對(duì)“受損袋”的理解是“明顯破了的”這個(gè)“看起來(lái)”和“明顯”就很主觀。所以我在規(guī)范里盡量用可量化的描述并且提供了參考圖作為錨定。3.3 標(biāo)注質(zhì)量校驗(yàn)的三層檢查標(biāo)注完成之后我分三層做質(zhì)檢不能只憑肉眼掃一遍就拉倒。第一層是格式校驗(yàn)。用腳本檢查每個(gè)標(biāo)注文件的格式是否合規(guī)比如邊界框坐標(biāo)是否越界、類(lèi)別ID是否在合法范圍內(nèi)、文件名是否一一對(duì)應(yīng)。這個(gè)用Python腳本批量跑十幾分鐘就能完成。第二層是可視化復(fù)盤(pán)。把標(biāo)注框畫(huà)到圖上人眼快速掃一遍。重點(diǎn)關(guān)注框是否框得過(guò)大或過(guò)小、類(lèi)別標(biāo)簽是否明顯歸錯(cuò)。這個(gè)環(huán)節(jié)比較費(fèi)時(shí)間但必要我一般會(huì)花半天時(shí)間過(guò)完整批圖。第三層是交叉抽樣。隨機(jī)抽取約10%的圖讓另一個(gè)標(biāo)過(guò)別的數(shù)據(jù)集的同事重新標(biāo)一遍然后計(jì)算兩次標(biāo)注的IoUIntersection over Union。IoU大于0.7算合格不合格的退回重標(biāo)。這一步是為了發(fā)現(xiàn)系統(tǒng)性的偏差——比如同一個(gè)標(biāo)注員習(xí)慣性把框畫(huà)大半個(gè)像素其他標(biāo)注員完全看不出來(lái)。三層質(zhì)檢做完數(shù)據(jù)集的標(biāo)簽可信度就上了一個(gè)臺(tái)階。我不建議在這一步省時(shí)間因?yàn)槟P陀?xùn)練出來(lái)后80%的“臟數(shù)據(jù)問(wèn)題”都可以追溯到標(biāo)注環(huán)節(jié)。4. 數(shù)據(jù)劃分與增強(qiáng)策略4.1 訓(xùn)練驗(yàn)證測(cè)試集的劃分邏輯600多張圖的劃分方式直接影響最終評(píng)估指標(biāo)的可信度。我最基礎(chǔ)的做法是60%訓(xùn)練、15%驗(yàn)證、25%測(cè)試——注意測(cè)試集的比例我故意放得比較大。為什么因?yàn)閿?shù)據(jù)量本身小測(cè)試集如果太小比如只有50張精度指標(biāo)的置信區(qū)間會(huì)特別寬跑出來(lái)結(jié)果80%和85%的差異根本沒(méi)有統(tǒng)計(jì)顯著性。測(cè)試集放大到150張左右得出的結(jié)論相對(duì)可靠一些。但這里有一個(gè)關(guān)鍵點(diǎn)訓(xùn)練集和測(cè)試集的分割不能是純隨機(jī)的要按場(chǎng)景維度分層采樣。比如采集了A倉(cāng)庫(kù)室內(nèi)和B場(chǎng)地室外的照片如果隨機(jī)劃分同一個(gè)倉(cāng)庫(kù)的相似圖可能同時(shí)落到訓(xùn)練集和測(cè)試集評(píng)估結(jié)果虛高。我采用的是按拍攝場(chǎng)景分組確保測(cè)試集里的場(chǎng)景在訓(xùn)練集里沒(méi)有“近親”。具體做法是先把所有圖片按采集場(chǎng)景分組然后每個(gè)組內(nèi)按比例抽取測(cè)試樣本再合并成總的測(cè)試集。這樣雖然保證不了絕對(duì)嚴(yán)格——同一類(lèi)編織袋在不同場(chǎng)景下還是有相似之處——但至少避免了一個(gè)場(chǎng)景的全量圖像都進(jìn)入訓(xùn)練集導(dǎo)致測(cè)試集完全沒(méi)難度的情況。4.2 數(shù)據(jù)增強(qiáng)從600到6000的有效手段數(shù)據(jù)增強(qiáng)是讓600張圖發(fā)揮6000張效果的核心手段。我按“必須用、建議用、慎用”三檔來(lái)梳理必須用的增強(qiáng)對(duì)這些圖像的語(yǔ)義不會(huì)造成影響水平翻轉(zhuǎn)編織袋類(lèi)別不會(huì)因?yàn)樽笥曳D(zhuǎn)而改變水平翻轉(zhuǎn)等效于把數(shù)據(jù)集翻倍。隨機(jī)旋轉(zhuǎn)±15度以內(nèi)輕微的旋轉(zhuǎn)可以模擬拍攝角度的小幅變化但超過(guò)30度會(huì)引入大量非自然角度可能出現(xiàn)模型沒(méi)見(jiàn)過(guò)的情況。色彩抖動(dòng)亮度/對(duì)比度/飽和度小幅度變化模擬不同光照條件。隨機(jī)裁剪裁剪后resize回原尺寸模擬不同尺度下的觀察增強(qiáng)模型對(duì)目標(biāo)大小變化的適應(yīng)能力。建議用的增強(qiáng)有條件使用Mosaic增強(qiáng)YOLOv5之后流行的方式把4張圖拼接成一張供模型訓(xùn)練。好處是讓模型在一次前向傳播中同時(shí)看到4個(gè)不同場(chǎng)景相當(dāng)于同時(shí)增加了batch的有效信息量對(duì)小數(shù)據(jù)集特別友好。MixUp兩張圖按一定比例透明度混合樣本的標(biāo)簽也按同樣比例做軟標(biāo)簽混合。這個(gè)略微激進(jìn)但是我發(fā)現(xiàn)在編織袋這類(lèi)紋理重復(fù)度較高的數(shù)據(jù)上效果意外地好因?yàn)槟P偷淖⒁饬?huì)從“記憶整圖”轉(zhuǎn)向“關(guān)注局部紋理”。慎用的增強(qiáng)高斯噪聲雖然可以模擬攝像頭質(zhì)量不佳的情況但噪聲過(guò)大會(huì)掩蓋編織袋本身的紋理特征。顏色反轉(zhuǎn)/灰度化如果應(yīng)用場(chǎng)景本身就是彩色攝像頭拍攝灰度化反而會(huì)讓模型丟失顏色特征。除非你的部署端攝像頭確實(shí)是黑白的否則不建議大規(guī)模使用。我用了一個(gè)小技巧來(lái)驗(yàn)證增強(qiáng)策略是否有效——用增強(qiáng)后的數(shù)據(jù)做一次訓(xùn)練再用不增強(qiáng)的數(shù)據(jù)做一次訓(xùn)練對(duì)比驗(yàn)證集上的損失曲線。如果加了增強(qiáng)之后損失曲線下降更慢但收斂值更低說(shuō)明增強(qiáng)起的是正面作用如果損失一直居高不下那可能增強(qiáng)太猛了需要調(diào)低增強(qiáng)強(qiáng)度。這個(gè)方法不花時(shí)間但能幫你避免“增強(qiáng)了個(gè)寂寞”。4.3 主動(dòng)學(xué)習(xí)思路讓600張逐步擴(kuò)展這里提供一個(gè)超出數(shù)據(jù)集本身范圍的思路用這600張訓(xùn)練一個(gè)初始模型然后去“挖”新的無(wú)標(biāo)注數(shù)據(jù)。具體做法是用模型對(duì)一批未標(biāo)注的圖片做預(yù)測(cè)把置信度低于某個(gè)閾值比如0.5的圖挑出來(lái)這些就是模型“拿不準(zhǔn)”的樣本也是最值得人工標(biāo)注的樣本。這個(gè)流程叫主動(dòng)學(xué)習(xí)邏輯是模型覺(jué)得難的樣本才是最適合補(bǔ)充標(biāo)注的數(shù)據(jù)。如果只是隨機(jī)挑圖去標(biāo)注很多是模型已經(jīng)學(xué)得很好的重復(fù)樣本不僅浪費(fèi)時(shí)間對(duì)模型能力提升也沒(méi)有幫助。我試過(guò)一次從現(xiàn)場(chǎng)抓了2000張未標(biāo)注圖像模型跑完一遍后挑出置信度在0.3到0.7之間的約400張人工標(biāo)注后加入訓(xùn)練集精度直接提升約6個(gè)百分點(diǎn)。這個(gè)比例比隨機(jī)補(bǔ)標(biāo)200張的效果高出不少。5. 模型選擇與訓(xùn)練參數(shù)經(jīng)驗(yàn)5.1 分類(lèi)模型 vs 檢測(cè)模型的選型對(duì)比這個(gè)數(shù)據(jù)集到底是喂給分類(lèi)模型還是檢測(cè)模型取決于你要解決的實(shí)際問(wèn)題。我把兩者的適用場(chǎng)景做一個(gè)對(duì)比圖像分類(lèi)如ResNet、MobileNet解決“這張圖里有沒(méi)有編織袋”或者“這張圖里的主要物體是哪類(lèi)編織袋”的問(wèn)題。優(yōu)點(diǎn)是訓(xùn)練快、模型輕量、部署成本低缺點(diǎn)是只能告訴你圖里有什么不能告訴你在哪里。目標(biāo)檢測(cè)如YOLOv8、Faster R-CNN解決“圖里的編織袋在哪個(gè)位置”的問(wèn)題同時(shí)可以輸出每個(gè)目標(biāo)的類(lèi)別和置信度。優(yōu)點(diǎn)是信息量完整直接服務(wù)分揀、抓取等物理操作缺點(diǎn)是標(biāo)注成本高需要畫(huà)框、模型更重、訓(xùn)練時(shí)間更長(zhǎng)。我做的是分類(lèi)標(biāo)注所以第一版模型直接用分類(lèi)網(wǎng)絡(luò)。這個(gè)決策基于一個(gè)實(shí)際考慮當(dāng)時(shí)客戶的需求是“在傳送帶入口處判斷是否有編織袋進(jìn)入”只需要一個(gè)布爾判斷不需要位置信息。等到后面要做“機(jī)械臂抓取編織袋”時(shí)再在已有分類(lèi)模型基礎(chǔ)上做檢測(cè)模型的遷移把主干網(wǎng)絡(luò)的權(quán)重拷貝過(guò)來(lái)做初始化訓(xùn)練速度會(huì)比從零開(kāi)始快很多。這里有個(gè)細(xì)節(jié)方便說(shuō)一下分類(lèi)模型的主干網(wǎng)絡(luò)權(quán)重直接拿來(lái)初始化檢測(cè)模型的Backbone是常見(jiàn)做法。因?yàn)榉诸?lèi)和檢測(cè)在底層提取的特征邊緣、紋理、形狀是通用的只有后幾層的語(yǔ)義信息不同。用分類(lèi)權(quán)重做預(yù)訓(xùn)練相當(dāng)于讓檢測(cè)模型在起步時(shí)就有了“認(rèn)得編織袋紋理”的能力。5.2 YOLOv8訓(xùn)練自己的數(shù)據(jù)集配置記錄如果你決定走檢測(cè)路線我直接用YOLOv8為例給出訓(xùn)練配置。先說(shuō)結(jié)論我再解釋為什么是這些參數(shù)。# dataset.yaml train: ./datasets/bags/train val: ./datasets/bags/val test: ./datasets/bags/test # 類(lèi)別數(shù) nc: 3 # 類(lèi)別名稱(chēng)按實(shí)際修改 names: [new_white_bag, old_white_bag, colored_bag]訓(xùn)練指令yolo detect train \ datadataset.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ augmentTrue有幾個(gè)參數(shù)值得展開(kāi)說(shuō)說(shuō)模型選擇yolov8nnano版而不是yolov8s或m。因?yàn)閿?shù)據(jù)量小用大模型反而容易過(guò)擬合——大模型的參數(shù)量是幾個(gè)百萬(wàn)級(jí)600張圖很難填滿它的表達(dá)空間。nano版模型的容量小擬合小數(shù)據(jù)集的難度相對(duì)低訓(xùn)練收斂更快。實(shí)測(cè)下來(lái)nano版在編織袋數(shù)據(jù)集上的mAP50大約在0.85左右而s版反而因?yàn)檫^(guò)擬合掉到0.78差距很明顯。imgsz640。yolov8的默認(rèn)輸入尺寸是640x640。如果原始圖像比640大訓(xùn)練時(shí)會(huì)resize相當(dāng)于目標(biāo)變小。如果編織袋在原始圖中占比很大比如特寫(xiě)照片可以在訓(xùn)練時(shí)直接用imgsz832甚至1024讓目標(biāo)占的有效像素更多。代價(jià)是顯存占用增加、訓(xùn)練時(shí)間變長(zhǎng)。小數(shù)據(jù)集情況下我建議先用640看效果再?zèng)Q定是否調(diào)大。epochs100。對(duì)于600多張圖100輪訓(xùn)練并不會(huì)花太多時(shí)間但足夠讓模型收斂。我做過(guò)一個(gè)對(duì)比訓(xùn)練到60輪時(shí)mAP50已經(jīng)接近0.8100輪時(shí)到0.85150輪時(shí)反而開(kāi)始略降——這就是過(guò)擬合的征兆小數(shù)據(jù)集上epochs不宜拉太長(zhǎng)。batch16。這取決于GPU顯存。yolov8n在batch16、imgsz640下的顯存占用大約6GB左右一般消費(fèi)級(jí)顯卡都能跑。batch太小比如4會(huì)導(dǎo)致梯度噪聲大、訓(xùn)練不穩(wěn)定batch太大比如64在小數(shù)據(jù)集上會(huì)加劇過(guò)擬合因?yàn)槊總€(gè)epoch內(nèi)的有效更新次數(shù)變少了。5.3 訓(xùn)練過(guò)程中的監(jiān)控指標(biāo)解讀訓(xùn)練時(shí)不能只盯著loss要同時(shí)盯幾個(gè)指標(biāo)。我的習(xí)慣是每5個(gè)epoch記錄一次train/loss訓(xùn)練損失、val/box_loss驗(yàn)證集邊界框損失、metrics/precision精確率、metrics/recall召回率、metrics/mAP50IoU閾值0.5下的平均精度。這里有三個(gè)值得關(guān)注的信號(hào)第一個(gè)信號(hào)是precison和recall的剪刀差。如果precision高但recall低說(shuō)明模型“寧缺毋濫”——預(yù)測(cè)的框命中率很高但漏檢了很多真實(shí)目標(biāo)。編織袋識(shí)別場(chǎng)景里漏檢和誤檢的代價(jià)不一樣質(zhì)檢場(chǎng)景漏檢有破損袋沒(méi)發(fā)現(xiàn)比誤檢好袋被標(biāo)記為破損嚴(yán)重而分揀場(chǎng)景誤檢把別的物體當(dāng)編織袋抓比漏檢更麻煩。落地時(shí)要根據(jù)實(shí)際業(yè)務(wù)調(diào)整置信度閾值。第二個(gè)信號(hào)是val_loss曲線先降后升。這是過(guò)擬合的經(jīng)典信號(hào)。看到loss在驗(yàn)證集上升應(yīng)該立即停止訓(xùn)練不要等它跑完所有epochs。YOLOv8里可以直接用早停調(diào)參避免這個(gè)問(wèn)題。第三個(gè)信號(hào)是不同類(lèi)別的mAP差異。如果發(fā)現(xiàn)“彩色袋”的mAP特別低而“舊白袋”的mAP很高那大概率是彩色袋的訓(xùn)練樣本太少或顏色多樣性不足。這時(shí)需要回去補(bǔ)數(shù)據(jù)而不是改模型結(jié)構(gòu)。5.4 模型導(dǎo)出與端側(cè)部署注意事項(xiàng)訓(xùn)練完成的模型要落地到實(shí)際場(chǎng)景還需要做格式轉(zhuǎn)換和精度校驗(yàn)。我用的是一個(gè)標(biāo)準(zhǔn)流程# 導(dǎo)出ONNX格式 yolo export modelbest.pt formatonnx imgsz640 # 導(dǎo)出TensorRT格式NVIDIA GPU部署時(shí) yolo export modelbest.pt formatengine imgsz640 device0 # 導(dǎo)出NCNN格式手機(jī)/嵌入式端部署時(shí) # 先用ONNX導(dǎo)出再用ncnnoptimize轉(zhuǎn)換這里有個(gè)很多人忽略的細(xì)節(jié)導(dǎo)出后必須用驗(yàn)證集重新測(cè)一次精度因?yàn)閷?dǎo)出過(guò)程特別是INT8量化可能會(huì)導(dǎo)致精度下降。有個(gè)經(jīng)驗(yàn)精度下降在2個(gè)點(diǎn)以內(nèi)是正常的超過(guò)5個(gè)點(diǎn)就需要考慮改用FP16量化或者干脆用原始FP32模型部署。另外一個(gè)部署端的小經(jīng)驗(yàn)是輸入尺寸要和訓(xùn)練時(shí)保持一致。如果你訓(xùn)練時(shí)用640x640部署時(shí)也最好用640x640不要為了追求速度改成416x416——模型的感受野和anchors對(duì)YOLOv5及之前的版本都是按訓(xùn)練時(shí)的尺寸設(shè)計(jì)的改了之后精度會(huì)顯著下降。YOLOv8已經(jīng)改成anchor-free結(jié)構(gòu)對(duì)輸入尺寸變化沒(méi)那么敏感但建議還是保持一致。6. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄6.1 標(biāo)注階段的高頻問(wèn)題問(wèn)題一多目標(biāo)重疊時(shí)邊界框怎么畫(huà)裝箱場(chǎng)景下編織袋經(jīng)常堆疊在一起兩個(gè)袋子的邊緣重合肉眼根本分不清邊界。我的規(guī)則是能明確辨認(rèn)出是兩個(gè)獨(dú)立目標(biāo)的分開(kāi)標(biāo)辨認(rèn)不出邊界的合并成一個(gè)框。標(biāo)成兩個(gè)框但框得不準(zhǔn)對(duì)訓(xùn)練的傷害遠(yuǎn)大于標(biāo)成一個(gè)框。這條經(jīng)驗(yàn)來(lái)自一次翻車(chē)經(jīng)歷我硬把一張圖里堆疊的三個(gè)袋子標(biāo)成三個(gè)框結(jié)果邊界框IoU很低模型在這個(gè)位置反復(fù)震蕩訓(xùn)練時(shí)損失一直下不去。問(wèn)題二模糊的圖要不要?jiǎng)h前面提到“人眼能辨認(rèn)就留辯認(rèn)不出就刪”但有一種特例部分模糊但袋體邊緣清晰的圖可以留。比如對(duì)焦對(duì)準(zhǔn)了袋子正面但袋子邊緣有點(diǎn)虛化這種圖反而有助于模型學(xué)習(xí)“關(guān)注核心區(qū)域、忽略邊緣噪聲”。關(guān)鍵判斷標(biāo)準(zhǔn)是目標(biāo)主體區(qū)域的紋理是否可辨。問(wèn)題三不同標(biāo)注員之間標(biāo)準(zhǔn)不統(tǒng)一怎么辦我的經(jīng)驗(yàn)是在開(kāi)始標(biāo)注前用10張圖做“試標(biāo)”。讓每個(gè)標(biāo)注員獨(dú)立標(biāo)注這10張然后對(duì)比差異。通常你會(huì)發(fā)現(xiàn)類(lèi)別判斷的差異不大但邊界框的貼合度差異很大。針對(duì)邊界框的差異我不要求大家做到100%精確只要框中心偏移小于3像素、長(zhǎng)寬誤差小于10%就視為合格。追求像素級(jí)精確會(huì)大幅拖慢進(jìn)度而收益微乎其微。6.2 訓(xùn)練階段的高頻問(wèn)題問(wèn)題一loss一直在0.5以上下不去這個(gè)現(xiàn)象我遇到過(guò)幾次排查詢問(wèn)之后發(fā)現(xiàn)是標(biāo)注格式問(wèn)題。YOLO格式的標(biāo)簽是歸一化的中心坐標(biāo)x_center, y_center和寬高width, height如果代碼里誤用了左上角坐標(biāo)x_min, y_min模型根本學(xué)不到正確的目標(biāo)位置loss當(dāng)然降不下去。檢查方式很簡(jiǎn)單隨機(jī)抽幾張圖把標(biāo)簽畫(huà)出來(lái)看一眼——如果發(fā)現(xiàn)框的位置完全錯(cuò)亂十有八九是格式問(wèn)題。問(wèn)題二訓(xùn)練精度很高但實(shí)際場(chǎng)景檢測(cè)率很低這是典型的過(guò)擬合到訓(xùn)練集場(chǎng)景的表現(xiàn)。訓(xùn)練圖主要是在倉(cāng)庫(kù)拍的實(shí)際用的時(shí)候搬到室外環(huán)境一變模型就瞎了。排查方法把實(shí)際場(chǎng)景里的失敗案例收集起來(lái)統(tǒng)計(jì)失敗案例里是否有訓(xùn)練集未出現(xiàn)的背景特征比如樹(shù)影、鐵欄桿、地面紋理變化。修復(fù)辦法不是盲目增加數(shù)據(jù)量而是針對(duì)失敗場(chǎng)景定向采集數(shù)據(jù)——把相機(jī)放到實(shí)際部署的位置和環(huán)境里拍幾百?gòu)埼礃?biāo)注圖然后做半自動(dòng)標(biāo)注效率很高。問(wèn)題三小目標(biāo)編織袋容易被漏檢600張圖里如果有大量遠(yuǎn)景拍攝的小目標(biāo)模型會(huì)對(duì)小圖不敏感。排查方法是把驗(yàn)證集結(jié)果可視化出來(lái)看漏檢的目標(biāo)是不是都是小框。解決思路優(yōu)先級(jí)從高到低最高效的是調(diào)高輸入分辨率其次是添加SAHI切片推理把圖像切成小塊分別檢測(cè)再合并最后才是增加小目標(biāo)訓(xùn)練樣本。對(duì)編織袋場(chǎng)景來(lái)說(shuō)調(diào)高輸入分辨率到1024通常能直接把小目標(biāo)mAP提升5到10個(gè)百分點(diǎn)。6.3 關(guān)于精度的合理預(yù)期別被指標(biāo)騙了最后說(shuō)一個(gè)很多人忽視的問(wèn)題600張標(biāo)注數(shù)據(jù)訓(xùn)練出來(lái)的模型mAP50到了0.85看起來(lái)不錯(cuò)但實(shí)際業(yè)務(wù)評(píng)估時(shí)應(yīng)該用什么樣的標(biāo)準(zhǔn)我的建議是用業(yè)務(wù)相關(guān)指標(biāo)而不是純mAP。比如對(duì)于“傳送帶是否有編織袋”這個(gè)場(chǎng)景真正有價(jià)值的是精確率和召回率在特定置信度閾值下的值而不是mAP這種平均指標(biāo)。因?yàn)槟憧梢钥空{(diào)低置信度閾值讓召回率接近100%但誤檢率會(huì)飆升也可以靠調(diào)高閾值讓誤檢率趨近于0但漏檢就多了。業(yè)務(wù)方需要的是一個(gè)具體的置信度閾值和這個(gè)閾值下precision/recall的準(zhǔn)確數(shù)值而不是一個(gè)模糊的mAP。我在交付數(shù)據(jù)集和模型時(shí)通常附帶一份“閾值選擇建議表”列出不同置信度閾值下模型的precision、recall、F1值讓使用方根據(jù)業(yè)務(wù)成本自行選擇工作點(diǎn)。這種做法比單純說(shuō)“模型精度85%”要專(zhuān)業(yè)得多也更容易獲得信任。關(guān)于后續(xù)擴(kuò)展的幾個(gè)實(shí)操方向前面提到600張是種子數(shù)據(jù)這里給幾個(gè)具體可落地的擴(kuò)展方向每一條我都試過(guò)或驗(yàn)證過(guò)可行性。第一條是半監(jiān)督自訓(xùn)練。用現(xiàn)有模型對(duì)大規(guī)模未標(biāo)注圖預(yù)測(cè)篩選高置信度樣本比如大于0.9自動(dòng)加入訓(xùn)練集作為偽標(biāo)簽。這里要注意兩個(gè)陷阱一是偽標(biāo)簽不能全加只加高置信度且與已有類(lèi)別分布不沖突的二是要控制偽標(biāo)簽占總訓(xùn)練集的比例超過(guò)30%容易導(dǎo)致模型固步自封。我在編織袋場(chǎng)景下測(cè)試用這個(gè)方法把訓(xùn)練集從600擴(kuò)到1800精度提升約4個(gè)百分點(diǎn)。第二條是跨場(chǎng)景微調(diào)。如果未來(lái)要在不同工廠、不同國(guó)家部署可以把當(dāng)前模型作為預(yù)訓(xùn)練模型在新的場(chǎng)景采集少量圖100到200張做微調(diào)。這比每到一個(gè)場(chǎng)景都從零訓(xùn)練數(shù)據(jù)要高效得多。遷移學(xué)習(xí)對(duì)小數(shù)據(jù)集的價(jià)值怎么強(qiáng)調(diào)都不過(guò)分。第三條是主動(dòng)學(xué)習(xí)閉環(huán)。部署后的模型持續(xù)收集低置信度樣本每周人工審核一次并加入訓(xùn)練集形成一個(gè)持續(xù)迭代的閉環(huán)。這個(gè)機(jī)制能讓模型在實(shí)際環(huán)境中越用越準(zhǔn)最終收斂到90%以上的業(yè)務(wù)可用精度。我在實(shí)際做這個(gè)數(shù)據(jù)集時(shí)最深的體會(huì)是做視覺(jué)識(shí)別項(xiàng)目80%的工作都在數(shù)據(jù)上訓(xùn)練模型本身反而是最輕松的一環(huán)。數(shù)據(jù)采集的規(guī)劃、清洗的標(biāo)準(zhǔn)、標(biāo)注的規(guī)范、劃分的策略每一環(huán)都會(huì)在最終的模型指標(biāo)上體現(xiàn)出來(lái)。600多張圖聽(tīng)起來(lái)不多但如果每一步都做扎實(shí)它完全能支撐一個(gè)實(shí)用的業(yè)務(wù)方案。最后再分享一個(gè)小技巧做數(shù)據(jù)集時(shí)記得記錄每張圖的來(lái)源信息和采集參數(shù)這個(gè)看起來(lái)不起眼的metadata在后期排查模型問(wèn)題時(shí)會(huì)成為最寶貴的一手資料——很多看似是算法的問(wèn)題溯源到最后都是數(shù)據(jù)采集階段埋下的隱患。本文還有配套的精品資源點(diǎn)擊獲取