MMDetection v2.22.0 實(shí)戰(zhàn):從零訓(xùn)練自定義目標(biāo)檢測(cè)模型
1. 項(xiàng)目概述從零上手MMDetection v2.22.0如果你剛拿到一批標(biāo)注好的圖片想用MMDetection這個(gè)強(qiáng)大的目標(biāo)檢測(cè)工具箱來(lái)訓(xùn)練自己的模型但面對(duì)官方文檔和繁雜的配置文件感到無(wú)從下手那你來(lái)對(duì)地方了。我最近剛用MMDetection v2.22.0完整跑通了一個(gè)自定義數(shù)據(jù)集的訓(xùn)練流程從環(huán)境搭建、數(shù)據(jù)準(zhǔn)備、配置修改到模型訓(xùn)練和測(cè)試中間踩了不少坑也總結(jié)了一套行之有效的“流水線”操作。這篇文章就是我的實(shí)戰(zhàn)筆記目標(biāo)很明確讓你能避開(kāi)我走過(guò)的彎路用最清晰的步驟在MMDetection v2.22.0上成功訓(xùn)練出第一個(gè)屬于你自己的目標(biāo)檢測(cè)模型。無(wú)論你是做學(xué)術(shù)研究、工業(yè)質(zhì)檢還是個(gè)人興趣項(xiàng)目這套流程都能直接套用。我們會(huì)聚焦于最常用的Faster R-CNN模型和COCO數(shù)據(jù)格式因?yàn)檫@是最通用、社區(qū)支持最好的路徑掌握了它再探索其他模型和格式就會(huì)容易得多。2. 環(huán)境搭建與MMDetection安裝2.1 基礎(chǔ)環(huán)境準(zhǔn)備CUDA、PyTorch與MMCVMMDetection的穩(wěn)定運(yùn)行嚴(yán)重依賴底層環(huán)境尤其是PyTorch和MMCVOpenMMLab的計(jì)算機(jī)視覺(jué)基礎(chǔ)庫(kù)的版本匹配。v2.22.0版本發(fā)布于一段時(shí)間其版本依賴相對(duì)固定盲目使用最新版PyTorch很可能導(dǎo)致兼容性問(wèn)題。我的建議是嚴(yán)格按照 MMDetection官方安裝文檔 中推薦的版本來(lái)。以我使用的環(huán)境為例操作系統(tǒng)Ubuntu 20.04 LTS 或 Windows 10/11WSL2環(huán)境下。純Windows原生安裝會(huì)遇到更多編譯問(wèn)題強(qiáng)烈推薦WSL2。CUDA Toolkit11.3。這是經(jīng)過(guò)廣泛測(cè)試的版本。確保nvidia-smi顯示的CUDA版本不低于此。PyTorch1.11.0。使用以下命令安裝pip install torch1.11.0cu113 torchvision0.12.0cu113 torchaudio0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113MMCV這是關(guān)鍵。MMDetection v2.22.0需要mmcv-full而非輕量版的mmcv。我們必須安裝與CUDA、PyTorch版本完全匹配的預(yù)編譯包。pip install mmcv-full1.5.3 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.11.0/index.html請(qǐng)將URL中的cu113和torch1.11.0替換成你的CUDA和PyTorch版本。安裝成功后在Python中運(yùn)行import mmcv; print(mmcv.__version__)應(yīng)能正確輸出版本號(hào)。注意切勿直接pip install mmcv-full這大概率會(huì)觸發(fā)從源碼編譯過(guò)程漫長(zhǎng)且極易失敗。一定要使用-f指定預(yù)編譯包的索引地址。2.2 MMDetection安裝與驗(yàn)證基礎(chǔ)環(huán)境就緒后安裝MMDetection本身反而很簡(jiǎn)單。推薦從GitHub克隆特定版本以保證代碼一致性。git clone -b v2.22.0 https://github.com/openmmlab/mmdetection.git cd mmdetection pip install -v -e . # “-e”代表可編輯模式安裝方便修改源碼 # 或者使用requirements文件安裝依賴 # pip install -r requirements/build.txt # pip install -r requirements/optional.txt安裝完成后進(jìn)行一個(gè)快速的完整性驗(yàn)證。創(chuàng)建一個(gè)簡(jiǎn)單的Python腳本test_install.pyfrom mmdet.apis import init_detector, inference_detector import mmcv config_file configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py checkpoint_file checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth # 下載預(yù)訓(xùn)練模型如果尚未下載 # from mmdet.apis import init_detector # 模型會(huì)在首次運(yùn)行時(shí)自動(dòng)下載也可以手動(dòng)下載到checkpoints目錄 model init_detector(config_file, checkpoint_file, devicecpu) # 先用CPU測(cè)試 print(MMDetection安裝及模型加載測(cè)試通過(guò))如果運(yùn)行沒(méi)有報(bào)錯(cuò)說(shuō)明核心安裝成功。接下來(lái)我們需要準(zhǔn)備最重要的燃料——你自己的數(shù)據(jù)集。3. 自定義數(shù)據(jù)集準(zhǔn)備COCO格式詳解與制作MMDetection支持多種數(shù)據(jù)集格式PASCAL VOC、COCO等但COCO格式是社區(qū)生態(tài)最完善、文檔示例最全的格式強(qiáng)烈建議將你的數(shù)據(jù)轉(zhuǎn)為COCO格式能省去大量適配工作。3.1 COCO數(shù)據(jù)集格式深度解析COCO格式的核心是一個(gè)JSON文件通常命名為annotations.json。它包含以下幾個(gè)頂級(jí)字段images: 一個(gè)列表包含所有圖像的信息。annotations: 一個(gè)列表包含所有目標(biāo)實(shí)例的標(biāo)注信息。categories: 一個(gè)列表定義所有物體類別。下面我們拆解每一個(gè)部分并說(shuō)明如何從你的原始標(biāo)注比如LabelImg生成的XML轉(zhuǎn)換過(guò)來(lái)。1.images字段每個(gè)圖像是一個(gè)字典例如{ id: 1, // 圖像唯一ID從1開(kāi)始遞增 width: 800, height: 600, file_name: image_001.jpg // 相對(duì)于數(shù)據(jù)集根目錄的路徑 }你需要遍歷你的所有圖片為每一張生成這樣一個(gè)記錄。id必須唯一且連續(xù)。2.categories字段定義你的檢測(cè)類別。id通常從1開(kāi)始0保留給背景MMDetection內(nèi)部處理。[ {id: 1, name: cat, supercategory: animal}, {id: 2, name: dog, supercategory: animal}, {id: 3, name: person, supercategory: human} ]supercategory可以用于更粗粒度的分組非必需但建議填寫。3.annotations字段最關(guān)鍵每個(gè)目標(biāo)實(shí)例一個(gè)字典{ id: 1, // 標(biāo)注實(shí)例唯一ID全局遞增 image_id: 1, // 對(duì)應(yīng) images 中的 id category_id: 1, // 對(duì)應(yīng) categories 中的 id bbox: [x, y, width, height], // [左上角x, 左上角y, 寬度, 高度] area: width * height, // bbox面積用于評(píng)估指標(biāo)如AP segmentation: [], // 實(shí)例分割多邊形坐標(biāo)目標(biāo)檢測(cè)可留空列表 iscrowd: 0 // 0表示單個(gè)物體1表示一群物體如人群 }這里最重要的是bbox的格式。COCO使用的是[x, y, width, height]即左上角坐標(biāo)和寬高。這與某些標(biāo)注工具如YOLO使用的中心點(diǎn)坐標(biāo)和歸一化寬高不同轉(zhuǎn)換時(shí)務(wù)必注意。3.2 從常見(jiàn)格式轉(zhuǎn)換到COCO格式的實(shí)操腳本假設(shè)你的原始標(biāo)注是PASCAL VOC格式XML文件下面是一個(gè)使用Pythonxml.etree.ElementTree進(jìn)行轉(zhuǎn)換的示例腳本核心邏輯import json import os import xml.etree.ElementTree as ET from PIL import Image def voc_to_coco(voc_annotations_dir, images_dir, output_json_path): images [] annotations [] categories [] # 1. 構(gòu)建 categories # 這里需要你事先知道所有類別并映射到id category_dict {cat: 1, dog: 2, person: 3} for name, cid in category_dict.items(): categories.append({id: cid, name: name, supercategory: none}) ann_id 1 for img_id, xml_file in enumerate(os.listdir(voc_annotations_dir), 1): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(voc_annotations_dir, xml_file)) root tree.getroot() # 2. 構(gòu)建 image 信息 filename root.find(filename).text img_path os.path.join(images_dir, filename) with Image.open(img_path) as img: width, height img.size images.append({ id: img_id, width: width, height: height, file_name: filename, }) # 3. 構(gòu)建 annotation 信息 for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in category_dict: continue # 或者跳過(guò)未知類別 xml_box obj.find(bndbox) xmin int(float(xml_box.find(xmin).text)) ymin int(float(xml_box.find(ymin).text)) xmax int(float(xml_box.find(xmax).text)) ymax int(float(xml_box.find(ymax).text)) # VOC是[xmin, ymin, xmax, ymax]需轉(zhuǎn)為COCO的[x, y, width, height] coco_bbox [xmin, ymin, xmax - xmin, ymax - ymin] area coco_bbox[2] * coco_bbox[3] annotations.append({ id: ann_id, image_id: img_id, category_id: category_dict[cls_name], bbox: coco_bbox, area: area, segmentation: [], iscrowd: 0 }) ann_id 1 # 4. 組裝成COCO JSON coco_format_json { images: images, annotations: annotations, categories: categories } with open(output_json_path, w) as f: json.dump(coco_format_json, f, indent2) print(f轉(zhuǎn)換完成共 {len(images)} 張圖片{len(annotations)} 個(gè)標(biāo)注。) # 使用示例 voc_to_coco(./voc_annotations, ./images, ./annotations/train.json)運(yùn)行這個(gè)腳本你就能得到標(biāo)準(zhǔn)的COCO格式標(biāo)注文件。記得將圖片文件放在images_dir指定的目錄下。3.3 數(shù)據(jù)集目錄結(jié)構(gòu)規(guī)劃一個(gè)清晰的數(shù)據(jù)集目錄結(jié)構(gòu)能讓后續(xù)配置變得簡(jiǎn)單。我推薦如下結(jié)構(gòu)mmdetection/ ├── data/ │ └── my_dataset/ # 你的數(shù)據(jù)集根目錄 │ ├── annotations/ # 存放COCO格式的JSON文件 │ │ ├── train.json │ │ └── val.json │ └── images/ # 存放所有圖片或按train/val放子目錄 │ ├── train/ │ │ ├── img1.jpg │ │ └── ... │ └── val/ │ ├── img2.jpg │ └── ...實(shí)操心得在制作train.json和val.json時(shí)images列表和annotations列表只包含對(duì)應(yīng)劃分的數(shù)據(jù)。categories列表在兩個(gè)文件中必須完全一致。你可以先用一個(gè)腳本生成完整的all.json再根據(jù)劃分列表拆分成train.json和val.json。4. 配置文件解析與關(guān)鍵修改MMDetection采用模塊化、可繼承的配置文件系統(tǒng)這是其強(qiáng)大之處也是新手最容易困惑的地方。我們不需要從頭寫配置而是基于一個(gè)基準(zhǔn)配置文件進(jìn)行修改。4.1 配置文件繼承機(jī)制解讀以訓(xùn)練Faster R-CNN為例我們查看configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py會(huì)發(fā)現(xiàn)它的第一行是_base_ [ ../_base_/models/faster_rcnn_r50_fpn.py, ../_base_/datasets/coco_detection.py, ../_base_/schedules/schedule_1x.py, ../_base_/default_runtime.py ]這表示它繼承了四個(gè)基礎(chǔ)配置文件分別定義了模型結(jié)構(gòu)、數(shù)據(jù)流水線、訓(xùn)練策略和運(yùn)行時(shí)設(shè)置如日志、鉤子。我們的修改策略是創(chuàng)建一個(gè)新的配置文件繼承我們選中的基準(zhǔn)配置然后只覆蓋需要修改的部分。這樣做既保證了配置的完整性又使修改清晰可追溯。4.2 創(chuàng)建自定義配置文件在mmdetection/configs目錄下或任何你喜歡的位置建議在項(xiàng)目根目錄新建一個(gè)configs文件夾創(chuàng)建我們的配置文件例如my_faster_rcnn_r50_fpn_1x_mydataset.py。# my_faster_rcnn_r50_fpn_1x_mydataset.py _base_ ./faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py # 相對(duì)于當(dāng)前文件的路徑 # 1. 修改數(shù)據(jù)集相關(guān)配置 dataset_type CocoDataset classes (cat, dog, person) # 務(wù)必與你的 categories 中 name 的順序和內(nèi)容一致 data_root data/my_dataset/ # 指向你的數(shù)據(jù)集根目錄 # 覆蓋 _base_ 中關(guān)于數(shù)據(jù)集的配置 data dict( samples_per_gpu2, # 批大小。根據(jù)你的GPU內(nèi)存調(diào)整。如果遇到CUDA out of memory就調(diào)小這個(gè)值。 workers_per_gpu2, # 數(shù)據(jù)加載線程數(shù)。通常設(shè)為CPU核心數(shù)但不宜過(guò)大。 traindict( typedataset_type, ann_filedata_root annotations/train.json, img_prefixdata_root images/train/, classesclasses # 指定類別 ), valdict( typedataset_type, ann_filedata_root annotations/val.json, img_prefixdata_root images/val/, classesclasses ), testdict( typedataset_type, ann_filedata_root annotations/val.json, # 測(cè)試集可以用驗(yàn)證集代替 img_prefixdata_root images/val/, classesclasses ) ) # 2. 修改模型頭部類別數(shù) # 找到 _base_ 中模型定義的路徑然后修改 roi_head 的 bbox_head model dict( roi_headdict( bbox_headdict( num_classeslen(classes) # 關(guān)鍵必須修改為你的類別數(shù)這里是3 ) ) ) # 3. 修改訓(xùn)練策略可選但建議調(diào)整 # 學(xué)習(xí)率根據(jù) batch size 線性縮放是一個(gè)經(jīng)驗(yàn)法則。原配置 base_lr0.02 對(duì)應(yīng) 8 GPUs * 2 imgs/gpu 16 的總batch size。 # 如果你用單卡samples_per_gpu2總batch size2那么學(xué)習(xí)率應(yīng)縮放為 0.02 * (2 / 16) 0.0025 optimizer dict(typeSGD, lr0.0025, momentum0.9, weight_decay0.0001) lr_config dict( policystep, warmuplinear, warmup_iters500, warmup_ratio0.001, step[8, 11]) # 學(xué)習(xí)率在第8和第11個(gè)epoch下降 runner dict(typeEpochBasedRunner, max_epochs12) # 總訓(xùn)練輪數(shù) # 4. 修改運(yùn)行時(shí)配置如日志、檢查點(diǎn)頻率 checkpoint_config dict(interval1) # 每個(gè)epoch保存一次檢查點(diǎn) log_config dict(interval50, hooks[dict(typeTextLoggerHook)]) # 每50個(gè)iteration打印一次日志 # 指定工作目錄訓(xùn)練日志和模型權(quán)重將保存在這里 work_dir ./work_dirs/my_faster_rcnn_exp1這個(gè)配置文件是核心中的核心。請(qǐng)逐行理解特別是num_classes和lr的修改這是新手最常出錯(cuò)的兩個(gè)地方。num_classes不修改會(huì)導(dǎo)致維度不匹配錯(cuò)誤lr設(shè)置不當(dāng)會(huì)導(dǎo)致訓(xùn)練不收斂。4.3 配置文件的調(diào)試與驗(yàn)證在開(kāi)始漫長(zhǎng)訓(xùn)練之前先用一個(gè)極小的設(shè)置驗(yàn)證整個(gè)數(shù)據(jù)流和配置是否正確。我們可以創(chuàng)建一個(gè)“玩具”配置文件只加載幾張圖片跑通前向傳播。# debug_config.py _base_ ./my_faster_rcnn_r50_fpn_1x_mydataset.py # 覆蓋數(shù)據(jù)加載部分僅用于調(diào)試 data dict( samples_per_gpu1, workers_per_gpu1, traindict( type_base_.dataset_type, ann_file_base_.data_root annotations/train.json, img_prefix_base_.data_root images/train/, classes_base_.classes, # 使用更小的流水線加速調(diào)試 pipeline[ dict(typeLoadImageFromFile), dict(typeLoadAnnotations, with_bboxTrue), dict(typeResize, img_scale(1333, 800), keep_ratioTrue), dict(typeRandomFlip, flip_ratio0.5), dict(typeNormalize, **img_norm_cfg), dict(typePad, size_divisor32), dict(typeDefaultFormatBundle), dict(typeCollect, keys[img, gt_bboxes, gt_labels]), ] ) )然后運(yùn)行一個(gè)簡(jiǎn)單的測(cè)試腳本python tools/misc/browse_dataset.py debug_config.py --show這個(gè)命令會(huì)可視化你的數(shù)據(jù)加載和增強(qiáng)效果確保圖片和標(biāo)注能正確配對(duì)、顯示。這是排查數(shù)據(jù)問(wèn)題最直觀的方法。5. 模型訓(xùn)練、監(jiān)控與測(cè)試5.1 啟動(dòng)訓(xùn)練與分布式訓(xùn)練單GPU訓(xùn)練命令很簡(jiǎn)單python tools/train.py my_faster_rcnn_r50_fpn_1x_mydataset.py如果你有多張GPU可以使用分布式訓(xùn)練以大幅加速。MMDetection基于PyTorch的DistributedDataParallel(DDP) 封裝了分布式訓(xùn)練命令./tools/dist_train.sh my_faster_rcnn_r50_fpn_1x_mydataset.py 8 --work-dir ./work_dirs/my_exp這里的8代表使用8個(gè)GPU。dist_train.sh腳本會(huì)自動(dòng)處理進(jìn)程啟動(dòng)、端口分配等繁瑣細(xì)節(jié)。訓(xùn)練日志和模型權(quán)重會(huì)保存在--work-dir指定的目錄如果配置文件中已指定work_dir則以配置文件為準(zhǔn)。5.2 訓(xùn)練過(guò)程監(jiān)控與日志解讀訓(xùn)練開(kāi)始后控制臺(tái)會(huì)打印日志。你需要關(guān)注以下幾個(gè)關(guān)鍵信息Loss曲線loss_rpn_cls、loss_rpn_bbox、loss_cls、loss_bbox是Faster R-CNN的主要損失。在訓(xùn)練初期這些loss應(yīng)該呈現(xiàn)明顯的下降趨勢(shì)。如果loss劇烈震蕩或居高不下可能是學(xué)習(xí)率過(guò)高、數(shù)據(jù)有問(wèn)題或標(biāo)注錯(cuò)誤。學(xué)習(xí)率日志會(huì)顯示當(dāng)前的學(xué)習(xí)率。根據(jù)lr_config的設(shè)置你應(yīng)該能看到在指定epoch學(xué)習(xí)率按比例下降。內(nèi)存使用關(guān)注GPU內(nèi)存占用。如果接近上限可以嘗試減小samples_per_gpu或輸入圖片尺寸。更強(qiáng)大的監(jiān)控工具是TensorBoard。MMDetection默認(rèn)集成了TensorBoard日志。在訓(xùn)練命令后加上--tensorboard參數(shù)或者在配置文件中添加log_config dict( interval50, hooks[ dict(typeTextLoggerHook), dict(typeTensorboardLoggerHook) # 添加這行 ])訓(xùn)練后在work_dir下會(huì)生成tf_logs目錄使用tensorboard --logdir ./work_dirs/my_exp/tf_logs即可在瀏覽器中查看豐富的可視化圖表包括Loss曲線、學(xué)習(xí)率、驗(yàn)證集mAP等這對(duì)于分析訓(xùn)練狀態(tài)至關(guān)重要。5.3 模型測(cè)試與性能評(píng)估訓(xùn)練完成后我們使用驗(yàn)證集評(píng)估模型性能。使用以下命令# 單GPU測(cè)試 python tools/test.py my_faster_rcnn_r50_fpn_1x_mydataset.py ./work_dirs/my_exp/latest.pth --eval bbox # 多GPU測(cè)試 ./tools/dist_test.sh my_faster_rcnn_r50_fpn_1x_mydataset.py ./work_dirs/my_exp/latest.pth 8 --eval bbox--eval bbox指定評(píng)估邊界框檢測(cè)的指標(biāo)。MMDetection會(huì)計(jì)算COCO風(fēng)格的一系列指標(biāo)其中最重要的是AP (Average Precision): IoU閾值從0.5到0.95步長(zhǎng)0.05的平均精度。這是COCO的主要評(píng)價(jià)指標(biāo)記為AP或AP[.5:.95]。AP50: IoU閾值為0.5時(shí)的AP即PASCAL VOC的評(píng)價(jià)標(biāo)準(zhǔn)。AP75: IoU閾值為0.75時(shí)的AP。AP_s, AP_m, AP_l: 分別對(duì)應(yīng)小、中、大尺寸目標(biāo)的AP。一份合格的訓(xùn)練結(jié)果AP和AP50應(yīng)該達(dá)到一個(gè)合理的值取決于你的數(shù)據(jù)集難度和規(guī)模。如果AP_s遠(yuǎn)低于AP_l說(shuō)明模型對(duì)小目標(biāo)檢測(cè)不好可能需要調(diào)整FPN結(jié)構(gòu)、使用更小的anchor或增加小目標(biāo)的訓(xùn)練數(shù)據(jù)。5.4 模型推理與可視化訓(xùn)練出模型后我們當(dāng)然想看看它的實(shí)際檢測(cè)效果。MMDetection提供了簡(jiǎn)單的推理APIfrom mmdet.apis import init_detector, inference_detector, show_result_pyplot import mmcv # 指定配置文件和訓(xùn)練好的模型 config_file my_faster_rcnn_r50_fpn_1x_mydataset.py checkpoint_file ./work_dirs/my_exp/latest.pth # 初始化模型 model init_detector(config_file, checkpoint_file, devicecuda:0) # 對(duì)單張圖片進(jìn)行推理 img test.jpg # 或者 img mmcv.imread(test.jpg) result inference_detector(model, img) # 可視化結(jié)果 # show_result_pyplot函數(shù)會(huì)直接顯示圖片適合在Jupyter Notebook中使用 # show_result_pyplot(model, img, result, score_thr0.3) # score_thr是顯示分?jǐn)?shù)閾值 # 更常用的方式將結(jié)果繪制到圖片上并保存 vis_img model.show_result(img, result, score_thr0.3, showFalse) mmcv.imwrite(vis_img, result.jpg) print(檢測(cè)結(jié)果已保存至 result.jpg)你可以調(diào)整score_thr來(lái)過(guò)濾低置信度的檢測(cè)框這個(gè)值需要根據(jù)你的具體應(yīng)用場(chǎng)景來(lái)權(quán)衡召回率和精度。6. 實(shí)戰(zhàn)避坑指南與高級(jí)技巧6.1 常見(jiàn)錯(cuò)誤與解決方案KeyError: ‘xxx’ is not in the fields或AssertionError: Thenum_classes(xx) shared by all branches must be the same問(wèn)題這是最經(jīng)典的錯(cuò)誤。根本原因是模型的num_classes沒(méi)有修改或者修改得不徹底。Faster R-CNN的num_classes需要同時(shí)在roi_head.bbox_head和rpn_head如果RPN也有分類頭的話新版通常不需要中修改。最穩(wěn)妥的方法是像我們之前那樣在配置文件中通過(guò)model.dict()覆蓋。解決仔細(xì)檢查配置文件確保model.roi_head.bbox_head.num_classes已正確設(shè)置為你的類別數(shù)。使用print(model)打印模型結(jié)構(gòu)來(lái)確認(rèn)。CUDA out of memory (OOM)問(wèn)題GPU內(nèi)存不足。解決減小配置中的samples_per_gpu批大小。減小輸入圖片尺寸。在train_pipeline和test_pipeline中找到Resize操作將img_scale改小例如從(1333, 800)改為(800, 600)。使用梯度累積Gradient Accumulation。這需要在優(yōu)化器配置和train_cfg中設(shè)置對(duì)新手稍復(fù)雜但可以有效模擬大batch size訓(xùn)練。嘗試更輕量的模型如RetinaNet或FCOS。Loss為NaN或訓(xùn)練不收斂問(wèn)題學(xué)習(xí)率設(shè)置不當(dāng)、數(shù)據(jù)存在極端值如坐標(biāo)超出圖像范圍、標(biāo)注錯(cuò)誤。解決首要檢查數(shù)據(jù)使用browse_dataset.py腳本仔細(xì)檢查標(biāo)注框是否合理。確保bbox坐標(biāo)非負(fù)且不超過(guò)圖像寬高。調(diào)整學(xué)習(xí)率根據(jù)你的batch size按線性縮放規(guī)則調(diào)整lr。如果loss爆炸變成NaN大幅降低學(xué)習(xí)率如除以10再試。使用預(yù)訓(xùn)練權(quán)重確保你的配置中l(wèi)oad_from指向了在COCO上預(yù)訓(xùn)練的模型權(quán)重MMDetection會(huì)自動(dòng)下載或你需要手動(dòng)指定路徑。從隨機(jī)初始化開(kāi)始訓(xùn)練檢測(cè)器非常困難。驗(yàn)證集mAP為0或極低但訓(xùn)練loss正常下降問(wèn)題過(guò)擬合或者訓(xùn)練集和驗(yàn)證集分布差異極大。解決增加數(shù)據(jù)增強(qiáng)的多樣性如更多的隨機(jī)裁剪、顏色抖動(dòng)。檢查是否不小心在驗(yàn)證集上使用了訓(xùn)練時(shí)的數(shù)據(jù)增強(qiáng)如RandomFlip。驗(yàn)證集流水線應(yīng)該只有Resize,Normalize,Pad,DefaultFormatBundle等確定性操作。使用更小的模型或添加正則化如Dropout但檢測(cè)模型中不常用。確保訓(xùn)練輪數(shù)max_epochs沒(méi)有過(guò)多。6.2 性能調(diào)優(yōu)與進(jìn)階技巧數(shù)據(jù)增強(qiáng)策略調(diào)優(yōu)MMDetection的數(shù)據(jù)增強(qiáng)流水線pipeline非常靈活。對(duì)于小數(shù)據(jù)集增強(qiáng)是防止過(guò)擬合的關(guān)鍵。你可以在配置文件的train_pipeline中添加或調(diào)整增強(qiáng)操作例如train_pipeline [ dict(typeLoadImageFromFile), dict(typeLoadAnnotations, with_bboxTrue), dict(typeResize, img_scale[(1333, 800), (1600, 960)], multiscale_moderange, keep_ratioTrue), # 多尺度訓(xùn)練 dict(typeRandomFlip, flip_ratio0.5), dict(typeRandomCrop, crop_size(0.8, 0.8), crop_typerelative_range), # 隨機(jī)裁剪 dict(typePhotoMetricDistortion, # 光度失真 brightness_delta32, contrast_range(0.5, 1.5), saturation_range(0.5, 1.5), hue_delta18), dict(typeNormalize, **img_norm_cfg), dict(typePad, size_divisor32), dict(typeDefaultFormatBundle), dict(typeCollect, keys[img, gt_bboxes, gt_labels]), ]注意增強(qiáng)不是越多越好需要根據(jù)你的任務(wù)特性調(diào)整。工業(yè)質(zhì)檢可能不需要RandomFlip而自然場(chǎng)景目標(biāo)檢測(cè)則需要。學(xué)習(xí)率策略與優(yōu)化器選擇除了StepLR還可以嘗試CosineAnnealingLR余弦退火它通常能帶來(lái)更好的收斂效果和最終精度。將lr_config修改為lr_config dict( policyCosineAnnealing, warmuplinear, warmup_iters500, warmup_ratio0.001, min_lr_ratio1e-5 # 最小學(xué)習(xí)率 )對(duì)于優(yōu)化器SGD with momentum是檢測(cè)任務(wù)的主流但也可以嘗試AdamW尤其在小數(shù)據(jù)集或訓(xùn)練不穩(wěn)定時(shí)。模型微調(diào)與凍結(jié)骨干網(wǎng)絡(luò)如果你的數(shù)據(jù)集與預(yù)訓(xùn)練數(shù)據(jù)集如COCO差異很大或者數(shù)據(jù)量很小可以考慮凍結(jié)骨干網(wǎng)絡(luò)Backbone的前幾層只訓(xùn)練后面的網(wǎng)絡(luò)層以防止過(guò)擬合和加速訓(xùn)練。# 在配置文件中修改 model dict( backbonedict( frozen_stages2, # 凍結(jié)前2個(gè)stageResNet有4個(gè)stage norm_cfgdict(typeBN, requires_gradFalse), # 凍結(jié)BN層的統(tǒng)計(jì)量 norm_evalTrue), ... )訓(xùn)練初期驗(yàn)證集指標(biāo)提升很快但后續(xù)可能遇到瓶頸此時(shí)可以解凍部分層繼續(xù)訓(xùn)練。6.3 部署與落地考量訓(xùn)練出一個(gè)指標(biāo)不錯(cuò)的模型只是第一步要真正用起來(lái)還需要考慮部署。模型轉(zhuǎn)換MMDetection模型通常需要轉(zhuǎn)換為其他格式以便部署。常用的有ONNX: 使用tools/deployment/pytorch2onnx.py腳本轉(zhuǎn)換可以獲得一個(gè)跨平臺(tái)的中間表示。TorchScript: 使用PyTorch自帶的torch.jit.trace或torch.jit.script進(jìn)行轉(zhuǎn)換適合在PyTorch生態(tài)內(nèi)部署。TensorRT (for NVIDIA GPUs): 通過(guò)ONNX中轉(zhuǎn)或直接使用MMDeploy等工具鏈可以極大提升推理速度。速度與精度權(quán)衡在配置文件中選擇不同的Backbone如將r50換成r18或mobilenetv2和Neck如修改FPN的通道數(shù)可以顯著影響模型速度和精度。MMDetection的Model Zoo提供了大量預(yù)訓(xùn)練模型及其性能指標(biāo)可以作為選型參考。構(gòu)建簡(jiǎn)易推理服務(wù)對(duì)于原型驗(yàn)證可以快速搭建一個(gè)基于Flask或FastAPI的Web服務(wù)將上面提到的推理代碼封裝成API方便其他系統(tǒng)調(diào)用。走到這一步你已經(jīng)完成了從數(shù)據(jù)準(zhǔn)備到模型訓(xùn)練、評(píng)估和初步部署的完整閉環(huán)。MMDetection的功能遠(yuǎn)不止于此它支持?jǐn)?shù)十種檢測(cè)算法、實(shí)例分割、全景分割等高級(jí)任務(wù)。但掌握這套基于Faster R-CNN和COCO格式的標(biāo)準(zhǔn)流程就像掌握了打開(kāi)寶庫(kù)的鑰匙你可以自信地去探索更復(fù)雜的模型和任務(wù)了。記住遇到問(wèn)題多查官方文檔和GitHub Issues社區(qū)里很可能已經(jīng)有現(xiàn)成的解決方案。

相關(guān)新聞

構(gòu)建專屬GPT-3 API代理:從架構(gòu)設(shè)計(jì)到RAG集成的完整實(shí)踐

構(gòu)建專屬GPT-3 API代理:從架構(gòu)設(shè)計(jì)到RAG集成的完整實(shí)踐

1. 項(xiàng)目概述:為什么你需要一個(gè)專屬的GPT-3 API如果你正在開(kāi)發(fā)一個(gè)需要智能對(duì)話、內(nèi)容生成或者復(fù)雜文本理解功能的應(yīng)用,直接調(diào)用OpenAI的官方API可能是你腦海中的第一個(gè)念頭。這確實(shí)方便,但當(dāng)你深入項(xiàng)目,尤其是涉及到數(shù)據(jù)隱私、成本…

2026/7/29 6:36:07 閱讀更多
ESP32 GPIO中斷編程實(shí)戰(zhàn):從輪詢到事件驅(qū)動(dòng)的實(shí)時(shí)響應(yīng)優(yōu)化

ESP32 GPIO中斷編程實(shí)戰(zhàn):從輪詢到事件驅(qū)動(dòng)的實(shí)時(shí)響應(yīng)優(yōu)化

1. 項(xiàng)目概述:從輪詢到中斷,ESP32 GPIO的進(jìn)階之路玩過(guò)ESP32的朋友,對(duì)digitalWrite和digitalRead這兩個(gè)函數(shù)肯定不陌生。點(diǎn)個(gè)燈、讀個(gè)按鍵狀態(tài),用它們輪詢一下,簡(jiǎn)單直接。但當(dāng)你開(kāi)始做更復(fù)雜的項(xiàng)目,比如做一個(gè)…

2026/7/29 6:36:07 閱讀更多
UrbanGS:數(shù)據(jù)驅(qū)動(dòng)的城市綠地規(guī)劃與管理系統(tǒng)

UrbanGS:數(shù)據(jù)驅(qū)動(dòng)的城市綠地規(guī)劃與管理系統(tǒng)

1. UrbanGS項(xiàng)目概述UrbanGS(Urban Green Space)是一個(gè)專注于城市綠地空間規(guī)劃與管理的創(chuàng)新項(xiàng)目。作為一名在城市規(guī)劃領(lǐng)域深耕多年的從業(yè)者,我見(jiàn)證了太多"鋼筋水泥森林"對(duì)居民生活質(zhì)量的負(fù)面影響。這個(gè)項(xiàng)目的核心目標(biāo)是通過(guò)數(shù)據(jù)驅(qū)動(dòng)…

2026/7/29 6:36:07 閱讀更多
麥昆STEAM教育機(jī)器人:從硬件解析到編程進(jìn)階的完整學(xué)習(xí)路徑

麥昆STEAM教育機(jī)器人:從硬件解析到編程進(jìn)階的完整學(xué)習(xí)路徑

1. 從“玩具”到“伙伴”:麥昆STEAM成長(zhǎng)記的緣起如果你是一位關(guān)注青少年科技教育或創(chuàng)客文化的家長(zhǎng)、老師,或者你本身就是個(gè)對(duì)機(jī)器人、編程充滿好奇的大朋友,那么“麥昆”這個(gè)名字你大概率不會(huì)陌生。它可能不是那個(gè)動(dòng)畫片里的賽車,…

2026/7/29 7:36:08 閱讀更多
Intel Edison開(kāi)發(fā)板WiFi連接全攻略:從connmanctl配置到物聯(lián)網(wǎng)應(yīng)用實(shí)戰(zhàn)

Intel Edison開(kāi)發(fā)板WiFi連接全攻略:從connmanctl配置到物聯(lián)網(wǎng)應(yīng)用實(shí)戰(zhàn)

1. 項(xiàng)目概述:為什么需要連接WiFi?如果你手頭有一塊Intel Edison開(kāi)發(fā)板,并且已經(jīng)用它點(diǎn)亮過(guò)LED,或者跑通了基礎(chǔ)的“Hello World”,那么下一步,你大概率會(huì)想讓它“上網(wǎng)”。讓Edison連接上WiFi,是把…

2026/7/29 7:36:08 閱讀更多
物聯(lián)網(wǎng)設(shè)備安全芯片選型與SE050+PIC18F45K22方案解析

物聯(lián)網(wǎng)設(shè)備安全芯片選型與SE050+PIC18F45K22方案解析

1. 為什么物聯(lián)網(wǎng)設(shè)備需要專用安全芯片?在智能家居和工業(yè)物聯(lián)網(wǎng)項(xiàng)目中,開(kāi)發(fā)者常面臨一個(gè)兩難選擇:使用通用MCU實(shí)現(xiàn)基礎(chǔ)功能雖成本低廉,但安全防護(hù)薄弱;而采用高端安全方案又會(huì)導(dǎo)致BOM成本飆升。這正是SE050 Plug&Tr…

2026/7/29 7:36:08 閱讀更多
量子計(jì)算VQE算法解析與TFIM模型應(yīng)用實(shí)踐

量子計(jì)算VQE算法解析與TFIM模型應(yīng)用實(shí)踐

1. 量子計(jì)算時(shí)代的變分算法革命當(dāng)我在IBM量子體驗(yàn)平臺(tái)上第一次運(yùn)行VQE算法時(shí),那個(gè)瞬間讓我想起了早期經(jīng)典計(jì)算機(jī)編程的歲月。變分量子本征求解器(Variational Quantum Eigensolver, VQE)作為當(dāng)前NISQ(含噪聲中等規(guī)模量子)時(shí)代最具實(shí)用價(jià)值的量子-經(jīng)典混合算法&#…

2026/7/29 7:36:08 閱讀更多
LaTeX插圖全攻略:從浮動(dòng)體原理到多圖排版實(shí)戰(zhàn)

LaTeX插圖全攻略:從浮動(dòng)體原理到多圖排版實(shí)戰(zhàn)

1. 項(xiàng)目概述:為什么LaTeX插圖是個(gè)“技術(shù)活”?在學(xué)術(shù)寫作、技術(shù)報(bào)告乃至?xí)虐骖I(lǐng)域,LaTeX以其卓越的排版質(zhì)量和穩(wěn)定性,一直是專業(yè)人士的首選工具。然而,對(duì)于許多初次接觸或日常使用頻率不高的朋友來(lái)說(shuō),“在…

2026/7/29 7:36:08 閱讀更多
Arduino環(huán)境光傳感器選型指南:從光敏電阻到數(shù)字芯片的進(jìn)階之路

Arduino環(huán)境光傳感器選型指南:從光敏電阻到數(shù)字芯片的進(jìn)階之路

1. 項(xiàng)目概述:為什么需要一份Arduino環(huán)境光傳感器選型指南?如果你玩過(guò)Arduino,大概率遇到過(guò)這樣的場(chǎng)景:想做一個(gè)能根據(jù)環(huán)境亮度自動(dòng)開(kāi)關(guān)的智能燈,或者一個(gè)能隨光線變化調(diào)整屏幕亮度的裝置。第一個(gè)蹦進(jìn)你腦海的組件可能就…

2026/7/29 7:26:08 閱讀更多
面試官大笑:“一個(gè)任務(wù)拆給 5 個(gè) Subagent 并行跑,不比 1 個(gè)快 5 倍?“我搖頭:“快不了,還可能更慢“

面試官大笑:“一個(gè)任務(wù)拆給 5 個(gè) Subagent 并行跑,不比 1 個(gè)快 5 倍?“我搖頭:“快不了,還可能更慢“

前兩個(gè)月,我在重構(gòu) AlgoMooc 網(wǎng)站過(guò)程中,發(fā)現(xiàn)一個(gè)問(wèn)題:在 Claude Code 里把一個(gè)任務(wù)拆給 5 個(gè) Subagent 并行跑,結(jié)果可能比 1 個(gè) agent 從頭干到尾還慢? 大多數(shù)人的第一反應(yīng)是反過(guò)來(lái)的:活是并行干的&#…

2026/7/29 0:15:24 閱讀更多
# 鴻蒙 HarmonyOS 應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號(hào)與動(dòng)畫渲染精講

# 鴻蒙 HarmonyOS 應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號(hào)與動(dòng)畫渲染精講

一、應(yīng)用概述 骰子(Dice Roller) 是一款經(jīng)典的休閑娛樂(lè)應(yīng)用,模擬了真實(shí)擲骰子的過(guò)程。應(yīng)用投擲兩個(gè)骰子(六面標(biāo)準(zhǔn)骰),使用 Unicode 骰面符號(hào)直觀展示每個(gè)骰子的點(diǎn)數(shù),并伴有快速滾動(dòng)的動(dòng)畫效果?!?/p>

2026/7/29 0:15:24 閱讀更多