實(shí)戰(zhàn):從數(shù)據(jù)標(biāo)注到UI部署全流程)
去樓下便利店自助結(jié)賬第一次用就翻車了三瓶飲料疊在一起系統(tǒng)只識別出兩瓶兩包外包裝幾乎一樣的薯片直接算成了同款。后來我自己基于YOLOv8搭了一套超市商品識別檢測系統(tǒng)把線下采集的超市貨架數(shù)據(jù)、YOLO格式標(biāo)注、模型訓(xùn)練到帶UI界面的Python項(xiàng)目源碼全部串起來最后跑出了一個(gè)真正能部署到收銀場景的Demo。這篇文章就是這次完整落地過程的技術(shù)復(fù)盤內(nèi)容包括為什么在眾多目標(biāo)檢測方案里選了YOLOv8、超市商品數(shù)據(jù)集是怎么從零構(gòu)造并清洗的、訓(xùn)練調(diào)參過程中哪些參數(shù)真正影響效果以及模型如何導(dǎo)出、封裝、接到可視化界面并扛住現(xiàn)場復(fù)雜光線和遮擋干擾。不管你是準(zhǔn)備做畢業(yè)設(shè)計(jì)還是想給線下門店做一個(gè)輕量級的商品識別結(jié)算系統(tǒng)這套流程都能直接參考復(fù)現(xiàn)。1. 超市商品識別任務(wù)里YOLOv8為什么成了首選方案1.1 這個(gè)任務(wù)比想象中難別拿普通物體檢測的思路套很多人一聽“識別商品”第一反應(yīng)是“這不就是目標(biāo)檢測嘛訓(xùn)練一個(gè)模型就行”。真正把超市貨架上的東西拉到鏡頭前才發(fā)現(xiàn)這個(gè)場景比通用檢測要刁鉆得多。超市商品識別的難點(diǎn)主要集中在幾個(gè)方面。第一個(gè)是類別多且外觀極度相似同一類飲料的不同口味、不同容量包裝主色調(diào)一樣只靠局部顏色差異區(qū)分第二個(gè)是商品密集擺放貨架層板上同類商品一個(gè)挨一個(gè)遮擋嚴(yán)重結(jié)算臺上商品也會(huì)互相疊壓第三個(gè)是光線條件差超市頂燈往往帶強(qiáng)烈暖色光玻璃瓶和鋁罐反光嚴(yán)重模型經(jīng)常把高光區(qū)域當(dāng)成物體邊緣第四個(gè)是同一SKU的多規(guī)格包裝同一款零食有大袋、小袋、家庭裝寬高比差很多用固定錨框思路的老模型很吃力。傳統(tǒng)視覺方案在這個(gè)場景里基本不可行。做顏色直方圖匹配換一種燈光顏色就失效做形狀模板匹配商品只要旋轉(zhuǎn)幾度或者被遮住一角匹配率立刻掉下來掃二維碼倒是穩(wěn)定但不是所有商品都有標(biāo)準(zhǔn)碼生鮮、散裝稱重商品、超市自有品牌包裝經(jīng)常沒有可掃的碼。所以只能上深度學(xué)習(xí)目標(biāo)檢測。1.2 各代目標(biāo)檢測框架橫向?qū)Ρ茸錾唐窓z測市面上可選的無非就是兩階段檢測器、單階段檢測器和最新的端到端方案。我自己把主流的幾個(gè)都跑過一輪也搜過不少公開評測數(shù)據(jù)這里直接放一張對比表。方案精度同數(shù)據(jù)集下mAP參考值推理速度訓(xùn)練復(fù)雜度部署生態(tài)適合場景Faster R-CNN高但優(yōu)勢隨數(shù)據(jù)量增大而縮小慢幀率偏低需要調(diào)RPN、候選框相關(guān)參數(shù)中TensorRT可用但有兼容坑小目標(biāo)密集但實(shí)時(shí)性要求低的場景SSD中低快但易漏檢低一般老框架維護(hù)少簡單場景YOLOv5中高快低非常成熟網(wǎng)上資料多通用落地YOLOv8高快低官方庫自帶導(dǎo)出ONNX/TensorRT能力商品識別這種類內(nèi)差異大的場景端到端DETR類高大模型慢顯存要求高調(diào)參門檻高一般邊緣設(shè)備跑不動(dòng)長期研究項(xiàng)目而非快速落地之所以最后選定YOLOv8核心就幾條一是它改成了Anchor-Free結(jié)構(gòu)對高寬比差異大的商品包裝更友好不再依賴先驗(yàn)錨框的尺寸設(shè)置二是C2f結(jié)構(gòu)的特征融合讓淺層小目標(biāo)信息保留得更好貨架上那些小瓶飲料、小袋零食也能被召回三是官方庫自帶訓(xùn)練、驗(yàn)證、導(dǎo)出一條龍腳本省去大量造輪子的時(shí)間四是社區(qū)活躍踩到坑很快能找到解法。1.3 整套系統(tǒng)包含哪些模塊這個(gè)項(xiàng)目的最終形態(tài)并不是一個(gè)孤立的pt權(quán)重文件而是一套可運(yùn)行的完整鏈路攝像頭或圖片輸入經(jīng)過YOLOv8模型推理得到每個(gè)商品的類別和邊界框再走一個(gè)后處理模塊做置信度過濾、類別合并和價(jià)格計(jì)算最后把識別結(jié)果實(shí)時(shí)渲染到UI界面上顯示商品名、數(shù)量、識別置信度和總價(jià)。項(xiàng)目文件里包含模型權(quán)重、訓(xùn)練腳本、數(shù)據(jù)集標(biāo)注文件、UI界面代碼以及推理封裝模塊是一整套能直接打包運(yùn)行的Python項(xiàng)目。2. 數(shù)據(jù)的命脈超市商品訓(xùn)練集的構(gòu)造、標(biāo)注與質(zhì)量清洗2.1 數(shù)據(jù)從哪來光靠公開數(shù)據(jù)集遠(yuǎn)遠(yuǎn)不夠咨詢了某便利店的運(yùn)營工程師又結(jié)合我自己多次實(shí)拍經(jīng)驗(yàn)可以負(fù)責(zé)任地說公開的零售商品數(shù)據(jù)集只能用來驗(yàn)證流程不能直接撐起一個(gè)可用系統(tǒng)。公開數(shù)據(jù)集里的場景大多是國外超市、標(biāo)準(zhǔn)擺拍和國內(nèi)貨架的燈光、價(jià)簽、陳列密度差異很大模型訓(xùn)練出來一上真實(shí)貨架掉點(diǎn)非常明顯。我的數(shù)據(jù)來源分了三條線自有實(shí)拍數(shù)據(jù)拿手機(jī)和攝像頭去線下超市、便利店拍攝貨架和收銀臺場景覆蓋平拍、俯拍、斜45度視角并刻意選擇不同時(shí)段白天、傍晚、夜間彌補(bǔ)光線差異。公開數(shù)據(jù)集的可用子集只挑其中和自采類別重疊的商品圖。網(wǎng)絡(luò)渠道收集電商平臺商品圖可以補(bǔ)充大量白底圖但白底圖與實(shí)拍差異大只能做預(yù)訓(xùn)練冷啟動(dòng)不能作為主力。這三條線里自拍數(shù)據(jù)占比至少要拉到60%以上模型才可能在真實(shí)場景里看什么像什么。前期建議先選20個(gè)高頻商品類別做閉環(huán)驗(yàn)證每類采集到300~500張有效圖片再逐步擴(kuò)類而不是一上來就標(biāo)100個(gè)類。2.2 標(biāo)注規(guī)范邊界框怎么打直接決定模型學(xué)成什么樣標(biāo)注工具上我試過LabelImg和labelme還有Roboflow的在線標(biāo)注。如果只是做矩形檢測框LabelImg輕量夠用后期如果要轉(zhuǎn)到實(shí)例分割再換labelme。所有標(biāo)注最終都導(dǎo)出為YOLO格式的txt文件每行是“類別序號 中心點(diǎn)x 中心點(diǎn)y 框?qū)?框高”坐標(biāo)值是相對于圖片寬高的歸一化小數(shù)。但工具是次要的真正影響模型效果的是標(biāo)注口徑。有幾個(gè)坑必須提前定好規(guī)范??蛞o貼商品可見邊緣不要把商品背后的價(jià)簽、促銷牌包進(jìn)去否則模型會(huì)學(xué)會(huì)“連價(jià)簽一起框”。多瓶飲料整齊排列時(shí)框與框之間允許有輕微重疊但不能把一個(gè)商品框進(jìn)另一個(gè)的大半?yún)^(qū)域。商品被遮擋嚴(yán)重時(shí)只標(biāo)可見部分完全不出來的就不標(biāo)。遮擋超過一半的樣本前期寧可不標(biāo)后期再專門補(bǔ)充。對透明包裝和玻璃瓶標(biāo)注時(shí)以瓶身實(shí)際輪廓為準(zhǔn)不要把高光反射形成的白色區(qū)域當(dāng)成物體邊界剪掉。另外強(qiáng)調(diào)一點(diǎn)類別命名不要用中文也不要帶空格統(tǒng)一用拼音或英文小寫比如“soda”“chips”“milk”寫進(jìn)YAML時(shí)省去一堆編碼問題。2.3 數(shù)據(jù)清洗與易混淆類別處理標(biāo)注完不等于數(shù)據(jù)能用。我第一版直接拿標(biāo)注結(jié)果訓(xùn)練結(jié)果mAP很慘后來檢查才發(fā)現(xiàn)同一條貨架視頻里的連續(xù)幀很多重復(fù)進(jìn)訓(xùn)練集增強(qiáng)了模型對背景的記憶而不是對商品的識別還有一批網(wǎng)上抓的商品圖標(biāo)簽錯(cuò)了讓模型對某兩個(gè)類別徹底混亂。清洗時(shí)我做這幾步先按圖像哈希去重把同一場景的連拍幀用相似度閾值篩掉接著逐類檢查標(biāo)簽分布統(tǒng)計(jì)每個(gè)類別的bbox數(shù)量明顯偏低的類單獨(dú)補(bǔ)充拍攝最后人工抽檢最難的那批——兩種包裝差不多的飲料把它們單獨(dú)挑出來確認(rèn)是否有標(biāo)注張冠李戴。超市商品里最典型的就是易混淆對我用表格列一下。易混淆組合人工區(qū)分點(diǎn)補(bǔ)充數(shù)據(jù)策略某品牌蘇打水vs某品牌氣泡水瓶身標(biāo)簽主色和字體布局不同專門拍兩種瓶子混放、疊放的照片原味薯片vs番茄味薯片包裝正面大色塊區(qū)域不同增加多角度傾斜拍攝避免只看正面全脂牛奶vs脫脂牛奶包裝頂部色帶顏色不同瓶身幾乎一樣保證框內(nèi)包含頂部色帶區(qū)域不裁掉大瓶可樂vs小瓶可樂高寬比不同但平拍時(shí)比例感弱同時(shí)入鏡讓模型學(xué)到相對尺度2.4 數(shù)據(jù)集劃分防止貨架“同源數(shù)據(jù)”泄漏進(jìn)驗(yàn)證集劃分比例我一般按訓(xùn)練集:驗(yàn)證集:測試集 7:1.5:1.5。但比比例更重要的是按拍攝場景切分。同一時(shí)刻、同一機(jī)位連續(xù)拍攝的幀如果一部分進(jìn)訓(xùn)練集、一部分進(jìn)驗(yàn)證集驗(yàn)證集分?jǐn)?shù)會(huì)虛高模型實(shí)際泛化能力根本沒有那么強(qiáng)。我按“拍攝時(shí)間地點(diǎn)”作為分組單位一組數(shù)據(jù)整體劃入某一份集合這樣驗(yàn)證結(jié)果才真實(shí)可信。3. 訓(xùn)練實(shí)戰(zhàn)YOLOv8從默認(rèn)參數(shù)跑到穩(wěn)定收斂的全過程3.1 環(huán)境配置與數(shù)據(jù)集YAML組織方式訓(xùn)練前先把目錄和依賴?yán)眄?。我用的Python 3.10PyTorch2.x以及YOLOv8官方訓(xùn)練庫。項(xiàng)目的目錄結(jié)構(gòu)大致這樣project/ ├── datasets/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── labels/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── data.yaml ├── runs/ ├── models/ ├── train.py ├── infer.py └── ui/標(biāo)注好的txt文件要和圖片文件一一同名放到對應(yīng)的labels目錄下。然后寫一個(gè)data.yaml內(nèi)容如下path: ./datasets train: images/train val: images/val test: images/test nc: 20 names: 0: cola 1: soda 2: chips 3: milk # 后面按實(shí)際類別繼續(xù)列訓(xùn)練時(shí)我習(xí)慣不用命令行的一長串參數(shù)而是把關(guān)鍵參數(shù)寫進(jìn)一個(gè)Python腳本便于版本迭代和記錄。核心代碼如下from ultralytics import YOLO model YOLO(yolov8n.pt) results model.train( datadatasets/data.yaml, epochs200, imgsz640, batch16, device0, optimizerAdamW, lr00.0005, patience30, mosaic1.0, close_mosaic10, ampTrue, )3.2 默認(rèn)參數(shù)跑第一版結(jié)果哪里不對勁第一次訓(xùn)練我?guī)缀跞坑媚J(rèn)參數(shù)只改了數(shù)據(jù)路徑和epochs。200輪跑完驗(yàn)證集mAP50到了0.72看著還不錯(cuò)。但把模型接到攝像頭上跑真實(shí)貨架問題立刻暴露貨架中層的商品能識別最下層的小瓶裝漏檢嚴(yán)重兩個(gè)商品疊在一起時(shí)置信度雙雙掉到0.3以下反光的鋁罐包裝頻繁誤檢成別的類別。后來復(fù)盤發(fā)現(xiàn)問題不是模型結(jié)構(gòu)而是數(shù)據(jù)分布和推理設(shè)置訓(xùn)練集里貨架中層大尺寸樣本太多小目標(biāo)樣本不足驗(yàn)證集mAP高是因?yàn)轵?yàn)證集里大目標(biāo)占多數(shù)掩蓋了小目標(biāo)短板。最終的解決方向就是兩個(gè)數(shù)據(jù)層面補(bǔ)充小目標(biāo)樣本推理層面調(diào)整輸入分辨率和標(biāo)定閾值。3.3 調(diào)參過程的實(shí)測記錄下面這組參數(shù)是我在多次試驗(yàn)后穩(wěn)定下來的直接做成表格方便對照。參數(shù)第一版值調(diào)優(yōu)過程最終值imgsz640提升到960后小目標(biāo)mAP漲了約4個(gè)點(diǎn)但顯存和推理耗時(shí)翻倍最后取折中800epochs200用early stopping實(shí)際到155輪左右收斂300早停在合理范圍batch16顯存占用在16GB左右batch調(diào)到32會(huì)提示OOM16optimizerSGD換成AdamW后收斂更平穩(wěn)loss曲線不振蕩AdamWlr00.01AdamW配0.01偏高前20輪loss發(fā)散降到0.0005才穩(wěn)0.0005mosaic默認(rèn)1.0全程開mosaic容易在最后階段震蕩采用close_mosaic策略1.0close_mosaic0最后10輪關(guān)閉mosaic讓模型在真實(shí)分布上穩(wěn)定擬合10有一個(gè)很關(guān)鍵的細(xì)節(jié)別等訓(xùn)完再看曲線訓(xùn)練中要盯著val loss和mAP實(shí)時(shí)變化。我從第40輪開始每10輪跑一次驗(yàn)證發(fā)現(xiàn)mAP50-95在130輪附近開始原地抖動(dòng)當(dāng)時(shí)就意識到訓(xùn)練增益已經(jīng)耗盡。用early stopping機(jī)制可以自動(dòng)停但手動(dòng)盯一下更容易發(fā)現(xiàn)數(shù)據(jù)或參數(shù)層面而不是單純輪數(shù)層面的問題。3.4 透過指標(biāo)看本質(zhì)用混淆矩陣找到模型“臉盲”的類別只看mAP是遠(yuǎn)遠(yuǎn)不夠的。超市客戶關(guān)心的是“結(jié)算時(shí)不漏、不算錯(cuò)”。mAP50高但可能只是大類識別準(zhǔn)真正容易混淆的細(xì)分類根本看不出來。我訓(xùn)練完第一版打印混淆矩陣發(fā)現(xiàn)某品牌蘇打水和某品牌氣泡水互相誤檢的樣本數(shù)量占該類總樣本的11%。這個(gè)信息靠mAP看不出來必須看類別層面的混淆矩陣才能發(fā)現(xiàn)。同時(shí)還要理解precision和recall的權(quán)衡。在收銀場景漏檢一件商品的損失比多框一個(gè)空框更嚴(yán)重所以我把推理置信度閾值從默認(rèn)的0.5下調(diào)到0.35寧可多給幾個(gè)候選框讓員工肉眼復(fù)核也不要讓商品靜悄悄跳過結(jié)算。分類閾值調(diào)整之后實(shí)測漏檢率下降誤檢率略有上升但這個(gè)方向在業(yè)務(wù)上是正確的。4. 從權(quán)重文件到可用系統(tǒng)導(dǎo)出、封裝與UI展示層設(shè)計(jì)4.1 模型導(dǎo)出為ONNX推理速度提升多少訓(xùn)練好的pt文件不能直接丟給UI項(xiàng)目用一是慢二是依賴重型訓(xùn)練框架。我的做法是先導(dǎo)出為ONNX格式from ultralytics import YOLO model YOLO(datasets/weights/best.pt) model.export(formatonnx, dynamicTrue, imgsz800)導(dǎo)出后可以用ONNX Runtime加載推理CPU環(huán)境下幀率比原始PyTorch推理快不少。我之前在測試機(jī)上的對比值PyTorch推理一幀約160msONNX Runtime約90ms如果再用TensorRT INT8量化壓到邊緣盒子上可以跑到30ms以內(nèi)。精度損失方面常規(guī)部署用FP32的ONNX基本看不出掉點(diǎn)INT8會(huì)掉2~3個(gè)mAP點(diǎn)商品細(xì)分場景不太建議激進(jìn)量化。這里有一個(gè)容易踩的坑動(dòng)態(tài)尺寸設(shè)置。UI畫面輸入尺寸和訓(xùn)練尺寸不一致時(shí)模型會(huì)自動(dòng)縮放但如果動(dòng)態(tài)軸沒開啟固定輸入尺寸的ONNX遇到非640分辨率的視頻流就會(huì)報(bào)錯(cuò)。我建議導(dǎo)出時(shí)把dynamicTrue打開代價(jià)是多約幾十MB內(nèi)存但對前端更友好。4.2 Python部署封裝圖片、單幀視頻流統(tǒng)一走一個(gè)類推理封裝我建議寫成一個(gè)獨(dú)立的類這樣UI和后端接口都能復(fù)用。核心結(jié)構(gòu)就是加載模型、接收圖像、返回檢測結(jié)果列表。class ShelfDetector: def __init__(self, model_path, conf_threshold0.35, iou_threshold0.45): self.model YOLO(model_path) self.conf conf_threshold self.iou iou_threshold def detect(self, frame): results self.model.predict( sourceframe, confself.conf, iouself.iou, verboseFalse ) dets [] for r in results: boxes r.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() cls_id int(box.cls[0]) score float(box.conf[0]) dets.append({ box: [x1, y1, x2, y2], cls_id: cls_id, label: self.model.names[cls_id], score: score }) return dets實(shí)際項(xiàng)目里UI界面并不是直接調(diào)用model.predict()裸方法而是通過這個(gè)ShelfDetector類傳入OpenCV讀取的幀。這樣換模型、調(diào)閾值只改一處UI層保持穩(wěn)定。4.3 UI界面PyQt5桌面端和Gradio Web端怎么選UI是整個(gè)系統(tǒng)最容易做成“看起來像作業(yè)、用起來卻雞肋”的部分。我這次對比了三條路線分別試過之后給大家一個(gè)明確建議。方案優(yōu)點(diǎn)缺點(diǎn)適合場景PyQt5/PySide6桌面端界面定制強(qiáng)、可嵌入收銀軟件、支持?jǐn)z像頭實(shí)時(shí)顯示流暢開發(fā)量大、打包體積大正式商用收銀系統(tǒng)、實(shí)驗(yàn)室演示Gradio Web界面幾行代碼出網(wǎng)頁、有攝像頭和圖片上傳組件、自帶可視化定制性弱、不適合集成到現(xiàn)有業(yè)務(wù)系統(tǒng)快速demo、遠(yuǎn)程展示、畢設(shè)答辯Flask Vue前后端接口清晰、可對接現(xiàn)有收銀中間件開發(fā)周期最長、需要前后端基礎(chǔ)真正要跟門店ERP打通的生產(chǎn)系統(tǒng)如果你的目標(biāo)是快速看到效果并在答辯或演示中不卡殼首選Gradio。我從封裝好推理類到寫出一個(gè)可交互界面只用了不到20行代碼還自帶攝像頭輸入組件。但如果你想做成一個(gè)能放在某便利店收銀臺旁邊試用的桌面軟件PyQt5是更合適的路線。UI界面重點(diǎn)展示四塊內(nèi)容實(shí)時(shí)視頻畫面、識別出的商品列表、每件商品的置信度、以及結(jié)算總價(jià)??們r(jià)的實(shí)現(xiàn)并不復(fù)雜在代碼里維護(hù)一個(gè)“類別編號到單價(jià)”的映射字典按檢測結(jié)果累加即可。4.4 真實(shí)場景的后處理置信度閾值、幀間平滑和提示音模型框出來一堆結(jié)果直接顯示在界面上會(huì)閃爍得讓人崩潰。同樣一件商品前一幀置信度0.6后一幀變成0.3就導(dǎo)致畫面上框忽隱忽現(xiàn)。我加了兩層后處理一是幀間平滑連續(xù)5幀都識別出同一類別且框位置基本重疊才判定為“確認(rèn)識別”并在界面上置為穩(wěn)定狀態(tài)二是短時(shí)窗口去抖某商品在5幀內(nèi)消失又出現(xiàn)仍當(dāng)作同一個(gè)商品處理不重復(fù)計(jì)價(jià)。接攝像頭時(shí)還要加一個(gè)業(yè)務(wù)邏輯給每件商品設(shè)置“最少間隔時(shí)長”防止同框商品被反復(fù)觸發(fā)累計(jì)價(jià)格。這套邏輯在真實(shí)結(jié)算場景里非常關(guān)鍵測試時(shí)多試幾次就會(huì)發(fā)現(xiàn)沒有去重邏輯的結(jié)算金額會(huì)翻好幾倍。5. 部署后才知道的坑光照、遮擋、同款多規(guī)格與模型回爐5.1 冷白燈、暖黃燈、反光瓶一個(gè)都不能放過第一次把演示系統(tǒng)搬到另一個(gè)便利店發(fā)現(xiàn)識別率比我們自己測試環(huán)境掉了一截。排查之后定位到光照差異訓(xùn)練數(shù)據(jù)大多在標(biāo)準(zhǔn)白光下拍攝現(xiàn)場用的是暖黃光玻璃瓶反射出來的顏色完全變了。后來在訓(xùn)練階段加了強(qiáng)力的HSV擾動(dòng)增強(qiáng)把色調(diào)、飽和度、明度的隨機(jī)變化幅度加大同時(shí)采集數(shù)據(jù)時(shí)有意識地覆蓋暖光和冷光兩種場景。部署時(shí)我還加了一個(gè)簡單預(yù)處理把視頻幀先做白平衡校正再送入模型這步用OpenCV的灰度世界算法就能實(shí)現(xiàn)成本很低收益明顯。5.2 密集擺放、互相遮擋是小目標(biāo)漏檢的元兇貨架上的商品不可能是整齊單排的。同類商品前后疊放、飲料瓶互相遮擋、收銀臺上的商品堆在一起這類情況如果訓(xùn)練集里不夠多推理時(shí)就會(huì)漏框。我的建議是在訓(xùn)練集里專門加一組“密集遮擋模擬圖”用程序把商品圖按隨機(jī)位置拼貼到大圖上再打亂順序。也可以用簡單的圖像拼接腳本批量生成帶標(biāo)注的合成樣本注意合成圖需要確保商品比例和真實(shí)場景接近不要為了增加數(shù)量而做出扭曲變形。這類合成樣本作為補(bǔ)充可以但不要讓它超過總數(shù)據(jù)量的20%否則模型會(huì)對合成背景產(chǎn)生依賴。5.3 同一SKU的多規(guī)格包裝到底算一個(gè)類還是多個(gè)類做商品結(jié)算時(shí)最糾結(jié)的問題是分類粒度同一款飲料的500ml裝、1L裝、2L裝如果算三個(gè)類模型要學(xué)三個(gè)幾乎一樣的外觀如果算一個(gè)類結(jié)算時(shí)又不知道顧客拿的是大瓶還是小瓶價(jià)格沒法算。我最后的方案是檢測階段按外觀聚成“外觀類”每個(gè)外觀類內(nèi)部維護(hù)一個(gè)價(jià)格映射表同時(shí)用邊界框尺寸和寬高比作為輔助判據(jù)在識別邏輯層區(qū)分規(guī)格。比如500ml瓶子的框面積明顯小于1L瓶就自動(dòng)選擇對應(yīng)單價(jià)。這個(gè)后處理邏輯避開了硬讓模型學(xué)習(xí)細(xì)微尺寸差異的難題畢竟訓(xùn)練模型區(qū)分“幾乎一樣的瓶子但大小不同”是非常吃力不討好的。5.4 新包裝上市后模型如何快速回爐超市商品換包裝是家常便飯。同一個(gè)番茄醬三個(gè)月前紅色蓋子三個(gè)月后黃色蓋子老模型直接失效。前期設(shè)計(jì)項(xiàng)目結(jié)構(gòu)時(shí)就要預(yù)留迭代通道錯(cuò)檢圖片、新增包裝圖統(tǒng)一收集到擴(kuò)展數(shù)據(jù)集文件夾定期做一輪增量訓(xùn)練。增量訓(xùn)練不是從頭訓(xùn)一遍。我的做法是加載現(xiàn)有best.pt繼續(xù)訓(xùn)練30~50輪學(xué)習(xí)率設(shè)為正常訓(xùn)練的一半并把新數(shù)據(jù)與舊數(shù)據(jù)按1:2的比例混合防止災(zāi)難性遺忘。這個(gè)策略在兩次換包裝場景實(shí)測中召回率都恢復(fù)到90%以上。再提一個(gè)項(xiàng)目習(xí)慣所有訓(xùn)練、推理腳本都要鎖定固定隨機(jī)種子和依賴版本。我第一次沒有固定隨機(jī)種子同一份數(shù)據(jù)重新訓(xùn)練mAP波動(dòng)了將近兩個(gè)點(diǎn)這會(huì)給后續(xù)排查問題造成很多困擾。把seed、Python版本、torch版本、訓(xùn)練庫版本記錄在項(xiàng)目的requirements或配置文件中是保證結(jié)果可復(fù)現(xiàn)的最基本要求。最后分享一點(diǎn)個(gè)人經(jīng)驗(yàn)每次做這類檢測系統(tǒng)我都不會(huì)一開始就追求“全品類覆蓋”。先把20個(gè)高頻商品類別從數(shù)據(jù)、訓(xùn)練、UI、結(jié)算整條鏈路跑通讓客戶或?qū)熆吹綄?shí)物效果再根據(jù)反饋擴(kuò)展。這樣標(biāo)注成本可控迭代方向明確。如果你正準(zhǔn)備復(fù)現(xiàn)這個(gè)項(xiàng)目建議第一次訓(xùn)練時(shí)把batch降到8分辨率降到640先讓流程分鐘級跑通一遍再逐步增加復(fù)雜度——?jiǎng)e一上來就追求極致精度先把工程鏈路跑通后面調(diào)參才有依據(jù)。