參實踐)
1. 測試與可視化的整體思路MMDetection這個開源目標檢測工具箱大家在訓練上投入的精力往往最多但真正到了模型測試和結果可視化這一步反倒容易草草了事。其實測試和可視化是閉環(huán)里最關鍵的一環(huán)模型在驗證集上跑出什么指標、在真實場景里到底長什么樣全靠這一步來回答。如果只盯著訓練損失下降卻不知道預測框畫出來是什么效果那前面的調(diào)參工作基本屬于盲人摸象。很多同學第一次接觸MMDetection的test流程時第一反應是直接跑tools/test.py看到打印出一串mAP數(shù)值就覺得完事了。這里我想先強調(diào)一個容易被忽略的前提測試階段和訓練階段的數(shù)據(jù)處理方式是有差異的。MMDetection在訓練時為了增強魯棒性會做隨機翻轉、隨機尺度變化、馬賽克之類的操作而測試時這些都應該關掉保留原始分辨率或者只做固定尺度的縮放這樣才能真實反映模型在干凈數(shù)據(jù)上的表現(xiàn)。好在MMDetection的設計已經(jīng)內(nèi)置了pipeline的區(qū)分train_pipeline和test_pipeline各自獨立配置但從思路上理解這個差異能幫你在自定義數(shù)據(jù)時少踩坑。另外一個核心思路是可視化要放在指標之前做。我第一次跑一個新數(shù)據(jù)集時習慣先輸出幾張可視化結果圖粗略檢查預測框的坐標是否貼合目標、類別標簽是否正確然后再去看mAP、AR這些數(shù)字。因為指標是聚合的損失它可以告訴你整體好還是壞但不會告訴你具體錯在哪。比如mAP偏低可能是定位偏差、分類混淆、重復檢測、小目標漏檢四種完全不同的病根治療方案完全不同??梢暬苤苯佣ㄎ徊≡钸@是任何指標都替代不了的。測試和可視化適合誰來做不光是做算法研究的同學做工程落地的朋友更需要。經(jīng)常有做巡檢、安防、工業(yè)質檢的工程師朋友跟我聊說離線指標挺好但部署到現(xiàn)場效果不穩(wěn)定。這種問題十有八九能從測試可視化里看出端倪——場景光照變化、遮擋、目標尺度分布和訓練集不一致這些在畫框圖上一目了然。所以這篇文章我會從配置、命令行、原理解析、常見坑這幾個角度把這套流程完整拆開給你一份可以直接參考的實操方案。2. 測試階段的核心配置解析2.1 test_pipeline的數(shù)據(jù)處理鏈路MMDetection的測試流程本質上也是通過DataLoader驅動把測試數(shù)據(jù)從硬盤上的圖片變成可以直接喂進模型的張量。這條鏈路里的test_pipeline決定了模型推理時看到的數(shù)據(jù)長什么樣直接關系到預測結果的可靠性。先看一個常見的test_pipeline長什么樣。以RetinaNet或Faster R-CNN這類檢測模型為例配置文件里的測試數(shù)據(jù)處理單元通常由LoadImageFromFile、Resize、LoadAnnotations、PackDetInputs這幾個組件組成。LoadImageFromFile負責把圖片讀到內(nèi)存并解碼成數(shù)組Resize負責把圖片縮放到模型輸入尺寸LoadAnnotations負責把標注文件通常是COCO格式的JSON解析成模型需要的格式PackDetInputs負責把圖像數(shù)據(jù)和標注信息打包成一個統(tǒng)一的數(shù)據(jù)結構DetDataSample供模型推理時消費。這里最需要關注的是Resize的策略。MMDetection在測試推理時為了保證不同尺寸圖片能組成一個batch會先把所有圖片縮放到同一個尺度。常見的做法是保持長寬比縮放讓短邊固定為一個值比如img_scale(1333, 800)表示長邊不超過1333、短邊固定為800。如果測試時你想保持原始分辨率可以把img_scale設得足夠大也可以直接讓Resize不做縮放但那樣做batch內(nèi)圖片尺寸不一致MMDetection的collate函數(shù)需要額外處理實際中不推薦。我的經(jīng)驗是按訓練時用的img_scale來設定測試尺度這樣數(shù)據(jù)分布最接近訓練狀態(tài)指標參考價值最高。2.2 test_dataloader與test_evaluator的配置邏輯在MMDetection 3.x版本中測試配置被拆分成test_dataloader、test_evaluator、test_cfg三塊。test_dataloader里有batch_size、num_workers、dataset和sampler四個關鍵子配置。batch_size要結合顯存來定測試階段不需要做反向傳播梯度計算關閉顯存占用比訓練小很多通??梢栽O成訓練時的一倍或兩倍。num_workers決定數(shù)據(jù)加載線程數(shù)建議在Linux下用nproc命令看看物理核數(shù)一般設為8到12比較穩(wěn)妥設太高反而可能引起進程切換開銷過大。test_evaluator指定用哪種指標評測方式最常用的是CocoMetric。這個配置里核心參數(shù)是ann_file標注文件路徑、metric比如bbox或segm、classwise是否輸出每個類別獨立的AP值。我習慣把classwiseTrue打開因為只看整體mAP會掩蓋類別不均衡的問題。比如一個數(shù)據(jù)集里貓和狗的數(shù)量比例是10比1整體mAP可能還湊合但狗的AP往往慘不忍睹通過classwise能快速定位到哪個類別拖了后腿。test_cfg里還有一個容易被忽略的參數(shù)就是推理時的det_threshold之類的后處理配置。測試階段模型會輸出大量候選框一般通過NMS非極大值抑制篩選之后再用score_thr比如0.05或0.01過濾掉置信度過低的框。這里要說明一個細節(jié)評測指標計算時mAP本身就兼顧了不同置信度閾值下的精度和召回率所以score_thr設低一點如0.01不會漏報評測結果更接近模型的真實能力。如果你設成0.5mAP會有虛高的傾向因為相當于人為砍掉了大量低置信度檢測讓precision看起來很漂亮。做可視化時卻恰恰相反建議把score_thr調(diào)高到0.3或0.5只看高置信度的預測圖面更干凈、說服力更強。下面給一份精簡的測試配置片段方便你對照檢查自己的配置文件# configs/_base_/datasets/coco_detection.py test_dataloader dict( batch_size2, num_workers4, persistent_workersTrue, samplerdict(typeDefaultSampler, shuffleFalse), datasetdict( typeCocoDataset, data_rootdata/coco/, ann_fileannotations/instances_val2017.json, data_prefixdict(imgval2017/), pipeline[ dict(typeLoadImageFromFile), dict(typeResize, scale(1333, 800), keep_ratioTrue), dict(typeLoadAnnotations, with_bboxTrue), dict(typePackDetInputs, meta_keys(img_id, img_path, ori_shape, img_shape, scale_factor)) ])) test_evaluator dict( typeCocoMetric, ann_filedata/coco/annotations/instances_val2017.json, metricbbox, classwiseTrue, format_onlyFalse) test_cfg dict(typeTestLoop, det_threshold0.01)注意PackDetInputs里meta_keys這個參數(shù)它決定了哪些原始信息會被保留在數(shù)據(jù)樣本中img_shape、scale_factor是可視化時反向映射坐標必須的信息千萬別省。如果你自定義了可視化腳本需要用到原始圖像路徑或尺寸記得在這里補充對應的meta_key。3. 測試命令的完整實操流程3.1 基于訓練好的權重跑測試訓練完模型或者拿到一個預訓練權重測試是第一步。MMDetection標準的測試命令長這樣python tools/test.py \ configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py \ work_dirs/faster-rcnn_r50_fpn_1x_coco/epoch_12.pth \ --work-dir work_dirs/faster-rcnn_r50_fpn_1x_coco/test_epoch12 \ --cfg-options test_evaluator.classwiseTrue \ --show-dir work_dirs/faster-rcnn_r50_fpn_1x_coco/vis_results三個位置參數(shù)要記牢第一個是配置文件路徑第二個是權重文件路徑第三個可選是日志和評測結果的輸出目錄。--work-dir用來指定測試日志、評測pkl文件的落盤位置建議每次測試都單獨設置一個子目錄避免和訓練日志混在一起。--show-dir就是輸出可視化圖片的目錄只要指定了這個參數(shù)工具腳本會在跑完指標評測后自動把所有測試圖片都畫上預測框保存下來。--cfg-options可以臨時覆蓋配置里任何參數(shù)不需要改配置文件本身適合快速驗證某個參數(shù)的影響比如把classwise打開。在跑測試之前打開配置文件確認一下model.test_cfg的配置。以Faster R-CNN為例test_cfg里通常會有nms的iou_threshold默認0.5和max_per_img默認100。max_per_img決定了每張圖最終保留的檢測框上限設太小會丟失部分目標設太大會讓結果包含大量低質量框可視化時畫面也亂100是精度和可讀性的平衡點。測試過程跑完后終端會打印類似這樣的內(nèi)容coco/bbox_mAP: 0.376 coco/bbox_mAP_50: 0.584 coco/bbox_mAP_75: 0.405 coco/bbox_mAP_s: 0.209 coco/bbox_mAP_m: 0.417 coco/bbox_mAP_l: 0.493這些指標含義得先說透因為很多人只看一個mAP就下結論。mAP_50表示IoU閾值0.5下的平均精度mAP_75是IoU閾值0.75下的平均精度后者更嚴格對定位精度要求更高。mAP_s/m/l分別是小、中、大目標的平均精度COCO數(shù)據(jù)集的定義是小目標面積小于32x32大目標面積大于96x96。如果你的項目場景里小目標居多就得重點盯mAP_s這個指標比整體mAP更能反映實際效果。3.2 用測試結果pkl做更靈活的分析如果不指定--show-dir工具腳本默認會生成一個results開頭的.pkl文件里面保存了模型在測試集上每張圖的全部預測信息包括框坐標、置信度分數(shù)、類別ID。這個文件是后續(xù)做各種自定義分析的“原材料”我強烈建議每次測試都保留它。比如你在測試腳本里加上--out work_dirs/test_result.pkl參數(shù)就能把預測結果整個dump出來。拿到pkl文件后有幾個很實用的分析方向。第一個是看置信度分布把每張圖的預測框按置信度從高到低排列統(tǒng)計不同置信度區(qū)間里正確檢測和誤檢的數(shù)量可以幫你判斷模型是“猶豫型”還是“自信型”。第二個是做PR曲線分析雖然mAP已經(jīng)聚合了PR曲線的面積但PR曲線的形狀能告訴你模型更擅長保精度還是保召回對業(yè)務上線時設置置信度閾值的參考價值很大。第三個是分析錯誤類型比如用TIDE之類的工具庫把檢測錯誤分類成定位誤差、分類混淆、重復檢測、背景誤檢等幾類有針對性地調(diào)優(yōu)。寫一段簡單代碼看看怎么讀取和分析pkl文件import pickle with open(work_dirs/test_result.pkl, rb) as f: results pickle.load(f) # MMDetection 3.x中results是DetDataSample列表 for sample in results[:5]: # 從gt_instances取真實框從pred_instances取預測框 gt_bboxes sample.gt_instances.bboxes.tolist() pred_bboxes sample.pred_instances.bboxes.tolist() pred_scores sample.pred_instances.scores.tolist() print(gt num:, len(gt_bboxes), pred num:, len(pred_bboxes)) print(max score:, max(pred_scores) if pred_scores else 0)這種腳本寫得越早越好因為后續(xù)換backbone、調(diào)anchor、調(diào)loss都需要用同一套分析腳本對比前后差異有了腳本就可以做到量化對比而不是誰訓完誰說了算。我曾經(jīng)把五六個版本的pkl合并在一起做可視化對比一眼就看出來某個版本在特定類別上召回率提升很多但在遮擋場景下誤檢也增多這種Trade-off只靠看單獨一個mAP根本發(fā)現(xiàn)不了。3.3 帶上可視化一起跑--show-dir的細節(jié)--show-dir參數(shù)是MMDetection 3.x內(nèi)置的可視化入口。指定它之后你不需要額外寫繪圖代碼測試腳本會在每個epoch的評估階段結束后遍歷測試集圖片把預測框和真實框畫到原圖上保存到指定目錄。對著一張圖你能直觀看到兩個方面預測框通常用藍色或綠色和真實框通常用紅色存在的錯檢、漏檢都能看出來。默認只畫預測框如果你想把真實框一起畫出來做對比需要確保test_pipeline里包含LoadAnnotations并且在配置文件的visualizer里設置draw_gtTrue??梢暬Y果的文件名默認是原圖文件名.jpg。如果你的測試圖片很多建議按類別或場景建子目錄否則幾百上千張圖堆在一起想找某一特定場景非常麻煩。另外建議在--cfg-options里加上visualizer.save_dirwork_dirs/vis_xxx把可視化目錄獨立出來不要和pkl文件混在一起。有一點值得單獨提醒test.py的可視化是邊推理邊畫圖全程不中斷但這種方式在高分辨率圖片上會明顯拖慢測試速度因為畫圖本身也是IO操作。如果你只是需要跑指標不一定要可視化就別開--show-dir如果必須要可視化建議用小一點的測試集子集做展示比如隨機抽200張效果一樣的卻能省不少時間。后續(xù)我會講怎么優(yōu)雅地做這種抽樣可視化。4. 靈活的可視化方案與手工可視化實踐4.1 使用內(nèi)置工具腳本快速出圖除了用--show-dirMMDetection還提供了一個專門的可視化腳本tools/analysis_tools/browse_dataset.py雖然它最初設計是給訓練前檢查數(shù)據(jù)標注用的但也能用來查看帶預測框的結果——如果你把模型權重掛載上去的話。大部分情況下--show-dir已經(jīng)夠用了。內(nèi)置可視化的最大好處是零代碼缺點是定制能力弱。比如你想把置信度分數(shù)直接顯示在框邊上默認畫布不展示想按類別用不同顏色區(qū)分默認是隨機顏色想只顯示置信度大于0.5的框默認是全部顯示。遇到這些需求就得自己寫腳本了。4.2 手工可視化腳本的完整實現(xiàn)我平時用得最多的可視化方案還是基于DetDataSample結構自己寫繪圖腳本。這樣可控性最強想調(diào)什么調(diào)什么。下面給出一份可以直接借鑒的腳本結合了pkl結果和原圖路徑進行可視化import os import pickle import cv2 import numpy as np from mmdet.visualization import DetLocalVisualizer with open(work_dirs/test_result.pkl, rb) as f: results pickle.load(f) # 假設測試圖片在test_imgs目錄 image_root data/coco/val2017 save_root work_dirs/vis_custom os.makedirs(save_root, exist_okTrue) for sample in results: img_path sample.metainfo[img_path] image cv2.imread(img_path) pred_instances sample.pred_instances # 過濾低置信度框可視化時只留下0.3以上的 keep pred_instances.scores 0.3 pred_instances pred_instances[keep] # 調(diào)用mmdet內(nèi)置可視化器的draw方法這里傳入樣本會繪制gt和pred visualizer DetLocalVisualizer() visualizer.dataset_meta {classes: (cat, dog)} visualizer.add_datasample( result, image, sample, draw_gtTrue, draw_predTrue, showFalse, wait_time0, out_fileos.path.join(save_root, os.path.basename(img_path)))這個腳本里有兩個關鍵地方。第一個sample.pred_instances是一個InstanceData對象支持布爾索引scores 0.3直接返回InstanceData的切片非常方便想過濾哪個字段都行。第二個visualizer.add_datasample接口負責真正畫圖draw_gtTrue時會把標注框也畫出來out_file指定輸出路徑不指定就會直接彈窗顯示在服務器上運行沒有GUI的話就等著報錯吧所以記得一定要設out_file。你可能會問手動畫圖為什么不用OpenCV畫框因為MMDetection的DetLocalVisualizer已經(jīng)實現(xiàn)了類別顏色管理、置信度文本、圖例等復雜功能自己用OpenCV從零畫代碼量至少翻三倍而且邊界框粗細、字體大小這些細節(jié)調(diào)試起來也費勁。除非你要做極度定制化的效果比如視頻流實時預覽、在非標準圖像格式上繪制否則不建議重復造輪子。4.3 視頻與多圖對比的可視化思路如果你測試的對象是視頻逐幀保存成圖片再合成視頻是最蠢但最穩(wěn)定的做法。效率高一點的方法是直接改造測試腳本的推理循環(huán)把每一幀的預測結果傳給視頻寫入器。MMDetection提供了inference_detector接口可以逐幀推理配合OpenCV的VideoWriter就能把預測框實時畫到視頻幀上并輸出成MP4。下面是用inference_detector做單張圖片推理的極簡示例from mmdet.apis import init_detector, inference_detector import mmcv config_file configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py checkpoint_file work_dirs/epoch_12.pth model init_detector(config_file, checkpoint_file, devicecuda:0) img test.jpg result inference_detector(model, img) # result是DetDataSample可以直接可視化或檢查框這個接口對工程集成特別有用比如接到攝像頭實時流、嵌入到Flask服務里做API推理都可以基于它來擴展。多圖對比分析時把同一張圖在不同模型配置下的預測結果拼成一張畫布左半部分是模型A的框右半部分是模型B的框能直觀看出哪個模型定位更準。我常用np.concatenate把多張可視化圖橫向拼接然后用一個標題欄標注每個子圖對應的配置名這樣對比效率極高。4.4 可視化結果如何指導調(diào)參講了這么多操作層面的東西落到最終用途上可視化結果到底怎么指導調(diào)參。這里我總結幾個高頻場景。第一如果預測框普遍偏大或偏小說明anchor size設置和數(shù)據(jù)集目標尺度不匹配。訓練前先用可視化腳本檢查數(shù)據(jù)集的標注框尺寸分布如果目標普遍較小而模型默認anchor是適合COCO的尺度就要在小尺度anchor上增密。第二如果同類目標距離極近導致漏檢或誤檢NMS的iou_threshold需要調(diào)低讓重復框更容易被抑制。第三如果預測框整體偏移比如所有框都往下偏大概率是訓練時數(shù)據(jù)標注有系統(tǒng)性誤差可視化能幫你一眼看出這種偏差。第四如果高置信度預測框經(jīng)常落在背景區(qū)域說明模型學到了紋理特征而非語義特征可能需要換更強的backbone或者增加上下文信息。這些調(diào)參結論如果不做可視化根本得不出來。所以我要強調(diào)這一條理念每跑一次測試至少抽看50張可視化結果圖然后再看指標。別看40張就說夠了因為錯檢和漏檢往往集中在長尾分布的那部分目標上看得越多樣品越容易碰到。5. 測試階段常用參數(shù)速查表與效率提示把測試環(huán)節(jié)涉及的常用參數(shù)和對應建議整理一張表方便你直接對照使用。其中有一些參數(shù)是從工程效率角度給出的經(jīng)驗值請結合自己的硬件條件合理調(diào)整。參數(shù)項常見取值建議與說明test_dataloader.batch_size1 ~ 8顯存不夠時優(yōu)先調(diào)小因為測試不走反向傳播Faster R-CNN系列2~4是穩(wěn)妥起點test_dataloader.num_workers4 ~ 12建議按CPU物理核數(shù)的一半設置設太高反而增加調(diào)度開銷test_evaluator.metricbbox / segm檢測任務用bbox實例分割任務用segmtest_cfg.det_threshold0.01 ~ 0.05評測時用低閾值保證召回率統(tǒng)計完整score_thr可視化0.3 ~ 0.5只在可視化或部署時使用評測時不用高閾值--show-dir自定義目錄只跑指標時不要設置避免無謂IO--out自定義.pkl路徑建議每次測試都保存方便后續(xù)自定義分析接著說說測試效率的問題。測試階段最耗時的點其實是數(shù)據(jù)加載和預處理GPU本身閑置率往往很高。有人覺得GPU顯存大干脆batch_size設成16猛干結果發(fā)現(xiàn)速度提升不是線性的瓶頸在CPU端數(shù)據(jù)預處理和IO。想提升測試吞吐優(yōu)先加num_workers再考慮批量大小。如果圖片分辨率很大預處理里的Resize會成為一個計算熱點測試時可以考慮用一個更小的img_scale比如(1000, 600)前提是你得明白這會降低小目標檢測精度必須做對比驗證后再確定。如果你的測試集是那種大而全的原始數(shù)據(jù)集幾萬張圖全跑一遍太耗時可以用--cfg-options臨時構造一個抽樣子集比如用tools/analysis_tools/analyze_logs.py的腳本或mmcv的抽樣工具隨機取500張做快速驗證。我在實際項目中經(jīng)常先跑500張驗證流程沒問題再全量跑能省下不少來回調(diào)試的時間。6. 測試可視化常見問題與排查技巧實錄6.1 預測框置信度全是0或者沒有預測輸出這個現(xiàn)象通常和test_cfg里的score_thr設置無關更可能是數(shù)據(jù)預處理出了問題。排查步驟從下往上走先看看測試圖片能否正常加載再檢查test_pipeline里的Resize是否把大圖縮得太狠導致目標在縮放后小于2像素最后檢查模型輸入的batch_inputs形狀是不是正常。我在自定義數(shù)據(jù)集上踩過這個坑原因是LoadAnnotations里的with_bbox在測試時依然為True而測試標注文件路徑不存在導致數(shù)據(jù)加載靜默失敗預測結果自然為空。解決方法是確保測試集標注文件始終可用即使零標注也要提供一個空的JSON別讓數(shù)據(jù)加載報錯吞掉。6.2 可視化結果里框和原圖對不上位置這是最常見也最容易讓人抓狂的坑??虍嫵鰜砗臀矬w位置錯位幾像素或幾十像素通常不是模型問題而是繪制時沒有用原圖坐標。MMDetection在推理時會把圖片縮放或加padding預測框坐標是基于縮放后的圖算的。如果你直接從pred_instances.bboxes里取值然后畫到原圖上框就會偏移。正確做法是乘回scale_factor或者用DetLocalVisualizer的add_datasample接口它會自動處理坐標還原。我建議在配置PackDetInputs時保留ori_shape和scale_factor元信息這樣任何時候想手動繪圖都有足夠信息做反變換。如果你在用inference_detector接口result里自帶這些元信息直接用visualizer渲染就行不需要手動換算。6.3 尺寸不匹配單張測試沒問題但batch測試崩潰這個問題大多是test_pipeline沒有設置統(tǒng)一的Resize尺度或者keep_ratioTrue導致batch內(nèi)圖片尺寸不一致觸碰了batch維度校驗的限制。MMDetection 3.x對batch內(nèi)張量尺寸一致性要求很嚴格如果尺寸不一致會報invalid argument或size mismatch錯誤。解決方法是確保所有測試圖片最終縮放到完全相同的尺寸比如固定(1333, 800)并且設置keep_ratioTrue這樣batch內(nèi)尺寸仍然可能不一致所以更好的做法是用統(tǒng)一的scale但這樣會犧牲原始比例信息。實際中一般不會對測試集做嚴格統(tǒng)一因為MMDetection的分組采樣器會盡量把尺寸接近的圖片分到同一個batch但如果你自己改了數(shù)據(jù)加載方式就要特別小心這個問題。6.4 顯存不足OOM怎么辦測試階段OOM可能出現(xiàn)在兩個地方。第一個是test_dataloader的batch_size設置太大FP16加速也沒開很容易爆顯存。第二個是高分辨率圖片做全圖推理時特征圖占用過大。常見解決辦法有四種把batch_size調(diào)成1使用--cfg-options model.data_preprocessor.batch_augmentsNone關閉一些數(shù)據(jù)增強相關操作如果配置里有嘗試開啟--amp混合精度推理或者給大的測試圖做TTATest-Time Augmention之前先切圖避免一次性把整張大圖塞進GPU。顯存優(yōu)化是一個越早做收益越大的事。建議測試之前先用nvidia-smi看看GPU顯存剩余量粗略估算一下當前模型大小x batch_size的顯存需求。如果還不夠用torch.cuda.max_memory_allocated()峰值統(tǒng)計接口判斷瓶頸是在backbone還是在檢測頭后處理上。6.5 可視化結果過多或過少可視化圖太多時篩選的策略很關鍵。只保存置信度最高的前K個檢測這是一個辦法按類別過濾只看你關心的類別這樣更精準。漏檢占比高的圖是最有價值的單獨抽出來分析誤檢多的圖也有參考意義。我的建議是把可視化結果按預測框數(shù)量排序多框的、零框的、高置信度錯檢的分別歸類存放這樣分析效率會高很多。如果你介意人工一個個翻圖還可以寫腳本統(tǒng)計每張圖的錯檢率只把錯檢率高于某個閾值的圖保存下來減少人工工作量。6.6 測試結果與訓練時的驗證集結果不一致有朋友遇到過這樣的怪事訓練日志里每個epoch的驗證mAP有0.5但單獨用tools/test.py跑出來的結果只有0.4。這個問題的根源通常是兩個評估流程的數(shù)據(jù)處理不完全一致。一種可能是訓練過程里的驗證階段用了val_pipeline而tools/test.py用的是test_pipeline兩者如果配置不同比如Resize尺度、是否帶TTA指標自然會不一樣。另一種可能是測試時使用了不同的權重文件最常見的是best_coco_bbox_mAP_epoch和latest的混淆——前者保存的是驗證集上指標最好的權重后者是隨機初始化的權重如果你用的是--auto-resume之類還有可能加載到不完整權重。解決的關鍵是每次測試都把配置和權重路徑記錄下來尤其是用bash腳本批量跑測試時別搞混。7. 將測試與可視化嵌入日常開發(fā)流的建議很多同學把測試和可視化當作一個階段性的動作訓完了跑一次就完事。但我更建議把它做成一個可重復的日常流程。每次調(diào)整數(shù)據(jù)增強、修改模型結構、更換訓練策略之后都跑一次小規(guī)模測試和可視化與前一個版本對比。這個迭代回路看起來增加了工作量實際能幫你盡早發(fā)現(xiàn)問題。具體怎么嵌進日常工作我的習慣是寫一個驗證腳本輸入是配置文件路徑和權重路徑輸出是一份自動生成的對比報告包含mAP、各類別AP、PR曲線以及抽樣可視化圖。這樣只要跑一條命令就能拿到全部信息不需要每次手動進終端敲一串工具命令再打開目錄找圖。sh scripts/validate_and_vis.sh \ configs/my_faster_rcnn.py \ work_dirs/best.pth \ work_dirs/exp_compare腳本內(nèi)部邏輯不算復雜調(diào)用tools/test.py跑指標和結果pkl再用一段Python腳本讀取pkl抽50張圖做可視化最后用pandas匯總指標并畫柱狀圖。整個過程跑完大概需要幾分鐘取決于測試集大小但省下來的“改配置-重新訓練-手工比較”時間往往是以天來計的。最后提醒一個容易被忽視的點可視化保存的圖片是給人類看的不是給模型看的。你在調(diào)參時看可視化結果也要帶上業(yè)務視角。比如做工業(yè)質檢漏檢比誤檢嚴重得多那看到低置信度漏檢的圖應該優(yōu)先考慮降低置信度閾值而不是調(diào)整NMS做安防巡檢誤檢率太高會煩死值班人員那就要想辦法提高正樣本質量、增加難負樣本挖掘。同一張可視化圖在不同業(yè)務目標下得出的調(diào)參方向可能是相反的。8. 結尾再聊兩句個人心得做檢測項目幾年下來我最大的感受是模型訓練只是“煉丹”測試和可視化才是“驗丹”。很多人煉丹煉得很投入驗丹卻馬虎得很只看一個mAP就交差。但真正把系統(tǒng)推到實際場景里最容易暴露問題的恰恰是那些可視化里看起來“不夠自然”的預測結果——一個高置信度的錯誤框、一個被漏檢的小目標、一條偏離的邊界這些才是模型能力邊界的真實投影。講到底測試可視化和指標評測是互補的指標告訴你“做到什么程度”可視化告訴你“為什么是這個程度”。兩者一起用模型在什么場景下能打、在什么場景下會翻車基本就心里有數(shù)了。最后分享一個小建議跑測試時與其等到訓完再看不如訓練到中途就經(jīng)常拿最新權重做小規(guī)模可視化抽查。批量訓練動輒幾十個小時中途發(fā)現(xiàn)模型存在系統(tǒng)性誤差比如類別混淆嚴重、或者目標邊界定位整體偏移早發(fā)現(xiàn)就能早停掉重訓或者調(diào)整方案比熬到最后一秒鐘看到結果失望要省錢省心得多。反正可視化的成本很低就是幾張圖的事但信息量往往比一個先進指標更大。這套“半路驗丹”的習慣我一直用到現(xiàn)在實戰(zhàn)里幫我在好幾次實驗中提前發(fā)現(xiàn)了一開始沒注意到的問題推薦你也試試。