1. 磐创AI首页
  2. 系列教程
  3. MMDetection

MMDetection 入门 | 二

本文是全系列中第2 / 4篇:MMDetection

作者|open-mmlab
编译|Flin
来源|Github

入门

本页提供有关MMDetection用法的基本教程。
有关安装说明,请参阅上一篇的安装文档 。

预训练模型的推论

我们提供测试脚本来评估整个数据集(COCO,PASCAL VOC等)以及一些高级api,以便更轻松地集成到其他项目。

测试数据集
  • [x]单个GPU测试
  • [x]多个GPU测试
  • [x]可视化检测结果

你可以使用以下命令测试数据集。

#单GPU测试
python tools / test.py $ {CONFIG_FILE} $ {CHECKPOINT_FILE} [--out $ {RESULT_FILE}] [--eval $ {EVAL_METRICS}] [--show]

#多GPU测试
./tools/dist_test.sh $ {CONFIG_FILE} $ {CHECKPOINT_FILE} $ {GPU_NUM} [--out $ {RESULT_FILE}] [--eval $ {EVAL_METRICS}]

可选参数:
RESULT_FILE:输出结果的文件名是pickle格式。如果未指定,结果将不会保存到文件中。
EVAL_METRICS:要根据结果评估的项目。允许的值取决于数据集,例如proposal_fast,proposal,bbox,segm可用于COCO和mAP,recall为PASCAL VOC。

--show:如果指定,检测结果将绘制在图像上并显示在新窗口中。它仅适用于单个GPU测试,并用于调试和可视化。请确保GUI在你的环境中可用,否则你可能会遇到类似cannot connect to X server的错误。

如果要评估数据集,请不要同时指定--show

例子:

假设你已经将检查点下载到目录checkpoints/

1.测试更快的R-CNN并可视化结果。按任意键获取下一张图像。

python tools/test.py configs/faster_rcnn_r50_fpn_1x.py 
    checkpoints/faster_rcnn_r50_fpn_1x_20181010-3d1b3351.pth 
    --show

2.在PASCAL VOC上测试更快的R-CNN(不保存测试结果)并评估mAP。

python tools/test.py configs/pascal_voc/faster_rcnn_r50_fpn_1x_voc.py 
    checkpoints/SOME_CHECKPOINT.pth 
    --eval mAP

3.使用8个GPU测试Mask R-CNN,并评估bbox和mask AP。

./tools/dist_test.sh configs/mask_rcnn_r50_fpn_1x.py 
    checkpoints/mask_rcnn_r50_fpn_1x_20181010-069fa190.pth 
    8 --out results.pkl --eval bbox segm

4.在具有8个GPU的COCO test-dev上测试Mask R-CNN,并生成json文件提交给官方评估服务器。

./tools/dist_test.sh configs/mask_rcnn_r50_fpn_1x.py 
    checkpoints/mask_rcnn_r50_fpn_1x_20181010-069fa190.pth 
    8 --format-only --options "jsonfile_prefix=./mask_rcnn_test-dev_results"

你将获得两个json文件mask_rcnn_test-dev_results.bbox.jsonmask_rcnn_test-dev_results.segm.json

网络摄像头演示

我们提供了一个网络摄像头演示来说明结果。

python demo / webcam_demo.py $ {CONFIG_FILE} $ {CHECKPOINT_FILE} [-设备$ {GPU_ID}] [--camera-id $ {CAMERA-ID}] [--score-thr $ {SCORE_THR}]

例子:

python demo/webcam_demo.py configs/faster_rcnn_r50_fpn_1x.py 
    checkpoints/faster_rcnn_r50_fpn_1x_20181010-3d1b3351.pth

用于测试图像的高级API

同步接口

这是构建模型并测试给定图像的示例。

from mmdet.apis import init_detector, inference_detector, show_result
import mmcv

config_file = 'configs/faster_rcnn_r50_fpn_1x.py'
checkpoint_file = 'checkpoints/faster_rcnn_r50_fpn_1x_20181010-3d1b3351.pth'

# 从配置文件和检查点文件构建模型
model = init_detector(config_file, checkpoint_file, device='cuda:0')

# 测试一张图片并显示结果
img = 'test.jpg'  # or img = mmcv.imread(img), which will only load it once
result = inference_detector(model, img)
# 在新窗口中可视化结果
show_result(img, result, model.CLASSES)
# 或者将可视化结果保存到图像文件中
show_result(img, result, model.CLASSES, out_file='result.jpg')

# 测试视频并显示结果
video = mmcv.VideoReader('video.mp4')
for frame in video:
    result = inference_detector(model, frame)
    show_result(frame, result, model.CLASSES, wait_time=1)

Jupyter Notebook演示可以在 demo/inference_demo.ipynb.(https://github.com/open-mmlab/mmdetection/blob/master/demo/inference_demo.ipynb)中找到。

异步接口-受Python 3.7+支持

异步接口允许不阻塞GPU绑定推理代码上的CPU,并为单线程应用程序提供更好的CPU / GPU利用率。可以在不同的输入数据样本之间或某个推理管道的不同模型之间同时进行推理。

请参阅tests/async_benchmark.py比较同步和异步接口的速度。

import torch
from mmdet.apis import init_detector, async_inference_detector, show_result
from mmdet.utils.contextmanagers import concurrent

async def main():
    config_file = 'configs/faster_rcnn_r50_fpn_1x.py'
    checkpoint_file = 'checkpoints/faster_rcnn_r50_fpn_1x_20181010-3d1b3351.pth'
    device = 'cuda:0'
    model = init_detector(config_file, checkpoint=checkpoint_file, device=device)

    # 队列用于多幅图像的并发推理
    streamqueue = asyncio.Queue()
    # 队列大小定义并发级别
    streamqueue_size = 3

    for _ in range(streamqueue_size):
        streamqueue.put_nowait(torch.cuda.Stream(device=device))

    # 测试单个图像并显示结果
    img = 'test.jpg'  # or img = mmcv.imread(img), which will only load it once

    async with concurrent(streamqueue):
        result = await async_inference_detector(model, img)

    # 在新窗口中可视化结果
    show_result(img, result, model.CLASSES)
    # 或者将可视化结果保存到图像文件中
    show_result(img, result, model.CLASSES, out_file='result.jpg')

训练模型

MMDetection实施分布式训练和非分布式训练,
它分别使用MMDistributedDataParallelMMDataParallel

所有输出(日志文件和检查点)将保存到工作目录中,
在配置文件中由work_dir指定。

默认情况下,我们在每个epoch后在验证集上评估模型,你可以通过在训练配置中添加interval参数来更改评估间隔。

Evaluation = dict(interval = 12)#每12个时间段评估一次模型。
  • 重要:配置文件中的默认学习率是8个GPU和2 img / gpu(批量大小= 8 * 2 = 16)。根据线性缩放规则(https://arxiv.org/abs/1706.02677),如果你使用不同的GPU或每个GPU的图像,则需要按批大小设置成比例的学习率,例如,对于4个GPU,lr = 0.01 * 2 img / gpu;对于16个GPU,lr = 0.08 * 4 img / gpu。
使用单个GPU训练
python tools / train.py $ {CONFIG_FILE}

如果要在命令中指定工作目录,则可以添加参数--work_dir $ {YOUR_WORK_DIR}

使用多个GPU训练
./tools/dist_train.sh $ {CONFIG_FILE} $ {GPU_NUM} [可选参数]

可选参数为:

  • --validate(强烈建议):在训练过程中,每隔k个epoch执行一次评估(默认值为1,可以像这样(https://github.com/open-mmlab/mmdetection/blob/master/configs/mask_rcnn_r50_fpn_1x.py#L174) 修改)。
  • --work_dir ${WORK_DIR}:覆盖配置文件中指定的工作目录。
  • --resume_from ${CHECKPOINT_FILE}:从先前的检查点文件恢复。

resume_fromload_from之间的区别:
resume_from加载模型权重和优化器状态,​​并且epoch也从指定的检查点继承。它通常用于恢复意外中断的训练过程。
load_from仅加载模型权重,训练时期从0开始。通常用于微调。

用多台机器训练

如果在由slurm(https://slurm.schedmd.com/) 管理的群集上运行MMDetection,则可以使用脚本”slurm_train.sh”。(此脚本还支持单机训练。)

./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} ${CONFIG_FILE} ${WORK_DIR} [${GPUS}]

这是使用16个GPU在dev分区上训练Mask R-CNN的示例。

./tools/slurm_train.sh dev mask_r50_1x configs/mask_rcnn_r50_fpn_1x.py /nfs/xxxx/mask_rcnn_r50_fpn_1x 16

你可以检查slurm_train.sh(https://github.com/open-mmlab/mmdetection/blob/master/tools/slurm_train.sh) 中的完整参数和环境变量。

如果只有多台计算机与以太网连接,则可以参考
pytorch 启动实用程序(https://pytorch.org/docs/stable/distributed_deprecated.html#launch-utility)。
如果没有像infiniband这样的高速网络,通常速度很慢。

在单台计算机上启动多个作业

如果你在一台计算机上启动多个作业,例如,在具有8个GPU的计算机上进行2个4-GPU训练作业,
你需要为每个作业指定不同的端口(默认为29500),以避免通信冲突。

如果你使用dist_train.sh启动训练作业,则可以在命令中设置端口。

CUDA_VISIBLE_DEVICES = 0,1,2,3 PORT = 29500 ./tools/dist_train.sh $ {CONFIG_FILE} 4
CUDA_VISIBLE_DEVICES = 4,5,6,7 PORT = 29501 ./tools/dist_train.sh $ {CONFIG_FILE} 4

如果你将启动训练作业与slurm一起使用,则需要修改配置文件(通常是配置文件底部的第6行)以设置不同的通信端口。

config1.py中,

dist_params = dict(backend='nccl',port= 29500)

在config2.py中,

dist_params = dict(backend='nccl',port= 29501)

然后,你可以使用config1.py和config2.py启动两个作业。

CUDA_VISIBLE_DEVICES=0,1,2,3 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config1.py ${WORK_DIR} 4
CUDA_VISIBLE_DEVICES=4,5,6,7 ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} config2.py ${WORK_DIR} 4

有用的工具

我们在tools/目录下提供了许多有用的工具。

分析日志

你可以绘制给定训练日志文件的损耗/ mAP曲线。首先运行pip install seaborn来安装依赖项。

MMDetection 入门 | 二

python tools/analyze_logs.py plot_curve [--keys ${KEYS}] [--title ${TITLE}] [--legend ${LEGEND}] [--backend ${BACKEND}] [--style ${STYLE}] [--out ${OUT_FILE}]

例子:

  • 绘制一些运行的分类损失。
python tools/analyze_logs.py plot_curve log.json --keys loss_cls --legend loss_cls
  • 绘制一些运行的分类和回归损失,并将该图保存为pdf。
python tools/analyze_logs.py plot_curve log.json --keys loss_cls loss_reg --out losses.pdf
  • 比较同一图中两次运行的bbox mAP。
python tools/analyze_logs.py plot_curve log1.json log2.json --keys bbox_mAP --legend run1 run2

你还可以计算平均训练速度。

python tools/analyze_logs.py cal_train_time ${CONFIG_FILE} [--include-outliers]

预期输出将如下所示。

-----Analyze train time of work_dirs/some_exp/20190611_192040.log.json-----
slowest epoch 11, average time is 1.2024
fastest epoch 1, average time is 1.1909
time std over epochs is 0.0028
average iter time: 1.1959 s/iter
获取FLOP和参数(实验)

我们提供了一个根据 flops-counter.pytorch (https://github.com/sovrasov/flops-counter.pytorch)改编的脚本,用于计算给定模型的FLOP和参数。

python tools/get_flops.py ${CONFIG_FILE} [--shape ${INPUT_SHAPE}]

你将得到这样的结果。

==============================
Input shape: (3, 1280, 800)
Flops: 239.32 GMac
Params: 37.74 M
==============================

注意:此工具仍处于试验阶段,我们不保证该数字正确。你可以将结果用于简单比较,但是在将其用于技术报告或论文之前,请仔细检查。

(1)FLOP与输入形状有关,而参数与输入形状无关。默认输入形状为(1、3、1280、800)。
(2)某些运算符不像GN和自定义运算符那样计入FLOP。
你可以通过修改mmdet / utils / flops_counter.py(https://github.com/open-mmlab/mmdetection/blob/master/mmdet/utils/flops_counter.py) 添加对新操作员的支持。
(3)两级检测器的FLOP取决于提议的数量。

发布模型

在将模型上传到AWS之前,你可能需要
(1)将模型权重转换为CPU张量,
(2)删除优化器状态并
(3)计算检查点文件的哈希并将哈希ID附加到文件名中。

python tools/publish_model.py ${INPUT_FILENAME} ${OUTPUT_FILENAME}

例如,

python tools/publish_model.py work_dirs/faster_rcnn/latest.pth faster_rcnn_r50_fpn_1x_20190801.pth

最终输出文件名将为faster_rcnn_r50_fpn_1x_20190801- {hash id} .pth

测试检测器的鲁棒性

请参考ROBUSTNESS_BENCHMARKING.md

操作方法

使用我自己的数据集

最简单的方法是将数据集转换为现有的数据集格式(COCO或PASCAL VOC)。

在这里,我们展示了一个添加5类自定义数据集的示例,假设它也是COCO格式。

mmdet/datasets/my_dataset.py中:

from .coco import CocoDataset
from .registry import DATASETS


@DATASETS.register_module
class MyDataset(CocoDataset):

    CLASSES = ('a', 'b', 'c', 'd', 'e')

mmdet/datasets/init.py中:

from .my_dataset import MyDataset

然后,你可以在配置文件中使用MyDataset,并使用与CocoDataset相同的API。

如果你不想将注释格式转换为COCO或PASCAL格式,也可以。
实际上,我们定义了一种简单的注释格式,并且所有现有数据集都是
处理以使其与在线或离线兼容。

数据集的注释是字典列表,每个字典对应一个图像。有3个字段filename(相对路径),width,height用于测试,还有一个用于训练的字段ann``ann也是一个至少包含2个字段的字典:都是numpy数组的bboxeslabels。一些数据集可能会提供注释,例如crowd/difficult/被忽略的bbox, 我们使用bboxes_ignorelabels_ignore掩盖他们。

这是一个例子。

[
    {
        'filename': 'a.jpg',
        'width': 1280,
        'height': 720,
        'ann': {
            'bboxes':  (n, 4),
            'labels':  (n, ),
            'bboxes_ignore':  (k, 4),
            'labels_ignore':  (k, ) (optional field)
        }
    },
    ...
]

有两种使用自定义数据集的方法。

  • 在线转换

    你可以编写一个继承自CustomDataset的新Dataset类,并覆盖两个方法
    load_annotations(self,ann_file)get_ann_info(self,idx),
    像CocoDataset(https://github.com/open-mmlab/mmdetection/blob/master/mmdet/datasets/coco.py) 和VOCDataset(https://github.com/open-mmlab/mmdetection/blob/master/mmdet/datasets/voc.py)

  • 离线转换

    你可以将注释格式转换为上面的预期格式,然后将其保存到
    泡菜或json文件,例如pascal_voc.py(https://github.com/open-mmlab/mmdetection/blob/master/tools/convert_datasets/pascal_voc.py)。
    然后,你可以简单地使用CustomDataset

自定义优化

mmdet/core/optimizer/copy_of_sgd.py中定义了定制优化器CopyOfSGD的示例。
更一般地,可以如下定义定制的优化器。

mmdet/core/optimizer/my_optimizer.py中:

from .registry import OPTIMIZERS
from torch.optim import Optimizer

@OPTIMIZERS.register_module
class MyOptimizer(Optimizer):

mmdet/core/optimizer/init.py中:

from .my_optimizer import MyOptimizer

然后,你可以在配置文件的”optimizer”字段中使用”MyOptimizer”。

开发新组件

我们基本上将模型组件分为4种类型。

  • backbone:通常是FCN网络,用于提取特征图,例如ResNet,MobileNet。
  • neck:骨干和头部之间的组件,例如FPN,PAFPN。
  • head:用于特定任务的组件,例如bbox预测和掩码预测。
  • roi提取器:用于从要素图(例如RoI Align)中提取RoI要素的部分。

在这里,我们以MobileNet为例说明如何开发新组件。

  1. 创建一个新文件”mmdet/models/backbones/mobilenet.py”。
import torch.nn as nn

from ..registry import BACKBONES

@BACKBONES.register_module
class MobileNet(nn.Module):

    def __init__(self, arg1, arg2):
        pass

    def forward(self, x):  # should return a tuple
        pass

    def init_weights(self, pretrained=None):
        pass
  1. 将模块导入”mmdet/models/backbones/init.py”。
from .mobilenet import MobileNet
  1. 在配置文件中使用它。
model = dict(
    ...
    backbone=dict(
        type='MobileNet',
        arg1=xxx,
        arg2=xxx),
    ...

有关其工作原理的更多信息,可以参考技术细节手册。

原文链接:https://mmdetection.readthedocs.io/en/latest/GETTING_STARTED.html

原创文章,作者:磐石,如若转载,请注明出处:https://panchuang.net/2020/05/05/mmdetection-%e5%85%a5%e9%97%a8-%e4%ba%8c/

发表评论

登录后才能评论

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息