日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MMDetectionV2 + Colab

發布時間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MMDetectionV2 + Colab 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MMDetectionV2 + Colab 超詳細教程及踩坑實錄

文章目錄

    • 前言
    • 一、環境配置
    • 二、準備自己的數據集
      • Aug.14更新
    • 三:修改config文件
      • 3.1 文件結構
      • 3.2 (本地)修改config文件
        • 3.2.1 (本地)構造自己模型的權重文件
        • 3.2.2 (本地)修改配置文件
      • 3.3 在colab上修改config
      • 3.5 在線訓練
      • 3.6 在線可視化模型效果
      • 3.7 在線inference
      • 4. 延伸思考
      • 5. 總結

前言

為了參加訊飛的X光目標檢測競賽,我們組研究了目前通用的幾種框架。包括Detectron2, Maskrcnn Benchmark和mmdetectionV2,最后決定采用MMDetectonV2,因為他有以下的幾個特性:

  • 相比較來說非常豐富的模型庫可供選擇。基礎模型包括:
  • Faster rcnn
  • Mask rcnn
  • Rpn rcnn
  • Cascade mask rcnn
  • Cascade rcnn
  • Retinanet (據說精度差不多的情況下,inference速度最快,可以以后再多了解一下。
  • 較多參考資料
  • 安全的License,Apache License 2.0

先說明下,為什么我要這么執著的使用Colab:

  • Colab Pro訂閱能夠提供一般學生無法獲得的算力資源:P100, 16g內存,$9.9/month簡直在做慈善。
  • 服務器在國外,免除網速煩惱。所有模型,包都是秒下秒裝。雖然每個session重啟都要重新裝包,不過有這個速度完全不用擔心花費過多時間。
  • 小白能專注上手跑模型,調參本身。配置環境的痛苦,想想你們學者最開始裝Docker、Anaconda等工具的時候,一不小心環境全亂了,電腦都打不開,幾個小時一事無成的感覺,懂得都懂。
  • However, 為了獲得以上的好處,我嘗試在mmdetection官網提供的tutorial 中更改,結果一言難盡。同時,目前絕大多數的mmdetection的筆記都是基于1.x版本,而且幾乎沒有在Colab環境的配置教程?;舅心懿鹊目游胰坎攘藗€遍,為了紀念一下也為了給其他的目標檢測學習者提供一下參考,就有了這篇筆記。
    在主體上我將采用colab tutorial的框架來介紹,但是仍然強烈建議在本地安裝配置好mmdetectionV2,能省下大把力氣。

    一、環境配置

    # Check nvcc version !nvcc -V # Check GCC version !gcc --version

    編寫時間:2020.8.11,colab預設為pytorch1.6.0 Cuda 10.1 gcc 7.5.0

    # install dependencies: (use cu101 because colab has CUDA 10.1) # 目前mmdetection只支持pytorch1.5.1及以下版本,使用1.6版本會報各種錯。 !pip install -U torch==1.5.1+cu101 torchvision==0.6.1+cu101 -f https://download.pytorch.org/whl/torch_stable.html # !pip install -U torch==1.6+cu101 torchvision==0.7.0+cu101 -f https://download.pytorch.org/whl/torch_stable.html# install mmcv-full thus we could use CUDA operators,此步需要花費大量時間,be patient !pip install mmcv-full # 在2020二月份pycocotools api有更新,而colab沒有配置最新的包,需要在這里重新安裝,看情況需不需要重啟runtime # install albumentations !pip install -U git+https://github.com/albu/albumentations --no-cache-dir !pip install "git+https://github.com/open-mmlab/cocoapi.git#subdirectory=pycocotools"# Install mmdetection !rm -rf mmdetection !git clone https://github.com/open-mmlab/mmdetection.git %cd mmdetection!pip install -e .# install Pillow 7.0.0 back in order to avoid bug in colab !pip install Pillow==7.0.0 # Check Pytorch installation import torch, torchvisionprint(torch.__version__, torch.cuda.is_available())# Check MMDetection installation import mmdetprint(mmdet.__version__)# Check mmcv installation from mmcv.ops import get_compiling_cuda_version, get_compiler_versionprint(get_compiling_cuda_version()) print(get_compiler_version())

    Output:
    1.5.1+cu101
    True 2.3.0
    10.1
    GCC 7.5

    掛載在自己的drive上:

    from google.colab import drivedrive.mount('/content/drive')

    在colab上,使用%cd或os.chdir(’…’)來切換工作目錄

    import os os.chdir('../content/drive/My Drive/mmdetection') !pwd !ls

    output:
    /content/drive/My Drive/mmdetection/mmdetection
    configs docs mmdet.egg-info requirements setup.cfg tools
    demo LICENSE pytest.ini requirements.txt setup.py
    docker mmdet README.md resources tests

    二、準備自己的數據集

    這是非常重要的一步,請務必按照以下的Tree準備自己的數據集,能給自己省下大量的麻煩。

    mmdetection ├── mmdet ├── tools ├── configs ├── data │ ├── coco │ │ ├── annotations │ │ ├── train2017 │ │ ├── val2017 │ │ ├── test2017 │ ├── cityscapes │ │ ├── annotations │ │ ├── leftImg8bit │ │ │ ├── train │ │ │ ├── val │ │ ├── gtFine │ │ │ ├── train │ │ │ ├── val │ ├── VOCdevkit │ │ ├── VOC2007 │ │ ├── VOC2012

    這次任務中,提供給我們的是voc格式的數據。第一步需要做轉化,voc2coco.ipynb.
    具體操作在這里不詳細展開,我將來會詳細寫一篇各數據集轉化到VOC,COCO數據集格式的文章。

    Aug.14更新

    本地做了mixup strategy數據增廣,具體實現見后續博客。
    每次做完本地的數據增廣后,需要轉化成COCO再重新上傳。因為COCO的格式需要所有注釋放在同一個json文件中,所以需要重新生成。

    三:修改config文件

    這里是我花了最多時間的地方,在tutorial中,官方是載入了一個config和它對應的模型,之后在colab即ipython 中用命令一行一行修改,這種方法在你非常明確MMDetectionV2的config結構和訓練方式的情況下,是有一定靈活性的。但是如果不了解config的搭建方法,這會讓你非常懵逼,多達一百多行的config命令實在非常難以輕松上手。這里我會介紹兩種方法,一種是在本地修改好config文件上傳,同時會介紹如何在colab cells中用命令修改。

    3.1 文件結構

    . ├── coco_exps ├── configs #configs主要修改的部分在這里,訓練config也是從這里繼承的 │ ├── albu_example │ ├── atss │ ├── _base_ #最根本的繼承 │ │ ├── datasets #存在著不同數據集的訓練方法,包含train_pipeline(augmentation), test_pipeline(TTA), data(batch_size, data root)等信息 │ │ ├── models #保存著基礎模型,需要在這里修改num_classes來適配自己的任務 │ │ └── schedules #保存著lr_schedule:1x, 2x, 20e,每x意味著12個epochs │ ├── carafe │ ├── cascade_rcnn │ ├── cityscapes │ ├── cornernet │ ├── dcn │ ├── deepfashion │ ├── detectors │ ├── double_heads │ ├── dynamic_rcnn │ ├── empirical_attention │ ├── faster_rcnn │ ├── fast_rcnn │ ├── fcos │ ├── foveabox │ ├── fp16 │ ├── free_anchor │ ├── fsaf │ ├── gcnet │ ├── gfl │ ├── ghm │ ├── gn │ ├── gn+ws │ ├── grid_rcnn │ ├── groie │ ├── guided_anchoring │ ├── hrnet │ ├── htc │ ├── instaboost │ ├── legacy_1.x │ ├── libra_rcnn │ ├── lvis │ ├── mask_rcnn │ ├── ms_rcnn │ ├── nas_fcos │ ├── nas_fpn │ ├── pafpn │ ├── pascal_voc │ ├── pisa │ ├── point_rend │ ├── regnet │ ├── reppoints │ ├── res2net │ ├── retinanet │ ├── rpn │ ├── scratch │ ├── ssd │ └── wider_face ├── data │ └── coco #把整理好的coco數據集放在這里 │ ├── annotations │ ├── test2017 │ ├── train2017 │ └── val2017 ├── mmdet #這里存放著mmdet的一些內部構件 │ ├── datasets #需要在這里的coco.py更改CLASSES,相當于Detectron2注冊數據集 │ │ ├── pipelines │ │ │ └── __pycache__ │ │ ├── __pycache__ │ │ └── samplers │ │ └── __pycache__ │ ├── core │ │ ├── evaluation #在這里修改evaluation相關的config。如在coco_classes中修改return的classes_names

    3.2 (本地)修改config文件

    這里非常建議在本地修改config文件再上傳到drive上,或者在colab提供的文件目錄中修改。如圖所示:

    因為colab使用的ipython shell,每個參數的修改都需要使用cfg的api去修改,很容易漏項或lose track,而且mmdetection V2有一個非常精密的inherit config系統,不用結構化的IDE修改實在有點可惜。最后一點,在后期inference testset的時候,必須從.py文件中讀取test_config,為什么不一勞永逸呢?

    3.2.1 (本地)構造自己模型的權重文件

    這里有爭議,我在線訓練并不需要修改權重,使用的預訓練.pth模型在num_classes不匹配時會提示,然后自動適配cascade_rcnn_r50_1x.py中的num_classes。
    不過修改后肯定不會錯。

    import torch pretrained_weights = torch.load('checkpoints/mask_rcnn_r50_fpn_1x_coco_20200205-d4b0c5d6.pth')num_class = 1 pretrained_weights['state_dict']['roi_head.bbox_head.fc_cls.weight'].resize_(num_class+1, 1024) pretrained_weights['state_dict']['roi_head.bbox_head.fc_cls.bias'].resize_(num_class+1) pretrained_weights['state_dict']['roi_head.bbox_head.fc_reg.weight'].resize_(num_class*4, 1024) pretrained_weights['state_dict']['roi_head.bbox_head.fc_reg.bias'].resize_(num_class*4)torch.save(pretrained_weights, "mask_rcnn_r50_fpn_1x_%d.pth"%num_class)

    其中num_class為你要訓練數據的類別數?(不用加1)?V2已經修改了,num_classes不再包含背景。

    3.2.2 (本地)修改配置文件

  • mmdet/coco.py
    在這里修改類別。
  • @DATASETS.register_module() class CocoDataset(CustomDataset):#CLASSES = ('person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',# 'train', 'truck', 'boat', 'traffic light', 'fire hydrant',# 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',# 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe',# 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',# 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat',# 'baseball glove', 'skateboard', 'surfboard', 'tennis racket',# 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl',# 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot',# 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',# 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop',# 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave',# 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock',# 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush')#在這里修改你所需要的CLASSESCLASSES =('knife, scissors, lighter, zippooil, pressure, slingshot, handcuffs, nailpolish, powerbank, firecrackers')
  • configs/_base_/datasets/coco_detection.py
    在train pipeline修改Data Augmentation在train
  • dataset_type = 'CocoDataset' data_root = 'data/coco/' img_norm_cfg = dict(mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) # 在這里加albumentation的aug albu_train_transforms = [dict(type='ShiftScaleRotate',shift_limit=0.0625,scale_limit=0.0,rotate_limit=0,interpolation=1,p=0.5),dict(type='RandomBrightnessContrast',brightness_limit=[0.1, 0.3],contrast_limit=[0.1, 0.3],p=0.2),dict(type='OneOf',transforms=[dict(type='RGBShift',r_shift_limit=10,g_shift_limit=10,b_shift_limit=10,p=1.0),dict(type='HueSaturationValue',hue_shift_limit=20,sat_shift_limit=30,val_shift_limit=20,p=1.0)],p=0.1),dict(type='JpegCompression', quality_lower=85, quality_upper=95, p=0.2),dict(type='ChannelShuffle', p=0.1),dict(type='OneOf',transforms=[dict(type='Blur', blur_limit=3, p=1.0),dict(type='MedianBlur', blur_limit=3, p=1.0)],p=0.1), ] train_pipeline = [dict(type='LoadImageFromFile'),dict(type='LoadAnnotations', with_bbox=True, with_mask=True),#據說這里改img_scale即可多尺度訓練,但是實際運行報錯。dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),dict(type='Pad', size_divisor=32),dict(type='Albu',transforms=albu_train_transforms,bbox_params=dict(type='BboxParams',format='pascal_voc',label_fields=['gt_labels'],min_visibility=0.0,filter_lost_elements=True),keymap={'img': 'image','gt_masks': 'masks','gt_bboxes': 'bboxes'}, #train_pipeline = [ # dict(type='LoadImageFromFile'), # dict(type='LoadAnnotations', with_bbox=True), # dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), # dict(type='RandomFlip', flip_ratio=0.5), # dict(type='Normalize', **img_norm_cfg), # dict(type='Pad', size_divisor=32), # dict(type='DefaultFormatBundle'), # dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),] # 測試的pipeline test_pipeline = [dict(type='LoadImageFromFile'),dict(type='MultiScaleFlipAug',# 多尺度測試 TTA在這里修改,注意有些模型不支持多尺度TTA,比如cascade_mask_rcnn,若不支持會提示# Unimplemented Errorimg_scale=(1333, 800),flip=False,transforms=[dict(type='Resize', keep_ratio=True),dict(type='RandomFlip'),dict(type='Normalize', **img_norm_cfg),dict(type='Pad', size_divisor=32),dict(type='ImageToTensor', keys=['img']),dict(type='Collect', keys=['img']),]) ] # 包含batch_size, workers和路徑。 # 路徑如果按照上面的設置好就不需要更改 data = dict(samples_per_gpu=2,workers_per_gpu=2,train=dict(type=dataset_type,ann_file=data_root + 'annotations/instances_train2017.json',img_prefix=data_root + 'train2017/',pipeline=train_pipeline),val=dict(type=dataset_type,ann_file=data_root + 'annotations/instances_val2017.json',img_prefix=data_root + 'val2017/',pipeline=test_pipeline),test=dict(type=dataset_type,ann_file=data_root + 'annotations/instances_val2017.json',img_prefix=data_root + 'val2017/',pipeline=test_pipeline)) evaluation = dict(interval=1, metric='bbox')

    其中,batch_size和路徑等頻繁修改的參數在colab中可以快速修改:

    # 舉例 cfg.samples_per_gpu = 4 cfg.data.train.ann_file = '...' cfg.data.train.img_prefix = '...' cfg.data.train.pipeline = train_pipeline
  • configs/_base_/models/cascade_rcnn_r50_fpn.py
    我們選用的是dcn/cascade_rcnn_r101_20e.py模型進行訓,mmdetectionV2的繼承比較復雜,但是可維護性較好。一路到底,最根本的繼承還是base model中的cascade_rcnn_r50_fpn.py,主要的改動也是在這里進行。
  • # model settings model = dict(type='CascadeRCNN',pretrained='torchvision://resnet50',backbone=dict(type='ResNet',depth=50,num_stages=4,out_indices=(0, 1, 2, 3),frozen_stages=1,norm_cfg=dict(type='BN', requires_grad=True),norm_eval=True,style='pytorch'),neck=dict(type='FPN',in_channels=[256, 512, 1024, 2048],out_channels=256,num_outs=5),rpn_head=dict(type='RPNHead',in_channels=256,feat_channels=256,anchor_generator=dict(type='AnchorGenerator',scales=[8],ratios=[0.5, 1.0, 2.0],strides=[4, 8, 16, 32, 64]),bbox_coder=dict(type='DeltaXYWHBBoxCoder',target_means=[.0, .0, .0, .0],target_stds=[1.0, 1.0, 1.0, 1.0]),loss_cls=dict(type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),loss_bbox=dict(type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0)),# 在這里修改num_classes. roi_head=dict(type='CascadeRoIHead',# 3個stage就意味著要改三個num_classesnum_stages=3,stage_loss_weights=[1, 0.5, 0.25],bbox_roi_extractor=dict(type='SingleRoIExtractor',roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),out_channels=256,featmap_strides=[4, 8, 16, 32]),bbox_head=[dict(type='Shared2FCBBoxHead',in_channels=256,fc_out_channels=1024,roi_feat_size=7,# 這里修改,原為80.注意這里不需要加BG類(+1)num_classes=10,bbox_coder=dict(type='DeltaXYWHBBoxCoder',target_means=[0., 0., 0., 0.],target_stds=[0.1, 0.1, 0.2, 0.2]),reg_class_agnostic=True,loss_cls=dict(type='CrossEntropyLoss',use_sigmoid=False,loss_weight=1.0),loss_bbox=dict(type='SmoothL1Loss', beta=1.0,loss_weight=1.0)),dict(type='Shared2FCBBoxHead',in_channels=256,fc_out_channels=1024,roi_feat_size=7,# 這里修改,原為80.注意這里不需要加BG類(+1)num_classes=10,bbox_coder=dict(type='DeltaXYWHBBoxCoder',target_means=[0., 0., 0., 0.],target_stds=[0.05, 0.05, 0.1, 0.1]),reg_class_agnostic=True,loss_cls=dict(type='CrossEntropyLoss',use_sigmoid=False,loss_weight=1.0),loss_bbox=dict(type='SmoothL1Loss', beta=1.0,loss_weight=1.0)),dict(type='Shared2FCBBoxHead',in_channels=256,fc_out_channels=1024,roi_feat_size=7,# 這里修改,原為80.注意這里不需要加BG類(+1)num_classes=10,bbox_coder=dict(type='DeltaXYWHBBoxCoder',target_means=[0., 0., 0., 0.],target_stds=[0.033, 0.033, 0.067, 0.067]),reg_class_agnostic=True,loss_cls=dict(type='CrossEntropyLoss',use_sigmoid=False,loss_weight=1.0),loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))]))test_cfg = dict(rpn=dict(nms_across_levels=False,nms_pre=1000,nms_post=1000,max_num=1000,nms_thr=0.7,min_bbox_size=0),rcnn=dict(score_thr=0.05,# 在這里可以修改為'soft_nms'nms=dict(type='nms', iou_threshold=0.5),max_per_img=100))
  • mmdetection/configs/_base_/default_runtime.py /
    這里比較簡單,我是為了要用Tensorboard查看訓練,所以在這里解掉注釋。
    可以從官網下載預訓練模型,放在checkpoint/…文件夾中,在這里的load_from中寫入路徑就可以加載權重訓練了。
  • checkpoint_config = dict(interval=1) # yapf:disable log_config = dict(interval=50,hooks=[dict(type='TextLoggerHook'),# 解掉注釋就能看到Tensorboard了dict(type='TensorboardLoggerHook')]) # yapf:enable # 在這里也可以修改load_from 和 resume_from dist_params = dict(backend='nccl') log_level = 'INFO' load_from = None resume_from = None workflow = [('train', 1)]

    這里,load_from和resume_from都可以在colab上在線設置

    cfg.load_from = ’...' cfg.resume_from = '...'
  • mmdetection/configs/_base_/schedules/schedule_20e.py
    這里是調整學習率的schedule的位置,可以設置warmup schedule和衰減策略。
    1x, 2x分別對應12epochs和24epochs,20e對應20epochs,這里注意配置都是默認8塊gpu的訓練,如果用一塊gpu訓練,需要在lr/8
  • # optimizer optimizer = dict(type='SGD', lr=0.02/8, momentum=0.9, weight_decay=0.0001) optimizer_config = dict(grad_clip=None) # learning policy lr_config = dict(policy='step',warmup='linear',warmup_iters=500,warmup_ratio=0.001,step=[16, 19]) total_epochs = 20
  • mmdetection/mmdet/core/evaluation/class_names.py
    這里把coco_classes改成自己對應的class名稱,不然在evaluation的時候返回的名稱不對應。
  • def coco_classes():return ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train','truck', 'boat', 'traffic_light', 'fire_hydrant', 'stop_sign','parking_meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep','cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella','handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard','sports_ball', 'kite', 'baseball_bat', 'baseball_glove', 'skateboard','surfboard', 'tennis_racket', 'bottle', 'wine_glass', 'cup', 'fork','knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange','broccoli', 'carrot', 'hot_dog', 'pizza', 'donut', 'cake', 'chair','couch', 'potted_plant', 'bed', 'dining_table', 'toilet', 'tv','laptop', 'mouse', 'remote', 'keyboard', 'cell_phone', 'microwave','oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase','scissors', 'teddy_bear', 'hair_drier', 'toothbrush']return ['knife, scissors, lighter, zippooil, pressure, slingshot, handcuffs, nailpolish, powerbank, firecrackers']

    總結一下,需要在本地修改的參數有(以使用dcn/cascade_rcnn_r101_20e.py為例):

    1. mmdet/datasets/coco.py 2. configs/\_base_/default_runtime.py 3. configs/\_base_/datasets/coco_detection.py 4. configs/\_base_/models/cascade_rcnn_r50_20e.py 5. mmdet/core/evaluation/class_names.py

    當把這些修改好的文件上傳后,有時需要等待1分鐘左右讓colab與drive同步。

    3.3 在colab上修改config

  • 載入修改好的config
  • from mmcv import Config import albumentations as albu cfg = Config.fromfile('./configs/dcn/cascade_rcnn_r101_fpn_dconv_c3-c5_20e_coco.py')
  • 可以使用以下的命令檢查幾個重要參數:
  • cfg.data.train cfg.total_epochs cfg.data.samples_per_gpu cfg.resume_from cfg.load_from cfg.data ...
  • 改變config中某些參數
  • from mmdet.apis import set_random_seed# Modify dataset type and path# cfg.dataset_type = 'Xray' # cfg.data_root = 'Xray'cfg.data.samples_per_gpu = 4 cfg.data.workers_per_gpu = 4# cfg.data.test.type = 'Xray' cfg.data.test.data_root = '../mmdetection_torch_1.5' # cfg.data.test.img_prefix = '../mmdetection_torch_1.5'# cfg.data.train.type = 'Xray' cfg.data.train.data_root = '../mmdetection_torch_1.5' # cfg.data.train.ann_file = 'instances_train2014.json' # # cfg.data.train.classes = classes # cfg.data.train.img_prefix = '../mmdetection_torch_1.5'# cfg.data.val.type = 'Xray' cfg.data.val.data_root = '../mmdetection_torch_1.5' # cfg.data.val.ann_file = 'instances_val2014.json' # # cfg.data.train.classes = classes # cfg.data.val.img_prefix = '../mmdetection_torch_1.5'# modify neck classes number # cfg.model.neck.num_outs # modify num classes of the model in box head # for i in range(len(cfg.model.roi_head.bbox_head)): # cfg.model.roi_head.bbox_head[i].num_classes = 10# cfg.data.train.pipeline[2].img_scale = (1333,800)cfg.load_from = '../mmdetection_torch_1.5/coco_exps/latest.pth' # cfg.resume_from = './coco_exps_v3/latest.pth'# Set up working dir to save files and logs. cfg.work_dir = './coco_exps_v4'# The original learning rate (LR) is set for 8-GPU training. # We divide it by 8 since we only use one GPU. cfg.optimizer.lr = 0.02 / 8 # cfg.lr_config.warmup = None # cfg.lr_config = dict( # policy='step', # warmup='linear', # warmup_iters=500, # warmup_ratio=0.001, # # [7] yields higher performance than [6] # step=[7]) # cfg.lr_config = dict( # policy='step', # warmup='linear', # warmup_iters=500, # warmup_ratio=0.001, # step=[36,39]) cfg.log_config.interval = 10# # Change the evaluation metric since we use customized dataset. # cfg.evaluation.metric = 'mAP' # # We can set the evaluation interval to reduce the evaluation times # cfg.evaluation.interval = 12 # # We can set the checkpoint saving interval to reduce the storage cost # cfg.checkpoint_config.interval = 12# # Set seed thus the results are more reproducible cfg.seed = 0 set_random_seed(0, deterministic=False) cfg.gpu_ids = range(1) # cfg.total_epochs = 40# # We can initialize the logger for training and have a look # # at the final config used for training print(f'Config:\n{cfg.pretty_text}')
  • 使用Tensorboard進行可視化
    如果有在default_runtime中解除注釋tensorboard,鍵入下面的命令可以開啟實時更新的tensorboard可視化模塊。
  • # Load the TensorBoard notebook extension %load_ext tensorboard # logdir需要填入你的work_dir/+tf_logs %tensorboard --logdir=coco_exps_v4/tf_logs

    3.5 在線訓練

    如果以上的configs都做了正確的修改,直接運行下面的代碼就可以開始訓練了。

    import mmcv import matplotlib.pyplot as plt import copy import os.path as ospfrom mmdet.datasets import build_dataset from mmdet.models import build_detector from mmdet.apis import train_detector# Build dataset datasets = [build_dataset(cfg.data.train)]# Build the detector model = build_detector(cfg.model, train_cfg=cfg.train_cfg, test_cfg=cfg.test_cfg) # Add an attribute for visualization convenience model.CLASSES = datasets[0].CLASSES# Create work_dir mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) print(model) train_detector(model, datasets, cfg, distributed=False, validate=True)

    這里的validate其實很玄學,有些時候運行完第一個epoch后的validate過程會中斷報錯。以下是我碰到的報錯和解決辦法:

    Error: List range out of index.

    一般報這個錯,就要求你檢查num_classes到底有沒有修改正確。一定要在選用的模型的base model中修改所有的num_classes,并且注意MMDV2開始不需要num_classes+1(背景類)了。

    ValueError: Expected x_max for bbox(0.94, 0.47, 1.003, 0.637, 0) to be in range[0,1], got 1.003.

    這個錯誤是Albumentation報的錯,需要檢查的是configs/_base_/coco_detection.py中的數據增廣albu部分是否正確,我的這個任務雖然是COCO格式的數據集但是不知道為什么需要在這里用pascal_voc格式的轉化。從Coco改回pascal_voc就不報錯了。

    dict(type='Albu',transforms=albu_train_transforms,bbox_params=dicttype='BboxParams',format='pascal_voc',.......}

    另外還有一個可能是在其他數據集轉化到CoCo格式數據集的過程中代碼出錯,w,h需要xmax-xmin-1來轉化,仔細檢查一下。

    OSError: Can't read data (file read failed: time = Mon May 20 00:34:07 2019 , filename = '/content/drive/My Drive/train/trainX_file1', file descriptor = 83, errno = 5, error message = 'Input/output error', buf = 0xc71d3864, total read size = 42145, bytes this sub-read = 42145, bytes actually read = 18446744073709551615, offset = 119840768)

    這個是colab的bug,一般這個情況下先檢查是不是指向的文件corrupt了,如果不是的話,可以試著重啟runtime。如果還是不能load,可以用重新force remount,一般就會解決了。

    Cuda out of memory

    經典爆顯存錯誤。需要注意的是中途停止訓練后需要重啟runtime才可以重置顯存的占用量。所以碰到很多奇怪的錯誤第一件事可以嘗試重新runtime。

    ...."Acyclic'

    追溯可以看到,lr_schedule是一個pop的函數讀取的,也就是說讀取一次就沒了。所以每次終止訓練后,需要從config重新導入一次。

    3.6 在線可視化模型效果

    在模型訓練完之后,除了看tensorboard或者log的可視化結果,也可以自己選出幾個圖片看看效果。

    from mmdet.apis import init_detector, inference_detector, show_result_pyplot import mmcv import random# Use your modified config file config_file = './configs/dcn/cascade_rcnn_r101_fpn_dconv_c3-c5_20e_coco.py' # Use your trained model checkpoint_file = './coco_exps_v4/latest.pth' # build the model from a config file and a checkpoint file model = init_detector(config_file, checkpoint_file, device='cuda:0') # get random test image and visualize it with model images = os.listdir('data/coco/test2017') rand_num = random.randint(0, len(images)) image = 'data/coco/test2017/'+images[rand_num] result = inference_detector(model, image)# show the results show_result_pyplot(model, image, result)

    可以看到20個epoch的效果還可以,檢出率和準確率都還可以接受。

    3.7 在線inference

    時間原因我們沒有做出一個在線inference的腳本。采取的方案是下載下來到本地,在本地進行inference。代碼如下

    from argparse import ArgumentParserfrom mmdet.apis import inference_detector, init_detector, show_result_pyplotfrom glob import glob import os from tqdm import tqdmdef get_single_out(result,score_thr):tmp=[i.tolist() for i in result]res=[i.tolist() for i in result]# print(res)for cls_idx,item in enumerate(tmp):if(len(item)!=0):res[cls_idx]=[i for i in item if i[4]>score_thr]# print(res)return resdef main():parser = ArgumentParser()parser.add_argument('--imgdir',default='./data/coco/test2017', help='Image file')parser.add_argument('--config',default='./configs/dcn/cascade_rcnn_r101_fpn_dconv_c3-c5_20e_coco.py', help='Config file')parser.add_argument('--checkpoint',default='coco_exps_v4/epoch_7.pth', help='Checkpoint file')parser.add_argument('--device', default='cuda:0', help='Device used for inference')parser.add_argument('--score-thr', type=float, default=0.01, help='bbox score threshold')args = parser.parse_args()imgdir=args.imgdirimgs=glob(os.path.join(imgdir,"*.jpg"))imgs.sort()out=[]# build the model from a config file and a checkpoint filemodel = init_detector(args.config, args.checkpoint, device=args.device)for imgpath in tqdm(imgs):print(imgpath)# # test a single imageresult = inference_detector(model, imgpath)single_out=get_single_out(result,args.score_thr)out.append(single_out)# # show the results# show_result_pyplot(model, imgpath, result, score_thr=args.score_thr)#將結果寫入到文件中f=open('coco_exps_v4/output_8_softnms.json','w')f.write(str(out))f.close()if __name__ == '__main__':main()

    最后的結果是本次比賽要求的格式,讀者可以根據需要修改成適合自己的任務。

    4. 延伸思考

    基礎的訓練任務到這里就告一段落了,但是對于一個項目或者一個比賽來說,只掌握基礎的訓練技巧是遠遠不夠的。比如我簡短涉及到的soft_nms,多尺度訓練,TTA,這些tricks可以一定程度上提高成績,但我認為相比較聚焦于tricks,一個highlevel的視角更重要。以下是我認為完成一個任務需要具備的幾個條件:

    1. 對于數據的深入了解。包括但不限于:w、h的分布,分辨率的分布,目標物體的w/h比(用來確定anchor shape) 2. 整體的思路要清晰:選用不同的baseline model測試,加tricks,怎么對數據集做處理,以及實驗記錄。 3. 有時候算力確實是決定一個隊伍能走多遠的瓶頸。

    5. 總結

    作為一個只了解目標檢測原理的小白,經過幾十個小時的摸索,我能夠掌握mmdetection+colab的基礎操作和相關error的debug,這個過程還是比較有成就感的。中間參考了許多CSDN和知乎的大佬的博客,讓我受益良多,也讓我覺得有必要整理一下自己的踩坑實錄,這篇文章權當做拋磚引玉,給其他大佬們一些啟發。中間如果有不正確和不efficient的部分歡迎探討。
    我今后會發表更多的與目標檢測相關的工具的詳細教程以及論文筆記,有興趣的朋友歡迎關注。
    都看到這里了,點個贊唄。

    本文鏈接http://smartadmin.com.cn/smartadmin/show-1159.html

    總結

    以上是生活随笔為你收集整理的MMDetectionV2 + Colab的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。