• MMDetection 简单教程之配置文件(MMDetection3D也可从此开始学习)


    写在前面:本人正在学习MMDetection3D的过程中,可能有理解错误,欢迎指正。

    参考视频链接:4小时入门深度学习+实操MMDetection 第二课

    官方中文文档:MMDetection 文档

    一、模型推断

            在官方github上下载所需模型(预训练模型参数文件/pth文件)及其配置文件(后面会讲配置文件的内容/py文件)。

            然后使用下列代码进行单张图片的推断:

    1. from mmdet import init_detector, inference_detector, show_result_pyplot
    2. config_file = "xxxx.py" # 刚才下载的配置文件路径
    3. checkpoint_file = "xxxx.pth" # 刚才下载的模型文件路径
    4. model = init_detector(config_file, checkpoint_file) # 初始化模型并从checkpoint加载模型
    5. result = inference_detector(model, "demo.jpg") # 得到检测结果
    6. show_result_pyplot(model, "demo.jpg", result) # 可视化检测结果

    二、配置文件

    官方教程:教程 1: 学习配置文件 — MMDetection 2.25.1 文档

            配置文件定义了完整的训练过程,通常包含多个字段,重要的有

    • model字段:定义模型(包含损失函数、训练和测试时的设置等)

    • data字段:定义数据(包含预处理)

    • optimizer、lr_config等字段:定义训练策略

    • load_from字段:定义预训练模型的参数文件

            下面以yolov3_mobilenetv2_mstrain-416_300e_coco.py为例进行简单介绍(暂不深究,目前需要注意的地方见注释):

    1. _base_ = '../_base_/default_runtime.py'
    2. # 表明该配置文件继承自配置文件default_runtime.py(后面会讲到继承)
    3. # 暂时可以理解为等价于将default_runtime.py中的内容复制到这里
    4. # model settings
    5. model = dict( # model字段
    6. type='YOLOV3',
    7. backbone=dict( # 主干网络
    8. type='MobileNetV2',
    9. out_indices=(2, 4, 6),
    10. act_cfg=dict(type='LeakyReLU', negative_slope=0.1),
    11. init_cfg=dict(
    12. type='Pretrained', checkpoint='open-mmlab://mmdet/mobilenet_v2')),
    13. neck=dict( # 颈部网络
    14. type='YOLOV3Neck',
    15. num_scales=3,
    16. in_channels=[320, 96, 32],
    17. out_channels=[96, 96, 96]),
    18. bbox_head=dict( # 检测头
    19. type='YOLOV3Head',
    20. num_classes=80, # 分类的类别数
    21. in_channels=[96, 96, 96],
    22. out_channels=[96, 96, 96],
    23. anchor_generator=dict(
    24. type='YOLOAnchorGenerator',
    25. base_sizes=[[(116, 90), (156, 198), (373, 326)],
    26. [(30, 61), (62, 45), (59, 119)],
    27. [(10, 13), (16, 30), (33, 23)]],
    28. strides=[32, 16, 8]),
    29. bbox_coder=dict(type='YOLOBBoxCoder'),
    30. featmap_strides=[32, 16, 8],
    31. loss_cls=dict( # 分类损失
    32. type='CrossEntropyLoss', # 损失类型:交叉熵
    33. use_sigmoid=True,
    34. loss_weight=1.0,
    35. reduction='sum'),
    36. loss_conf=dict( # 置信度损失(YOLO特有的损失)
    37. type='CrossEntropyLoss', # 损失类型:交叉熵
    38. use_sigmoid=True,
    39. loss_weight=1.0,
    40. reduction='sum'),
    41. loss_xy=dict( # 位置分类损失
    42. type='CrossEntropyLoss', # 损失类型:交叉熵
    43. use_sigmoid=True,
    44. loss_weight=2.0,
    45. reduction='sum'),
    46. loss_wh=dict( # 长宽回归损失
    47. type='MSELoss', # 损失类型:MSE
    48. loss_weight=2.0,
    49. reduction='sum')),
    50. # training and testing settings
    51. train_cfg=dict( # 训练配置
    52. assigner=dict(
    53. type='GridAssigner',
    54. pos_iou_thr=0.5, # 正锚框的IoU阈值设置
    55. neg_iou_thr=0.5, # 负锚框的IoU阈值设置
    56. min_pos_iou=0)),
    57. test_cfg=dict( # 测试配置
    58. nms_pre=1000,
    59. min_bbox_size=0,
    60. score_thr=0.05,
    61. conf_thr=0.005,
    62. nms=dict( # NMS设置
    63. type='nms',
    64. iou_threshold=0.45), # NMS中的IoU阈值设置
    65. max_per_img=100))
    66. # dataset settings
    67. dataset_type = 'CocoDataset'
    68. data_root = 'data/coco/'
    69. img_norm_cfg = dict(
    70. mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
    71. train_pipeline = [ # 训练数据读取和预处理
    72. dict(type='LoadImageFromFile'), # 读取图像
    73. dict(type='LoadAnnotations', with_bbox=True), # 读取标注
    74. dict( # 下面都是图像预处理及数据增广等操作
    75. type='Expand',
    76. mean=img_norm_cfg['mean'],
    77. to_rgb=img_norm_cfg['to_rgb'],
    78. ratio_range=(1, 2)),
    79. dict(
    80. type='MinIoURandomCrop',
    81. min_ious=(0.4, 0.5, 0.6, 0.7, 0.8, 0.9),
    82. min_crop_size=0.3),
    83. dict(
    84. type='Resize',
    85. img_scale=[(320, 320), (416, 416)],
    86. multiscale_mode='range',
    87. keep_ratio=True),
    88. dict(type='RandomFlip', flip_ratio=0.5),
    89. dict(type='PhotoMetricDistortion'),
    90. dict(type='Normalize', **img_norm_cfg),
    91. dict(type='Pad', size_divisor=32),
    92. dict(type='DefaultFormatBundle'),
    93. dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
    94. ]
    95. test_pipeline = [ # 测试数据读取和预处理
    96. dict(type='LoadImageFromFile'),
    97. dict(
    98. type='MultiScaleFlipAug',
    99. img_scale=(416, 416),
    100. flip=False,
    101. transforms=[
    102. dict(type='Resize', keep_ratio=True),
    103. dict(type='RandomFlip'),
    104. dict(type='Normalize', **img_norm_cfg),
    105. dict(type='Pad', size_divisor=32),
    106. dict(type='DefaultFormatBundle'),
    107. dict(type='Collect', keys=['img'])
    108. ])
    109. ]
    110. data = dict( # data字段
    111. samples_per_gpu=24, # batch size
    112. workers_per_gpu=4,
    113. train=dict( # 训练集
    114. type='RepeatDataset', # use RepeatDataset to speed up training
    115. times=10,
    116. dataset=dict(
    117. type=dataset_type,
    118. ann_file=data_root + 'annotations/instances_train2017.json',
    119. # 训练集标注文件路径
    120. img_prefix=data_root + 'train2017/', # 训练集图像所在文件夹路径
    121. pipeline=train_pipeline)),
    122. val=dict( # 验证集
    123. type=dataset_type,
    124. ann_file=data_root + 'annotations/instances_val2017.json',
    125. img_prefix=data_root + 'val2017/',
    126. pipeline=test_pipeline),
    127. test=dict( # 测试集
    128. type=dataset_type,
    129. ann_file=data_root + 'annotations/instances_val2017.json',
    130. img_prefix=data_root + 'val2017/',
    131. pipeline=test_pipeline))
    132. # optimizer
    133. optimizer = dict( # 优化器设置
    134. type='SGD', # 优化器类型
    135. lr=0.003, # 学习率
    136. momentum=0.9,
    137. weight_decay=0.0005)
    138. optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))
    139. # learning policy
    140. lr_config = dict( # 学习率变化策略设置
    141. policy='step',
    142. warmup='linear',
    143. warmup_iters=4000,
    144. warmup_ratio=0.0001,
    145. step=[24, 28])
    146. # runtime settings
    147. runner = dict(
    148. type='EpochBasedRunner',
    149. max_epochs=30) # 训练的总epoch数
    150. evaluation = dict(
    151. interval=1,
    152. metric=['bbox'])
    153. find_unused_parameters = True
    154. # NOTE: `auto_scale_lr` is for automatically scaling LR,
    155. # USER SHOULD NOT CHANGE ITS VALUES.
    156. # base_batch_size = (8 GPUs) x (24 samples per GPU)
    157. auto_scale_lr = dict(base_batch_size=192)

    三、自定义数据集进行模型训练

    官方教程:教程 2: 自定义数据集 — MMDetection 2.25.1 文档

            以目标检测任务为例,若要使用自己的数据集,在预训练模型上进行微调,则步骤如下:

            1.下载基础模型的参数和配置文件

            2.将自己的数据集整理为MMDetection支持的格式

            一个方法是使自己的数据集与已支持的数据集有相同的组织方式(如标注结构与含义等)。

            例如,要将自己的图像数据集组织为Coco数据集的形式,首先观察Coco数据集标注文件(json文件)格式:

    1. {
    2. "info" : info, # 数据集相关,可忽略
    3. "images" : [image], # 图像列表
    4. "annotations" : [annotation], # 标注列表
    5. "license" : [license], # 数据集相关,可忽略
    6. "categories" : [categories], # 类别名称列表
    7. }

            其中

    1. image {
    2. "id" : int,
    3. "width" : int,
    4. "height" : int,
    5. "file_name" : str,
    6. "license" : int,
    7. "flickr_url" : str,
    8. "coco_url" : str,
    9. "date_captured" : datetime,
    10. }
    1. annotation {
    2. "id" : int,
    3. "image_id" : int,
    4. "category_id" : int,
    5. "segmentation" : RLE or [polygon],
    6. "area" : float,
    7. "bbox" : [x,y,width,height], # x,y为边界框左上角到图像左上角的距离
    8. "iscrowd" : 0 or 1,
    9. }
    1. categories [{
    2. "id" : int,
    3. "name" : str,
    4. "supercategory" : str,
    5. }]

            按照上述格式建立自己数据集的标注文件即可。

            将自定义数据集转换为预训练时所用数据集的形式后,还需要在配置文件的data字段中修改相应的图像文件路径和标注文件路径(见下一步)。

            3.修改配置文件(数据路径、分类头、预训练模型加载、优化器配置等)

            配置文件的修改可通过继承的方式(当然,也可直接复制预训练模型的配置文件后修改)。

            例如新建微调模型的配置文件(如new_model_cfg.py),想在预训练模型的配置文件上修改时,可先写上如下语句表明该配置文件是在原配置文件上进行修改的:

    _base_ = ['yolov3_mobilenetv2_mstrain-416_300e_coco.py']    # 预训练模型的配置文件路径

            然后修改数据路径只需要找到对应项进行修改(下列代码中未出现的项不变):

    1. data = dict(
    2. train = dict(
    3. dataset = dict(
    4. ann_file = 'xxx', # 标注文件路径
    5. img = 'xxx', # 图像路径
    6. classes = ("xx", ...)) # 类别名称(新增项)
    7. ),
    8. val = dict(...), # 类似修改验证集和测试集
    9. test = dict(...)
    10. )

            分类头的修改也类似,只需修改类别数:

    model = dict(bbox_head(num_classes = xx))

            训练配置的修改同理:

    1. runner = dict(max_epochs=xx)
    2. optimizer = dict(lr=xx)
    3. lr_config = None

            最后加上load_from字段以使模型从预训练模型开始进行微调:

    1. load_from = "yolov3_mobilenetv2_mstrain-416_300e_coco_20210718_010823-f68a07b3.pth"
    2. # 预训练模型参数文件路径

            输出信息的频率设置如下(原始模型的配置文件中该部分继承自default_runtime.py):

    log_config = dict(interval=xx)  # 每xx迭代次数输出一次信息
  • 相关阅读:
    ARTS第五周:S - 数据编织 Data fabric
    人工智能:TensorFlow深度学习框架介绍
    数学学习与研究杂志数学学习与研究杂志社数学学习与研究编辑部2022年第24期目录
    autodl服务器中YOLOx训练自己数据集
    面试官:熟悉Redis?请讲讲Redis缓存穿透、缓存击穿、缓存雪崩有什么区别
    【Python学习笔记】超详细Python快速入门教程(下)
    山海鲸数字孪生防汛解决方案:智慧抵御自然灾害
    2023-09-13力扣每日一题
    CPU设计(单周期和流水线)
    varchar与char区别,以及最大长度
  • 原文地址:https://blog.csdn.net/weixin_45657478/article/details/126604432