欢迎使用 PaddleDetection!

入门使用教程

安装说明


简介

这份文档介绍了如何安装PaddleDetection及其依赖项(包括PaddlePaddle)。

PaddleDetection的相关信息,请参考README.md.

安装PaddlePaddle

环境需求:

  • OS 64位操作系统
  • Python2 >= 2.7.15 or Python 3(3.5.1+/3.6/3.7),64位版本
  • pip/pip3(9.0.1+),64位版本操作系统是
  • CUDA >= 9.0
  • cuDNN >= 7.6

如果需要 GPU 多卡训练,请先安装NCCL(Windows暂不支持nccl)。

PaddleDetection 依赖 PaddlePaddle 版本关系:

PaddleDetection版本 PaddlePaddle版本 备注
v0.3 >=1.7 --
v0.4 >= 1.8.4 PP-YOLO依赖1.8.4
v0.5 >= 1.8.4 大部分模型>=1.8.4即可运行,Cascade R-CNN系列模型与SOLOv2依赖2.0.0.rc版本
# install paddlepaddle
python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

# 如果您的机器安装的是CUDA9,请运行以下命令安装
python -m pip install paddlepaddle-gpu==1.8.4.post97 -i https://mirror.baidu.com/pypi/simple

如果您的机器安装的是CUDA10,请运行以下命令安装
python -m pip install paddlepaddle-gpu==1.8.4.post107 -i https://mirror.baidu.com/pypi/simple

如果您的机器是CPU,请运行以下命令安装

python -m pip install paddlepaddle==1.8.4 -i https://mirror.baidu.com/pypi/simple

更多的安装方式如conda, docker安装,请参考安装文档中的说明进行操作

请确保您的PaddlePaddle安装成功并且版本不低于需求版本。使用以下命令进行验证。

# 在您的Python解释器中确认PaddlePaddle安装成功
>>> import paddle.fluid as fluid
>>> fluid.install_check.run_check()

# 确认PaddlePaddle版本
python -c "import paddle; print(paddle.__version__)"

其他依赖安装

COCO-API:

运行需要COCO-API,安装方式如下:

# 安装pycocotools
pip install pycocotools

windows用户安装COCO-API方式:

# 若Cython未安装,请安装Cython
pip install Cython

# 由于原版cocoapi不支持windows,采用第三方实现版本,该版本仅支持Python3
pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI

PaddleDetection

安装Python依赖库:

Python依赖库在requirements.txt中给出,可通过如下命令安装:

pip install -r requirements.txt

克隆PaddleDetection库:

您可以通过以下命令克隆PaddleDetection:

cd <path/to/clone/PaddleDetection>
git clone https://github.com/PaddlePaddle/PaddleDetection.git

提示:

也可以通过 https://gitee.com/paddlepaddle/PaddleDetection 克隆。

cd <path/to/clone/PaddleDetection>
git clone https://gitee.com/paddlepaddle/PaddleDetection

确认测试通过:

python ppdet/modeling/tests/test_architectures.py

测试通过后会提示如下信息:

..........
----------------------------------------------------------------------
Ran 12 tests in 2.480s
OK (skipped=2)

预训练模型预测

使用预训练模型预测图像,快速体验模型预测效果:

# use_gpu参数设置是否使用GPU
python tools/infer.py -c configs/ppyolo/ppyolo.yml -o use_gpu=true weights=https://paddlemodels.bj.bcebos.com/object_detection/ppyolo.pdparams --infer_img=demo/000000014439.jpg

会在output文件夹下生成一个画有预测结果的同名图像。

结果如下图:

_images/000000014439.jpg

English | 简体中文

快速开始

为了使得用户能够在很短时间内快速产出模型,掌握PaddleDetection的使用方式,这篇教程通过一个预训练检测模型对小数据集进行finetune。在较短时间内即可产出一个效果不错的模型。实际业务中,建议用户根据需要选择合适模型配置文件进行适配。

  • 设置显卡
export CUDA_VISIBLE_DEVICES=0

一、快速体验

# 用PP-YOLO算法在COCO数据集上预训练模型预测一张图片
python tools/infer.py -c configs/ppyolo/ppyolo.yml -o use_gpu=true weights=https://paddlemodels.bj.bcebos.com/object_detection/ppyolo.pdparams --infer_img=demo/000000014439.jpg

结果如下图:

_images/000000014439.jpg

二、准备数据

数据集参考Kaggle数据集 ,包含877张图像,数据类别4类:crosswalk,speedlimit,stop,trafficlight。将数据划分为训练集701张图和测试集176张图,下载链接.

# 注意:可跳过这步下载,后面训练会自动下载
python dataset/roadsign_voc/download_roadsign_voc.py

三、训练、评估、预测

1、训练
# 边训练边测试 CPU需要约1小时(use_gpu=false),1080Ti GPU需要约5分钟。
# -c 参数表示指定使用哪个配置文件
# -o 参数表示指定配置文件中的全局变量(覆盖配置文件中的设置),这里设置使用gpu,
# --eval 参数表示边训练边评估,会自动保存一个评估结果最的名为best_model.pdmodel的模型


python tools/train.py -c configs/yolov3_mobilenet_v1_roadsign.yml --eval -o use_gpu=true

如果想通过VisualDL实时观察loss变化曲线,在训练命令中添加--use_vdl=true,以及通过--vdl_log_dir设置日志保存路径。

但注意VisualDL需Python>=3.5

首先安装VisualDL

python -m pip install visualdl -i https://mirror.baidu.com/pypi/simple
python -u tools/train.py -c configs/yolov3_mobilenet_v1_roadsign.yml \
                        --use_vdl=true \
                        --vdl_log_dir=vdl_dir/scalar \
                        --eval

通过visualdl命令实时查看变化曲线:

visualdl --logdir vdl_dir/scalar/ --host <host_IP> --port <port_num>
2、评估
# 评估 默认使用训练过程中保存的best_model
# -c 参数表示指定使用哪个配置文件
# -o 参数表示指定配置文件中的全局变量(覆盖配置文件中的设置),需使用单卡评估

CUDA_VISIBLE_DEVICES=0 python tools/eval.py -c configs/yolov3_mobilenet_v1_roadsign.yml -o use_gpu=true
3、预测
# -c 参数表示指定使用哪个配置文件
# -o 参数表示指定配置文件中的全局变量(覆盖配置文件中的设置)
# --infer_img 参数指定预测图像路径
# 预测结束后会在output文件夹中生成一张画有预测结果的同名图像

python tools/infer.py -c configs/yolov3_mobilenet_v1_roadsign.yml -o use_gpu=true --infer_img=demo/road554.png

结果如下图:

_images/road554.png

入门使用

关于配置运行环境,请参考安装指南

训练/评估/预测

PaddleDetection提供了训练/评估/预测,支持通过不同可选参数实现特定功能

# 设置PYTHONPATH路径
export PYTHONPATH=$PYTHONPATH:.
# GPU训练 支持单卡,多卡训练,通过CUDA_VISIBLE_DEVICES指定卡号
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
python tools/train.py -c configs/faster_rcnn_r50_1x.yml
# GPU评估
export CUDA_VISIBLE_DEVICES=0
python tools/eval.py -c configs/faster_rcnn_r50_1x.yml
# 预测
python tools/infer.py -c configs/faster_rcnn_r50_1x.yml --infer_img=demo/000000570688.jpg
可选参数列表

以下列表可以通过--help查看

FLAG 支持脚本 用途 默认值 备注
-c ALL 指定配置文件 None 配置模块说明请参考配置模块
-o ALL 设置配置文件里的参数内容 None 使用-o配置相较于-c选择的配置文件具有更高的优先级。例如:-o use_gpu=False max_iter=10000
-r/--resume_checkpoint train 从某一检查点恢复训练 None -r output/faster_rcnn_r50_1x/10000
--eval train 是否边训练边测试 False
--output_eval train/eval 编辑评测保存json路径 当前路径 --output_eval ./json_result
--fp16 train 是否使用混合精度训练模式 False 需使用GPU训练
--loss_scale train 设置混合精度训练模式中损失值的缩放比例 8.0 需先开启--fp16后使用
--json_eval eval 是否通过已存在的bbox.json或者mask.json进行评估 False json文件路径在--output_eval中设置
--output_dir infer 输出预测后可视化文件 ./output --output_dir output
--draw_threshold infer 可视化时分数阈值 0.5 --draw_threshold 0.7
--infer_dir infer 用于预测的图片文件夹路径 None
--infer_img infer 用于预测的图片路径 None 相较于--infer_dir具有更高优先级
--use_vdl train/infer 是否使用VisualDL记录数据,进而在VisualDL面板中显示 False VisualDL需Python>=3.5
--vdl_log_dir train/infer 指定 VisualDL 记录数据的存储路径 train:vdl_log_dir/scalar infer: vdl_log_dir/image VisualDL需Python>=3.5

使用示例

模型训练
  • 边训练边测试

    export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
    python -u tools/train.py -c configs/faster_rcnn_r50_1x.yml --eval
    

    在训练中交替执行评估, 评估在每个snapshot_iter时开始。每次评估后还会评出最佳mAP模型保存到best_model文件夹下。

    如果验证集很大,测试将会比较耗时,建议减少评估次数,或训练完再进行评估。

  • Fine-tune其他任务

    使用预训练模型fine-tune其他任务时,可以直接加载预训练模型,形状不匹配的参数将自动忽略,例如:

    export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
    python -u tools/train.py -c configs/faster_rcnn_r50_1x.yml \
                           -o pretrain_weights=output/faster_rcnn_r50_1x/model_final \
    

    也可以显示的指定忽略参数名,可采用如下两种方式:

    1. 在YAML配置文件中设置finetune_exclude_pretrained_params
    2. 在命令行中添加-o finetune_exclude_pretrained_params对预训练模型进行选择性加载。
    export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
    python -u tools/train.py -c configs/faster_rcnn_r50_1x.yml \
                           -o pretrain_weights=output/faster_rcnn_r50_1x/model_final \
                              finetune_exclude_pretrained_params=['cls_score','bbox_pred']
    

    详细说明请参考迁移学习文档

  • 使用Paddle OP组建的YOLOv3损失函数训练YOLOv3

    为了便于用户重新设计修改YOLOv3的损失函数,我们也提供了不使用fluid.layer.yolov3_loss接口而是在python代码中使用Paddle OP的方式组建YOLOv3损失函数, 可通过如下命令用Paddle OP组建YOLOv3损失函数版本的YOLOv3模型:

    export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
    python -u tools/train.py -c configs/yolov3_darknet.yml \
                             -o use_fine_grained_loss=true
    

    Paddle OP组建YOLOv3损失函数代码位于ppdet/modeling/losses/yolo_loss.py

提示:

  • CUDA_VISIBLE_DEVICES 参数可以指定不同的GPU。例如: export CUDA_VISIBLE_DEVICES=0,1,2,3. GPU计算规则可以参考 FAQ
  • 若本地未找到数据集,将自动下载数据集并保存在~/.cache/paddle/dataset中。
  • 预训练模型自动下载并保存在〜/.cache/paddle/weights中。
  • 模型checkpoints默认保存在output中,可通过修改配置文件中save_dir进行配置。
混合精度训练

通过设置 --fp16 命令行选项可以启用混合精度训练。目前混合精度训练已经在Faster-FPN, Mask-FPN 及 Yolov3 上进行验证,几乎没有精度损失(小于0.2 mAP)。

建议使用多进程方式来进一步加速混合精度训练。示例如下。

python -m paddle.distributed.launch --selected_gpus 0,1,2,3,4,5,6,7 tools/train.py --fp16 -c configs/faster_rcnn_r50_fpn_1x.yml

如果训练过程中loss出现NaN,请尝试调节--loss_scale选项数值,细节请参看混合精度训练相关的Nvidia文档

另外,请注意将配置文件中的 norm_typeaffine_channel 改为 bn

模型评估
  • 指定权重和数据集路径

    export CUDA_VISIBLE_DEVICES=0
    python -u tools/eval.py -c configs/faster_rcnn_r50_1x.yml \
                          -o weights=https://paddlemodels.bj.bcebos.com/object_detection/faster_rcnn_r50_1x.tar \
    

    评估模型可以为本地路径,例如output/faster_rcnn_r50_1x/model_final, 也可以是MODEL_ZOO中给出的模型链接。

  • 通过json文件评估

    export CUDA_VISIBLE_DEVICES=0
    python -u tools/eval.py -c configs/faster_rcnn_r50_1x.yml \
               --json_eval \
               --output_eval evaluation/
    

    json文件必须命名为bbox.json或者mask.json,放在evaluation/目录下。

提示:

  • R-CNN和SSD模型目前暂不支持多GPU评估,将在后续版本支持
模型预测
  • 设置输出路径 && 设置预测阈值

    export CUDA_VISIBLE_DEVICES=0
    python -u tools/infer.py -c configs/faster_rcnn_r50_1x.yml \
                        --infer_img=demo/000000570688.jpg \
                        --output_dir=infer_output/ \
                        --draw_threshold=0.5 \
                        -o weights=output/faster_rcnn_r50_1x/model_final \
    

    --draw_threshold 是个可选参数. 根据 NMS 的计算, 不同阈值会产生不同的结果。如果用户需要对自定义路径的模型进行预测,可以设置-o weights指定模型路径。

    此预测过程依赖PaddleDetection源码,如果您想使用C++进行服务器端预测、或在移动端预测、或使用PaddleServing部署、或独立于PaddleDetection源码使用Python预测可以参考模型导出教程和推理部署。

如何训练自定义数据集

1.准备数据

如果数据符合COCO或VOC数据集格式,可以直接进入2.选择模型,否则需要将数据集转换至COCO格式或VOC格式。

方式一:将数据集转换为COCO格式

./tools/中提供了x2coco.py用于将voc格式数据集、labelme标注的数据集或cityscape数据集转换为COCO数据集,例如:

(1)labelmes数据转换为COCO格式:

python tools/x2coco.py \
                --dataset_type labelme \
                --json_input_dir ./labelme_annos/ \
                --image_input_dir ./labelme_imgs/ \
                --output_dir ./cocome/ \
                --train_proportion 0.8 \
                --val_proportion 0.2 \
                --test_proportion 0.0

参数说明:

  • --dataset_type:需要转换的数据格式,目前支持:’voc‘、’labelme‘和’cityscape‘
  • --json_input_dir:使用labelme标注的json文件所在文件夹
  • --image_input_dir:图像文件所在文件夹
  • --output_dir:转换后的COCO格式数据集存放位置
  • --train_proportion:标注数据中用于train的比例
  • --val_proportion:标注数据中用于validation的比例
  • --test_proportion:标注数据中用于infer的比例

(2)voc数据转换为COCO格式:

python tools/x2coco.py \
        --dataset_type voc \
        --voc_anno_dir path/to/VOCdevkit/VOC2007/Annotations/ \
        --voc_anno_list path/to/VOCdevkit/VOC2007/ImageSets/Main/trainval.txt \
        --voc_label_list dataset/voc/label_list.txt \
        --voc_out_name voc_train.json

参数说明:

  • --dataset_type:需要转换的数据格式,当前数据集是voc格式时,指定’voc‘即可。
  • --voc_anno_dir:VOC数据转换为COCO数据集时的voc数据集标注文件路径。 例如:
├──Annotations/
   ├──	009881.xml
   ├──  009882.xml
   ├──  009886.xml
   ...
  • --voc_anno_list:VOC数据转换为COCO数据集时的标注列表文件,文件中是文件名前缀列表,一般是ImageSets/Main下trainval.txt和test.txt文件。 例如:trainval.txt里的内容如下:
009881
009882
009886
...
  • --voc_label_list:VOC数据转换为COCO数据集时的类别列表文件,文件中每一行表示一种物体类别。 例如:label_list.txt里的内容如下:
background
aeroplane
bicycle
...
  • --voc_out_name:VOC数据转换为COCO数据集时的输出的COCO数据集格式json文件名。
方式二:将数据集转换为VOC格式

VOC数据集所必须的文件内容如下所示,数据集根目录需有VOCdevkit/VOC2007VOCdevkit/VOC2012文件夹,该文件夹中需有Annotations,JPEGImagesImageSets/Main三个子目录,Annotations存放图片标注的xml文件,JPEGImages存放数据集图片,ImageSets/Main存放训练trainval.txt和测试test.txt列表。

VOCdevkit
├──VOC2007(或VOC2012)
│   ├── Annotations
│       ├── xxx.xml
│   ├── JPEGImages
│       ├── xxx.jpg
│   ├── ImageSets
│       ├── Main
│           ├── trainval.txt
│           ├── test.txt

执行以下脚本,将根据ImageSets/Main目录下的trainval.txt和test.txt文件在数据集根目录生成最终的trainval.txttest.txt列表文件:

python dataset/voc/create_list.py -d path/to/dataset

参数说明:

  • -d--dataset_dir:VOC格式数据集所在文件夹路径
方式三:添加新数据源

如果数据集有新的格式需要添加进PaddleDetection中,您可自行参考数据处理文档中的添加新数据源文档部分,开发相应代码完成新的数据源支持,同时数据处理具体代码解析等可阅读数据处理文档

2.选择模型

PaddleDetection中提供了丰富的模型库,具体可在模型库中查看各个模型的指标,您可依据实际部署算力的情况,选择合适的模型:

  • 算力资源小时,推荐您使用移动端模型,PaddleDetection中的移动端模型经过迭代优化,具有较高性价比。
  • 算力资源强大时,推荐您使用服务器端模型,该模型是PaddleDetection提出的面向服务器端实用的目标检测方案。

同时也可以根据使用场景不同选择合适的模型:

同时也可以尝试PaddleDetection中开发的YOLOv3增强模型YOLOv4模型Anchor Free模型等。

3.生成Anchor

在yolo系列模型中,可以运行tools/anchor_cluster.py来得到适用于你的数据集Anchor,使用方法如下:

python tools/anchor_cluster.py -c configs/ppyolo/ppyolo.yml -n 9 -s 608 -m v2 -i 1000

目前tools/anchor_cluster.py支持的主要参数配置如下表所示:

参数 用途 默认值 备注
-c/--config 模型的配置文件 无默认值 必须指定
-n/--n 聚类的簇数 9 Anchor的数目
-s/--size 图片的输入尺寸 None 若指定,则使用指定的尺寸,如果不指定, 则尝试从配置文件中读取图片尺寸
-m/--method 使用的Anchor聚类方法 v2 目前只支持yolov2/v5的聚类算法
-i/--iters kmeans聚类算法的迭代次数 1000 kmeans算法收敛或者达到迭代次数后终止
-gi/--gen_iters 遗传算法的迭代次数 1000 该参数只用于yolov5的Anchor聚类算法
-t/--thresh Anchor尺度的阈值 0.25 该参数只用于yolov5的Anchor聚类算法

4.修改参数配置

选择好模型后,需要在configs目录中找到对应的配置文件,为了适配在自定义数据集上训练,需要对参数配置做一些修改:

  • 数据路径配置: 在yaml配置文件中,依据1.数据准备中准备好的路径,配置TrainReaderEvalReaderTestReader的路径。

    • COCO数据集:
      dataset:
         !COCODataSet
         image_dir: val2017 # 图像数据基于数据集根目录的相对路径
         anno_path: annotations/instances_val2017.json  # 标注文件基于数据集根目录的相对路径
         dataset_dir: dataset/coco  # 数据集根目录
         with_background: true  # 背景是否作为一类标签,默认为true。
    
    • VOC数据集:
      dataset:
         !VOCDataSet
         anno_path: trainval.txt   # 训练集列表文件基于数据集根目录的相对路径
         dataset_dir: dataset/voc  # 数据集根目录
         use_default_label: true   # 是否使用默认标签,默认为true。
         with_background: true  # 背景是否作为一类标签,默认为true。
    

说明: 如果您使用自己的数据集进行训练,需要将use_default_label设为false,并在数据集根目录中修改label_list.txt文件,添加自己的类别名,其中行号对应类别号。

  • 类别数修改: 如果您自己的数据集类别数和COCO/VOC的类别数不同, 需修改yaml配置文件中类别数,num_classes: XX注意:如果dataset中设置with_background: true,那么num_classes数必须是真实类别数+1(背景也算作1类)
  • 根据需要修改LearningRate相关参数:
    • 如果GPU卡数变化,依据lr,batch-size关系调整lr: 学习率调整策略
    • 自己数据总数样本数和COCO不同,依据batch_size, 总共的样本数,换算总迭代次数max_iters,以及LearningRate中的milestones(学习率变化界限)。
  • 预训练模型配置:通过在yaml配置文件中的pretrain_weights: path/to/weights参数可以配置路径,可以是链接或权重文件路径。可直接沿用配置文件中给出的在ImageNet数据集上的预训练模型。同时我们支持训练在COCO或Obj365数据集上的模型权重作为预训练模型,做迁移学习,详情可参考迁移学习文档

5.开始训练与部署

附:一个自定义数据集demo

我们以AI识虫数据集为例,对自定义数据集上训练过程进行演示,该数据集提供了2183张图片,其中训练集1693张,验证集与测试集分别有245张,共包含7种昆虫。下载链接为:数据集链接, 在AIStudio上也有很多用户公开了此数据集,您可以进行搜索并下载,如:链接1链接2等。

第一步:准备数据

由于该数据集标注文件都是xml文件,所以在准备数据步骤中选择方式二:将数据集转换为VOC格式

  • 由于该数据集中缺少已标注图片名列表文件trainval.txt和test.txt,所以需要进行生成,利用如下python脚本,在数据集根目录下执行,便可生成trainval.txttest.txt文件:

    import os
    file_train = open('trainval.txt', 'w')
    file_test = open('test.txt', 'w')
    for xml_name in os.listdir('train/annotations/xmls'):
        file_train.write(xml_name[:-4] + '\n')
    for xml_name in os.listdir('val/annotations/xmls'):
        file_test.write(xml_name[:-4] + '\n')
    file_train.close()
    file_test.close()
    
  • 模仿VOC数据集目录结构,新建VOCdevkit文件夹并进入其中,然后继续新建VOC2007文件夹并进入其中,之后新建AnnotationsJPEGImagesImageSets文件夹,最后进入ImageSets文件夹中新建Main文件夹,至此完成VOC数据集目录结构的建立。

  • 将该数据集中的train/annotations/xmlsval/annotations/xmls下的所有xml标注文件拷贝到VOCdevkit/VOC2007/Annotations中,将该数据集中的train/images/val/images/下的所有图片拷贝到VOCdevkit/VOC2007/JPEGImages中,将第一步生成的trainval.txttest.txt文件移动到VOCdevkit/VOC2007/ImageSets/Main中。

  • 最后在数据集根目录下输出最终的trainval.txttest.txt文件:

    python dataset/voc/create_list.py -d path/to/dataset
    

** 注意:** 最终的trainval.txttest.txt文件与第一步生成的两个文件不同之处在于最终的文件存储的是标注文件路径与图片路径,初始生成的文件只有已标注的图片名称。

第二步:选择模型并修改配置文件

由于昆虫比较小,属于小物体检测范畴,我们选择Faster-Rcnn系列模型。

然后基于configs/faster_rcnn_r50_fpn_1x.yml文件进行修改:

  • 修改Reader模块:为了方便模型评估需要将metric改为VOC;Reader部分已经在faster_fpn_reader.yml中定义完成,此处将要修改的内容覆写即可,如下yaml配置所示:

    ...
    metric: VOC
    ...
    _READER_: 'faster_fpn_reader.yml'
    TrainReader:
      dataset:
        !VOCDataSet
        dataset_dir: path/to/dataset
        anno_path: trainval.txt
        use_default_label: false
      batch_size: 2
    
    EvalReader:
      inputs_def:
        fields: ['image', 'im_info', 'im_id',  'im_shape', 'gt_bbox', 'gt_class', 'is_difficult']
      dataset:
        !VOCDataSet
        dataset_dir: path/to/dataset
        anno_path: test.txt
        use_default_label: false
    
    TestReader:
      dataset:
        !ImageFolder
        anno_path: path/to/dataset/label_list.txt
        use_default_label: false
    
  • 修改训练轮数与学习率等参数:

    • 根据训练集数量与总batch_size大小计算epoch数,然后将epoch数换算得到训练总轮数max_itersmilestones(学习率变化界限)也是同理。原配置文件中总batch_size=2*8=16(8卡训练),训练集数量约为12万张,max_iters=90000,所以epoch数=16x90000/120000=12。在AI识虫数据集中,训练集数量约为1700,在单卡GPU上训练,max_iters=12x1700/2=10200。同理计算milestones为: [6800, 9000]。
    • 学习率与GPU数量呈线性变换关系,如果GPU数量减半,那么学习率也将减半。由于PaddleDetection中的faster_rcnn_r50_fpn模型是在8卡GPU环境下训练得到的,所以我们要将学习率除以8:
    max_iters: 10200
    ...
    LearningRate:
    base_lr: 0.0025
    schedulers:
    - !PiecewiseDecay
      gamma: 0.1
      milestones: [6800, 9000]
    
第三步:开始训练
  • 为了使模型更快的收敛,我们使用在COCO数据集上训好的模型进行迁移学习,并且增加--eval参数,表示边训练边测试:

    export CUDA_VISIBLE_DEVICES=0
    python -u tools/train.py -c configs/faster_rcnn_r50_fpn_1x.yml \
                  -o pretrain_weights=https://paddlemodels.bj.bcebos.com/object_detection/faster_rcnn_r50_fpn_1x.tar \
                  finetune_exclude_pretrained_params=['cls_score','bbox_pred'] \
                  --eval
    
  • 在P40机器上单卡训练40分钟左右就可完成训练,最终的mAP(0.50, 11point)=71.60,如果想让模型收敛的更好,可以继续增大max_iters,训练2x、3x等模型,但并不是意味着训练轮数越多效果越好,要防止过拟合的出现。

训完之后,可以任意挑选一张测试集图片进行测试,输出的结果图片会默认保存在output目录中:

python -u tools/infer.py -c configs/faster_rcnn_r50_fpn_1x.yml \
              --infer_img=path/to/dataset/2572.jpeg
  • 模型部署:

    • 首先需要先将模型导出成可预测模型:
    python -u tools/export_model.py -c configs/faster_rcnn_r50_fpn_1x.yml \
                  --output_dir=./inference_model
    
    • 然后我们使用python端进行预测:
    python deploy/python/infer.py --model_dir=./inference_model/faster_rcnn_r50_fpn_1x \
                  --image_file=path/to/dataset/2572.jpeg \
                  --use_gpu=True
    

预测结果如下图所示: _images/2572.jpeg

如仍有疑惑,欢迎给我们提issue。

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

进阶使用教程

推理部署教程

模型导出

训练得到一个满足要求的模型后,如果想要将该模型接入到C++预测库或者Serving服务,需要通过tools/export_model.py导出该模型。同时,会导出预测时使用的配置文件,路径与模型保存路径相同, 配置文件名为infer_cfg.yml

说明:

  • 输入部分: 导出模型输入为网络输入图像,即原始图片经过预处理后的图像,具体预处理方式可参考配置文件中TestReader部分。各类检测模型的输入格式分别为:
模型系列名称 输入图像预处理方式 其他输入信息
YOLO 缩放至指定大小,归一化 im_size: 格式为[origin_H, origin_W], origin为原始图像
SSD 缩放至指定大小,归一化 im_shape: 格式为[origin_H, origin_W], origin为原始图像
RCNN 归一化,等比例缩放 1. im_info: 格式为[input_H, input_W, scale],input为输入图像,scale为输入图像大小/原始图像大小
2. im_shape:格式为[origin_H, origin_W, 1.], origin为原始图像
RCNN+FPN 归一化,等比例缩放,对图像填充0使得长宽均为32的倍数 1. im_info: 格式为[input_H, input_W, scale],input为输入图像,scale为输入图像大小/原始图像大小
2. im_shape:格式为[origin_H, origin_W, 1.], origin为原始图像
RetinaNet 归一化,等比例缩放,对图像填充0使得长宽均为128的倍数 1. im_info: 格式为[input_H, input_W, scale],input为输入图像,scale为输入图像大小/原始图像大小
2. im_shape:格式为[origin_H, origin_W, 1.], origin为原始图像
Face 归一化 im_shape: 格式为[origin_H, origin_W], origin为原始图像
  • 输出部分: 导出模型输出统一为NMS的输出,形状为[N, 6], 其中N为预测框的个数,6为[class_id, score, x1, y1, x2, y2]。
  • 模型导出不支持模型结构中包含fluid.layers.py_func的情况。
启动参数说明
FLAG 用途 默认值 备注
-c 指定配置文件 None
--output_dir 模型保存路径 ./output 模型默认保存在output/配置文件名/路径下
使用示例

使用训练/评估/推断中训练得到的模型进行试用,脚本如下

# 导出FasterRCNN模型, 模型中data层默认的shape为3x800x1333
python tools/export_model.py -c configs/faster_rcnn_r50_1x.yml \
        --output_dir=./inference_model \
        -o weights=output/faster_rcnn_r50_1x/model_final

预测模型会导出到inference_model/faster_rcnn_r50_1x目录下,模型名和参数名分别为__model____params__

设置导出模型的输入大小

使用Fluid-TensorRT进行预测时,由于<=TensorRT 5.1的版本仅支持定长输入,保存模型的data层的图片大小需要和实际输入图片大小一致。而Fluid C++预测引擎没有此限制。设置TestReader中的image_shape可以修改保存模型中的输入图片大小。示例如下:

# 导出FasterRCNN模型,输入是3x640x640
python tools/export_model.py -c configs/faster_rcnn_r50_1x.yml \
        --output_dir=./inference_model \
        -o weights=https://paddlemodels.bj.bcebos.com/object_detection/faster_rcnn_r50_1x.tar \
           TestReader.inputs_def.image_shape=[3,640,640]

# 导出YOLOv3模型,输入是3x320x320
python tools/export_model.py -c configs/yolov3_darknet.yml \
        --output_dir=./inference_model \
        -o weights=https://paddlemodels.bj.bcebos.com/object_detection/yolov3_darknet.tar \
           TestReader.inputs_def.image_shape=[3,320,320]

# 导出SSD模型,输入是3x300x300
python tools/export_model.py -c configs/ssd/ssd_mobilenet_v1_voc.yml \
        --output_dir=./inference_model \
        -o weights=https://paddlemodels.bj.bcebos.com/object_detection/ssd_mobilenet_v1_voc.tar \
           TestReader.inputs_def.image_shape=[3,300,300]
Paddle Serving部署模型导出

如果您要将上述模型用于Paddle Serving在线预估服务,操作如下

# 导出Serving模型需要安装paddle-serving-client
pip install paddle-serving-client
# 导出FasterRCNN模型, 模型中data层默认的shape为3x800x1333
python tools/export_serving_model.py -c configs/faster_rcnn_r50_1x.yml \
        --output_dir=./inference_model \
        -o weights=output/faster_rcnn_r50_1x/model_final

用于Serving的预测模型会导出到inference_model/faster_rcnn_r50_1x目录下,其中serving_client为客户端配置文件夹,serving_server为服务端配置文件夹,模型参数也在服务端配置文件夹中。

更多的信息详情参见 使用Paddle Serving部署Faster RCNN模型

Python端预测部署

Python预测可以使用tools/infer.py,此种方式依赖PaddleDetection源码;也可以使用本篇教程预测方式,先将模型导出,使用一个独立的文件进行预测。

本篇教程使用AnalysisPredictor对导出模型进行高性能预测。

在PaddlePaddle中预测引擎和训练引擎底层有着不同的优化方法, 下面列出了两种不同的预测方式。Executor同时支持训练和预测,AnalysisPredictor则专门针对推理进行了优化,是基于C++预测库的Python接口,该引擎可以对模型进行多项图优化,减少不必要的内存拷贝。如果用户在部署已训练模型的过程中对性能有较高的要求,我们提供了独立于PaddleDetection的预测脚本,方便用户直接集成部署。

主要包含两个步骤:

  • 导出预测模型
  • 基于Python的预测
1. 导出预测模型

PaddleDetection在训练过程包括网络的前向和优化器相关参数,而在部署过程中,我们只需要前向参数,具体参考:导出模型

导出后目录下,包括__model____params__infer_cfg.yml三个文件。

2. 基于python的预测
2.1 安装依赖
  • PaddlePaddle的安装: 请点击官方安装文档 选择适合的方式,版本为1.7以上即可
  • 切换到PaddleDetection代码库根目录,执行pip install -r requirements.txt安装其它依赖
2.2 执行预测程序

在终端输入以下命令进行预测:

python deploy/python/infer.py --model_dir=/path/to/models --image_file=/path/to/image
--use_gpu=(False/True)

参数说明如下:

参数 是否必须 含义
--model_dir Yes 上述导出的模型路径
--image_file Option 需要预测的图片
--video_file Option 需要预测的视频
--camera_id Option 用来预测的摄像头ID,默认为-1(表示不使用摄像头预测,可设置为:0 - (摄像头数目-1) ),预测过程中在可视化界面按q退出输出预测结果到:output/output.mp4
--use_gpu No 是否GPU,默认为False
--run_mode No 使用GPU时,默认为fluid, 可选(fluid/trt_fp32/trt_fp16)
--threshold No 预测得分的阈值,默认为0.5
--output_dir No 可视化结果保存的根目录,默认为output/
--run_benchmark No 是否运行benchmark,同时需指定--image_file

说明:

  • run_mode:fluid代表使用AnalysisPredictor,精度float32来推理,其他参数指用AnalysisPredictor,TensorRT不同精度来推理。
  • PaddlePaddle默认的GPU安装包(<=1.7),不支持基于TensorRT进行预测,如果想基于TensorRT加速预测,需要自行编译,详细可参考预测库编译教程
3. 部署性能对比测试

对比AnalysisPredictor相对Executor的推理速度

3.1 测试环境:
  • CUDA 9.0
  • CUDNN 7.5
  • PaddlePaddle 1.71
  • GPU: Tesla P40
3.2 测试方式:
  • Batch Size=1
  • 去掉前100轮warmup时间,测试100轮的平均时间,单位ms/image,只计算模型运行时间,不包括数据的处理和拷贝。
3.3 测试结果
模型 AnalysisPredictor Executor 输入
YOLOv3-MobileNetv1 15.20 19.54 608*608
faster_rcnn_r50_fpn_1x 50.05 69.58 800*1088
faster_rcnn_r50_1x 326.11 347.22 800*1067
mask_rcnn_r50_fpn_1x 67.49 91.02 800*1088
mask_rcnn_r50_1x 326.11 350.94 800*1067

C++端预测部署

1.说明

本目录为用户提供一个跨平台的C++部署方案,让用户通过PaddleDetection训练的模型导出后,即可基于本项目快速运行,也可以快速集成代码结合到自己的项目实际应用中去。

主要设计的目标包括以下四点:

  • 跨平台,支持在 WindowsLinux 完成编译、二次开发集成和部署运行
  • 可扩展性,支持用户针对新模型开发自己特殊的数据预处理等逻辑
  • 高性能,除了PaddlePaddle自身带来的性能优势,我们还针对图像检测的特点对关键步骤进行了性能优化
  • 支持各种不同检测模型结构,包括Yolov3/Faster_RCNN/SSD/RetinaNet
2.主要目录和文件
deploy/cpp
|
├── src
│   ├── main.cc # 集成代码示例, 程序入口
│   ├── object_detector.cc # 模型加载和预测主要逻辑封装类实现
│   └── preprocess_op.cc # 预处理相关主要逻辑封装实现
|
├── include
│   ├── config_parser.h # 导出模型配置yaml文件解析
│   ├── object_detector.h # 模型加载和预测主要逻辑封装类
│   └── preprocess_op.h # 预处理相关主要逻辑类封装
|
├── docs
│   ├── linux_build.md # Linux 编译指南
│   └── windows_vs2019_build.md # Windows VS2019编译指南
│
├── build.sh # 编译命令脚本
│
├── CMakeList.txt # cmake编译入口文件
|
├── CMakeSettings.json # Visual Studio 2019 CMake项目编译设置
│
└── cmake # 依赖的外部项目cmake(目前仅有yaml-cpp)
3.编译部署
3.1 导出模型

请确认您已经基于PaddleDetectionexport_model.py导出您的模型,并妥善保存到合适的位置。导出模型细节请参考 导出模型教程

模型导出后, 目录结构如下(以yolov3_darknet为例):

yolov3_darknet # 模型目录
├── infer_cfg.yml # 模型配置信息
├── __model__     # 模型文件
└── __params__    # 参数文件

预测时,该目录所在的路径会作为程序的输入参数。

3.2 编译

仅支持在WindowsLinux平台编译和使用

推理Benchmark

环境准备
  • 测试环境:
    • CUDA 9.0
    • CUDNN 7.5
    • TensorRT-5.1.2.2
    • PaddlePaddle v1.6
    • GPU分别为: Tesla V100和Tesla P4
  • 测试方式:
    • 为了方便比较不同模型的推理速度,输入采用同样大小的图片,为 3x640x640,采用 demo/000000014439_640x640.jpg 图片。
    • Batch Size=1
    • 去掉前10轮warmup时间,测试100轮的平均时间,单位ms/image,包括输入数据拷贝至GPU的时间、计算时间、数据拷贝至CPU的时间。
    • 采用Fluid C++预测引擎: 包含Fluid C++预测、Fluid-TensorRT预测,下面同时测试了Float32 (FP32) 和Float16 (FP16)的推理速度。
    • 测试时开启了 FLAGS_cudnn_exhaustive_search=True,使用exhaustive方式搜索卷积计算算法。
推理速度
模型 Tesla V100 Fluid (ms/image) Tesla V100 Fluid-TensorRT-FP32 (ms/image) Tesla V100 Fluid-TensorRT-FP16 (ms/image) Tesla P4 Fluid (ms/image) Tesla P4 Fluid-TensorRT-FP32 (ms/image)
faster_rcnn_r50_1x 147.488 146.124 142.416 471.547 471.631
faster_rcnn_r50_2x 147.636 147.73 141.664 471.548 472.86
faster_rcnn_r50_vd_1x 146.588 144.767 141.208 459.357 457.852
faster_rcnn_r50_fpn_1x 25.11 24.758 20.744 59.411 57.585
faster_rcnn_r50_fpn_2x 25.351 24.505 20.509 59.594 57.591
faster_rcnn_r50_vd_fpn_2x 25.514 25.292 21.097 61.026 58.377
faster_rcnn_r50_fpn_gn_2x 36.959 36.173 32.356 101.339 101.212
faster_rcnn_dcn_r50_fpn_1x 28.707 28.162 27.503 68.154 67.443
faster_rcnn_dcn_r50_vd_fpn_2x 28.576 28.271 27.512 68.959 68.448
faster_rcnn_r101_1x 153.267 150.985 144.849 490.104 486.836
faster_rcnn_r101_fpn_1x 30.949 30.331 24.021 73.591 69.736
faster_rcnn_r101_fpn_2x 30.918 29.126 23.677 73.563 70.32
faster_rcnn_r101_vd_fpn_1x 31.144 30.202 23.57 74.767 70.773
faster_rcnn_r101_vd_fpn_2x 30.678 29.969 23.327 74.882 70.842
faster_rcnn_x101_vd_64x4d_fpn_1x 60.36 58.461 45.172 132.178 131.734
faster_rcnn_x101_vd_64x4d_fpn_2x 59.003 59.163 46.065 131.422 132.186
faster_rcnn_dcn_r101_vd_fpn_1x 36.862 37.205 36.539 93.273 92.616
faster_rcnn_dcn_x101_vd_64x4d_fpn_1x 78.476 78.335 77.559 185.976 185.996
faster_rcnn_se154_vd_fpn_s1x 166.282 90.508 80.738 304.653 193.234
mask_rcnn_r50_1x 160.185 160.4 160.322 - -
mask_rcnn_r50_2x 159.821 159.527 160.41 - -
mask_rcnn_r50_fpn_1x 95.72 95.719 92.455 259.8 258.04
mask_rcnn_r50_fpn_2x 84.545 83.567 79.269 227.284 222.975
mask_rcnn_r50_vd_fpn_2x 82.07 82.442 77.187 223.75 221.683
mask_rcnn_r50_fpn_gn_2x 94.936 94.611 91.42 265.468 263.76
mask_rcnn_dcn_r50_fpn_1x 97.828 97.433 93.76 256.295 258.056
mask_rcnn_dcn_r50_vd_fpn_2x 77.831 79.453 76.983 205.469 204.499
mask_rcnn_r101_fpn_1x 95.543 97.929 90.314 252.997 250.782
mask_rcnn_r101_vd_fpn_1x 98.046 97.647 90.272 261.286 262.108
mask_rcnn_x101_vd_64x4d_fpn_1x 115.461 115.756 102.04 296.066 293.62
mask_rcnn_x101_vd_64x4d_fpn_2x 107.144 107.29 97.275 267.636 267.577
mask_rcnn_dcn_r101_vd_fpn_1x 85.504 84.875 84.907 225.202 226.585
mask_rcnn_dcn_x101_vd_64x4d_fpn_1x 129.937 129.934 127.804 326.786 326.161
mask_rcnn_se154_vd_fpn_s1x 214.188 139.807 121.516 440.391 439.727
cascade_rcnn_r50_fpn_1x 36.866 36.949 36.637 101.851 101.912
cascade_mask_rcnn_r50_fpn_1x 110.344 106.412 100.367 301.703 297.739
cascade_rcnn_dcn_r50_fpn_1x 40.412 39.58 39.853 110.346 110.077
cascade_mask_rcnn_r50_fpn_gn_2x 170.092 168.758 163.298 527.998 529.59
cascade_rcnn_dcn_r101_vd_fpn_1x 48.414 48.849 48.701 134.9 134.846
cascade_rcnn_dcn_x101_vd_64x4d_fpn_1x 90.062 90.218 90.009 228.67 228.396
retinanet_r101_fpn_1x 55.59 54.636 48.489 90.394 83.951
retinanet_r50_fpn_1x 50.048 47.932 44.385 73.819 70.282
retinanet_x101_vd_64x4d_fpn_1x 83.329 83.446 70.76 145.936 146.168
yolov3_darknet 21.427 20.252 13.856 55.173 55.692
yolov3_darknet_voc 17.58 16.241 9.473 51.049 51.249
yolov3_mobilenet_v1 12.869 11.834 9.408 24.887 21.352
yolov3_mobilenet_v1_voc 9.118 8.146 5.575 20.787 17.169
yolov3_r34 14.914 14.125 11.176 20.798 20.822
yolov3_r34_voc 11.288 10.73 7.7 25.874 22.399
ssd_mobilenet_v1_voc 5.763 5.854 4.589 11.75 9.485
ssd_vgg16_300 28.722 29.644 20.399 73.707 74.531
ssd_vgg16_300_voc 18.425 19.288 11.298 56.297 56.201
ssd_vgg16_512 27.471 28.328 19.328 68.685 69.808
ssd_vgg16_512_voc 18.721 19.636 12.004 54.688 56.174
  1. RCNN系列模型Fluid-TensorRT速度相比Fluid预测没有优势,原因是: TensorRT仅支持定长输入,当前基于ResNet系列的RCNN模型,只有backbone部分采用了TensorRT子图计算,比较耗时的stage-5没有基于TensorRT计算。 Fluid对CNN模型也做了一系列的融合优化。后续TensorRT版本升级、或有其他优化策略时再更新数据。
  2. YOLO v3系列模型,Fluid-TensorRT相比Fluid预测加速5% - 10%不等。
  3. SSD和YOLOv3系列模型 TensorRT-FP16预测速度有一定的优势,加速约20% - 40%不等。具体如下图。

_images/bench_ssd_yolo_infer.png

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

模型参数配置教程

配置模块设计与介绍

简介

为了使配置过程更加自动化并减少配置错误,PaddleDetection的配置管理采取了较为严谨的设计。

设计思想

目前主流框架全局配置基本是一个Python dict,这种设计对配置的检查并不严格,拼写错误或者遗漏的配置项往往会造成训练过程中的严重错误,进而造成时间及资源的浪费。为了避免这些陷阱,从自动化和静态分析的原则出发,PaddleDetection采用了一种用户友好、 易于维护和扩展的配置设计。

基本设计

利用Python的反射机制,PaddleDection的配置系统从Python类的构造函数抽取多种信息 - 如参数名、初始值、参数注释、数据类型(如果给出type hint)- 来作为配置规则。 这种设计便于设计的模块化,提升可测试性及扩展性。

API

配置系统的大多数功能由 ppdet.core.workspace 模块提供

  • register: 装饰器,将类注册为可配置模块;能够识别类定义中的一些特殊标注。
    • __category__: 为便于组织,模块可以分为不同类别。
    • __inject__: 如果模块由多个子模块组成,可以这些子模块实例作为构造函数的参数注入。对应的默认值及配置项可以是类名字符串,yaml序列化的对象,指向序列化对象的配置键值或者Python dict(构造函数需要对其作出处理,参见下面的例子)。
    • __op__: 配合 __append_doc__ (抽取目标OP的 注释)使用,可以方便快速的封装PaddlePaddle底层OP。
  • serializable: 装饰器,利用 pyyaml 的序列化机制,可以直接将一个类实例序列化及反序列化。
  • create: 根据全局配置构造一个模块实例。
  • load_config and merge_config: 加载yaml文件,合并命令行提供的配置项。
示例

RPNHead 模块为例,该模块包含多个PaddlePaddle OP,先将这些OP封装成类,并将其实例在构造 RPNHead 时注入。

# excerpt from `ppdet/modeling/ops.py`
from ppdet.core.workspace import register, serializable

# ... more operators

@register
@serializable
class GenerateProposals(object):
    # NOTE this class simply wraps a PaddlePaddle operator
    __op__ = fluid.layers.generate_proposals
    # NOTE docstring for args are extracted from PaddlePaddle OP
    __append_doc__ = True

    def __init__(self,
                 pre_nms_top_n=6000,
                 post_nms_top_n=1000,
                 nms_thresh=.5,
                 min_size=.1,
                 eta=1.):
        super(GenerateProposals, self).__init__()
        self.pre_nms_top_n = pre_nms_top_n
        self.post_nms_top_n = post_nms_top_n
        self.nms_thresh = nms_thresh
        self.min_size = min_size
        self.eta = eta

# ... more operators

# excerpt from `ppdet/modeling/anchor_heads/rpn_head.py`
from ppdet.core.workspace import register
from ppdet.modeling.ops import AnchorGenerator, RPNTargetAssign, GenerateProposals

@register
class RPNHead(object):
    """
    RPN Head

    Args:
        anchor_generator (object): `AnchorGenerator` instance
        rpn_target_assign (object): `RPNTargetAssign` instance
        train_proposal (object): `GenerateProposals` instance for training
        test_proposal (object): `GenerateProposals` instance for testing
    """
    __inject__ = [
        'anchor_generator', 'rpn_target_assign', 'train_proposal',
        'test_proposal'
    ]

    def __init__(self,
                 anchor_generator=AnchorGenerator().__dict__,
                 rpn_target_assign=RPNTargetAssign().__dict__,
                 train_proposal=GenerateProposals(12000, 2000).__dict__,
                 test_proposal=GenerateProposals().__dict__):
        super(RPNHead, self).__init__()
        self.anchor_generator = anchor_generator
        self.rpn_target_assign = rpn_target_assign
        self.train_proposal = train_proposal
        self.test_proposal = test_proposal
        if isinstance(anchor_generator, dict):
            self.anchor_generator = AnchorGenerator(**anchor_generator)
        if isinstance(rpn_target_assign, dict):
            self.rpn_target_assign = RPNTargetAssign(**rpn_target_assign)
        if isinstance(train_proposal, dict):
            self.train_proposal = GenerateProposals(**train_proposal)
        if isinstance(test_proposal, dict):
            self.test_proposal = GenerateProposals(**test_proposal)

对应的yaml配置如下,请注意这里给出的是 完整 配置,其中所有默认值配置项都可以省略。上面的例子中的模块所有的构造函数参数都提供了默认值,因此配置文件中可以完全略过其配置。

RPNHead:
  test_proposal:
    eta: 1.0
    min_size: 0.1
    nms_thresh: 0.5
    post_nms_top_n: 1000
    pre_nms_top_n: 6000
  train_proposal:
    eta: 1.0
    min_size: 0.1
    nms_thresh: 0.5
    post_nms_top_n: 2000
    pre_nms_top_n: 12000
  anchor_generator:
    # ...
  rpn_target_assign:
    # ...

RPNHead 模块实际使用代码示例。

from ppdet.core.workspace import load_config, merge_config, create

load_config('some_config_file.yml')
merge_config(more_config_options_from_command_line)

rpn_head = create('RPNHead')
# ... code that use the created module!

配置文件用可以直接序列化模块实例,用 ! 标示,如

LearningRate:
  base_lr: 0.01
  schedulers:
  - !PiecewiseDecay
    gamma: 0.1
    milestones: [60000, 80000]
  - !LinearWarmup
    start_factor: 0.3333333333333333
    steps: 500
安装依赖

配置系统用到两个Python包,均为可选安装。

如需安装,运行下面命令即可。

pip install typeguard http://github.com/willthefrog/docstring_parser/tarball/master
相关工具

为了方便用户配置,PaddleDection提供了一个工具 (tools/configure.py), 共支持四个子命令:

  1. list: 列出当前已注册的模块,如需列出具体类别的模块,可以使用 --category 指定。

  2. help: 显示指定模块的帮助信息,如描述,配置项,配置文件模板及命令行示例。

  3. analyze: 检查配置文件中的缺少或者多余的配置项以及依赖缺失,如果给出type hint, 还可以检查配置项中错误的数据类型。非默认配置也会高亮显示。

  4. generate: 根据给出的模块列表生成配置文件,默认生成完整配置,如果指定 --minimal ,生成最小配置,即省略所有默认配置项。例如,执行下列命令可以生成Faster R-CNN (ResNet backbone + FPN) 架构的配置文件:

    python tools/configure.py generate FasterRCNN ResNet RPNHead RoIAlign BBoxAssigner BBoxHead LearningRate OptimizerBuilder
    

    如需最小配置,运行:

    python tools/configure.py generate --minimal FasterRCNN BBoxHead
    

RCNN系列模型参数配置教程

标签: 模型参数配置


#####################################基础配置#####################################

# 检测模型的名称
architecture: MaskRCNN
# 默认使用GPU运行,设为False时使用CPU运行
use_gpu: true
# 最大迭代次数,而一个iter会运行batch_size * device_num张图片
# 一般batch_size为1时,1x迭代18万次,2x迭代36万次
max_iters: 180000
# 模型保存间隔,如果训练时eval设置为True,会在保存后进行验证
snapshot_iter: 10000
# 输出指定区间的平均结果,默认20,即输出20次的平均结果。也是默认打印log的间隔。
log_iter: 20
# 训练权重的保存路径
save_dir: output
# 模型的预训练权重,默认是从指定url下载
pretrain_weights: https://paddle-imagenet-models-name.bj.bcebos.com/ResNet50_cos_pretrained.tar
# 验证模型的评测标准,可以选择COCO或者VOC
metric: COCO
# 用于模型验证或测试的训练好的权重
weights: output/mask_rcnn_r50_fpn_1x/model_final/
# 用于训练或验证的数据集的类别数目
# **其中包含背景类,即81=80 + 1(背景类)**
num_classes: 81

#####################################模型配置#####################################

# Mask RCNN元结构,包括了以下主要组件, 具体细节可以参考[论文]( https://arxiv.org/abs/1703.06870)
MaskRCNN:
  backbone: ResNet
  fpn: FPN
  rpn_head: FPNRPNHead
  roi_extractor: FPNRoIAlign
  bbox_assigner: BBoxAssigner
  bbox_head: BBoxHead
  mask_assigner: MaskAssigner
  mask_head: MaskHead
  rpn_only: false

# 主干网络
ResNet:
  # 配置在哪些阶段加入可变性卷积,默认不添加
  dcn_v2_stages: []
  # ResNet深度,默认50
  depth: 50
  # 主干网络返回的主要阶段特征用于FPN作进一步的特征融合
  # 默认从[2,3,4,5]返回特征
  feature_maps: [2,3,4,5]
  # 是否在训练中固定某些权重,默认从第2阶段开始固定,即resnet的stage 1
  freeze_at: 2
  # 是否停止norm layer的梯度回传,默认是
  freeze_norm: true
  # norm layer的权重衰退值
  norm_decay: 0.0
  # norm layer的类型, 可以选择bn/sync_bn/affine_channel, 默认为affine_channel
  norm_type: affine_channel
  # ResNet模型的类型, 分为'a', 'b', 'c', 'd'四种, 默认使用'b'类型
  variant: b

# FPN多特征融合
FPN:
  # FPN使用的最高层特征后是否添加额外conv,默认false
  has_extra_convs: false
  # FPN使用主干网络最高层特征,默认是resnet第5阶段后添加额外卷积操作变<成了FPN的第6个,总共有5个阶段
  max_level: 6
  # FPN使用主干网络最低层特征,默认是resnet第2阶段的输出
  min_level: 2
  # FPN中使用Norm类型, bn/sync_bn/affine_channel/null, 默认不用null
  norm_type: null
  # FPN输出特征的通道数量, 默认是256
  num_chan: 256
  # 特征图缩放比例, 默认是[0.03125, 0.0625, 0.125, 0.25]
  spatial_scale: [0.03125, 0.0625, 0.125, 0.25]

# 检测第一阶段RPN
FPNRPNHead:
  # FPN第一层特征生成anchor时,默认anchor尺寸32
  anchor_start_size: 32
  # RPNHead默认进行前背景二分类
  num_classes: 1
  # 根据特征图尺寸,在特征图的每个位置生成N个大小、长宽比各不同anchor
  # N = anchor_sizes * aspect_ratios
  # 具体实现参考[API](fluid.layers.anchor_generator)
  anchor_generator:
    aspect_ratios: [0.5, 1.0, 2.0]
    variance: [1.0, 1.0, 1.0, 1.0]
  # 首先计算Anchor和GT BBox之间的IoU,为每个Anchor匹配上GT,
  # 然后根据阈值过滤掉IoU低的Anchor,得到最终的Anchor及其GT进行loss计算
  # 具体实现参考[API](fluid.layers.rpn_target_assign)
  rpn_target_assign:
    rpn_batch_size_per_im: 256
    rpn_fg_fraction: 0.5
    rpn_negative_overlap: 0.3
    rpn_positive_overlap: 0.7
    rpn_straddle_thresh: 0.0
  # 首先取topk个分类分数高的anchor
  # 然后通过NMS对这topk个anchor进行重叠度检测,对重叠高的两个anchor只保留得分高的
  # 训练和测试阶段主要区别在最后NMS保留的Anchor数目
  # 训练时输出2000个proposals,推理时输出1000个proposals
  # 具体实现参考[API](fluid.layers.generate_proposals)
  train_proposal:
    min_size: 0.0
    nms_thresh: 0.7
    post_nms_top_n: 2000
    pre_nms_top_n: 2000
  test_proposal:
    min_size: 0.0
    nms_thresh: 0.7
    post_nms_top_n: 1000
    pre_nms_top_n: 1000

# 对FPN每层执行RoIAlign后,然后合并输出结果,用于BBox Head计算
FPNRoIAlign:
  # 用于抽取特征特征的FPN的层数,默认为4
  canconical_level: 4
  # 用于抽取特征特征的FPN的特征图尺寸,默认为224
  canonical_size: 224
  # 用于抽取特征特征的最高层FPN,默认是2
  max_level: 5
  # 用于抽取特征特征的最底层FPN,默认是2
  min_level: 2
  #roi extractor的采样率,默认为2
  sampling_ratio: 2
  # 输出bbox的特征图尺寸,默认为7
  box_resolution: 7
  # 输出mask的特征图尺寸,默认为14
  mask_resolution: 14

# 输出实例掩码的Head
MaskHead:
  # 卷积的数量,FPN是4,其他为0,默认为0
  num_convs: 4
  # mask head输出的特征图尺寸,默认14
  resolution: 28
  # 空洞率,默认为1
  dilation: 1
  # 第一个卷积后输出的特征图通道数, 默认为256
  num_chan_reduced: 256
  # 输出的mask的类别,默认为81
  num_classes: 81

# 求rpn生成的roi跟gt bbox之间的iou,然后根据阈值进行过滤,保留一定数量的roi
# 再根据gt bbox的标签,对roi进行标签赋值,即得到每个roi的类别
# 具体实现参考[API](fluid.layers.generate_proposal_labels)
BBoxAssigner:
  batch_size_per_im: 512
  bbox_reg_weights: [0.1, 0.1, 0.2, 0.2]
  bg_thresh_lo: 0.0
  bg_thresh_hi: 0.5
  fg_fraction: 0.25
  fg_thresh: 0.5

# 根据roi的label,选择前景,为其赋值mask label
# 具体实现参考[API](fluid.layers.generate_mask_labels)
MaskAssigner:
  resolution: 28
  num_classes: 81

# 输出检测框的Head
BBoxHead:
  # 在roi extractor和bbox head之间,插入两层FC,对特征做进一步学习
  head: TwoFCHead
  # 通过NMS进行bbox过滤
  # 具体实现参考[API](fluid.layers.multiclass_nms)
  nms:
    keep_top_k: 100
    nms_threshold: 0.5
    score_threshold: 0.05

# 输出检测框之前,对特征进一步学习
TwoFCHead:
  # FC输出的特征图通道数,默认是1024
  num_chan: 1024

#####################################训练配置#####################################

# 学习率配置
LearningRate:
  # 初始学习率, 一般情况下8卡gpu,batch size为2时设置为0.02
  # 可以根据具体情况,按比例调整
  # 比如说4卡V100,bs=2时,设置为0.01
  base_lr: 0.01
  # 学习率规划器
  # 具体实现参考[API](fluid.layers.piecewise_decay)
  schedulers:
    # 学习率衰减策略
    # 对于coco数据集,1个epoch大概需要7000个iter
    # if step < 120000:
    #    learning_rate = 0.1
    # elif 120000 <= step < 160000:
    #    learning_rate = 0.1 * 0.1
    # else:
    #    learning_rate = 0.1 * (0.1)**2
    - !PiecewiseDecay
      gamma: 0.1
      milestones: [120000, 160000]
    # 在训练开始时,调低学习率为base_lr * start_factor,然后逐步增长到base_lr,这个过程叫学习率热身,按照以下公式更新学习率
    # linear_step = end_lr - start_lr
    # lr = start_lr + linear_step * (global_step / warmup_steps)
    # 具体实现参考[API](fluid.layers.linear_lr_warmup)
    - !LinearWarmup
      start_factor: 0.3333333333333333
      steps: 500

OptimizerBuilder:
  # 默认使用SGD+Momentum进行训练
  # 具体实现参考[API](fluid.optimizer)
  optimizer:
    momentum: 0.9
    type: Momentum
  # 默认使用L2权重衰减正则化
  # 具体实现参考[API](fluid.regularizer)
  regularizer:
    factor: 0.0001
    type: L2

#####################################数据配置#####################################

# 模型训练集设置参考
# 训练、验证、测试使用的数据配置主要区别在数据路径、模型输入、数据增强参数设置
TrainReader:
  # 训练过程中模型的相关输入
  # 包括图片,图片长宽高等基本信息,图片id,标记的目标框、实例标签、实例分割掩码
  inputs_def:
    fields: ['image', 'im_info', 'im_id', 'gt_bbox', 'gt_class', 'is_crowd', 'gt_mask']
  # VOC数据集对应的输入,注意选择VOC时,也要对应修改metric: VOC
- # fields: ['image', 'im_info', 'im_id', 'gt_bbox', 'gt_class', 'is_difficult']
  # 数据集目录配置
  dataset:
    # 指定数据集名称,可以选择VOCDataSet, COCODataSet
    !COCODataSet
    # 训练图片所在目录
    image_dir: train2017
    # 标记文件所在目录
    anno_path: annotations/instances_train2017.json
    # 数据集根目录
    dataset_dir: dataset/coco
  # 对一个batch中的单张图片做的数据增强
  sample_transforms:
  # 读取Image图像为numpy数组
  # 可以选择将图片从BGR转到RGB,可以选择对一个batch中的图片做mixup增强
  - !DecodeImage
    to_rgb: true
  # 对图片进行随机翻转
  # 可以选择同步翻转mask,可以选择归一化bbox的坐标
  - !RandomFlipImage
    prob: 0.5
  # 归一化图片,默认均值[0.485, 0.456, 0.406],方差[1, 1, 1]
  # 可以选择将归一化结果除以255,可以选择图片的数据格式
  - !NormalizeImage
    is_channel_first: false
    is_scale: true
    mean: [0.485,0.456,0.406]
    std: [0.229, 0.224,0.225]
  # 调整图片尺寸,默认采用cv2的线性插值
  - !ResizeImage
    target_size: 800
    max_size: 1333
    interp: 1
    use_cv2: true
  # 调整图片数据格式,默认使用CHW
  - !Permute
    to_bgr: false
    channel_first: true
  # 对一个batch中的图片统一做的数据增强
  batch_transforms:
  # 将一个batch中的图片,按照最大的尺寸,做补齐
  - !PadBatch
    pad_to_stride: 32
    # 选择是否使用padding之后的image信息,默认为false
    use_padded_im_info: false
  # 1个GPU的batch size,默认为1
  batch_size: 1
  # 选择是否打乱所有样本的顺序
  shuffle: true
  # 使用多进程/线程的数目,默认为2
  worker_num: 2
  # 选择是否使用多进程,默认为false
  use_process: false
  # 如果最后一个batch的图片数量为奇数,选择是否丢掉这个batch,不进行训练,默认是不丢掉的
  drop_last: false
  # 使用数据集中的样本数目,默认是-1,表示使用全部
  samples: -1

  # 模型验证集设置参考
  EvalReader:
  # 验证过程中模型的相关输入
  # 包括图片,图片长宽高等基本信息,图片id,图片shape
  inputs_def:
    fields: ['image', 'im_info', 'im_id', 'im_shape']
  dataset:
    !COCODataSet
    image_dir: val2017
    anno_path: annotations/instances_val2017.json
    dataset_dir: dataset/coco
  sample_transforms:
  - !DecodeImage
    to_rgb: true
  - !NormalizeImage
    is_channel_first: false
    is_scale: true
    mean: [0.485,0.456,0.406]
    std: [0.229, 0.224,0.225]
  - !ResizeImage
    interp: 1
    max_size: 1333
    target_size: 800
    use_cv2: true
  - !Permute
    channel_first: true
    to_bgr: false
  batch_size: 1
  shuffle: false
  drop_last: false
  drop_empty: false
  worker_num: 2

# 测试验证集设置参考
TestReader:
  # 测试过程中模型的相关输入
  # 包括图片,图片长宽高等基本信息,图片id,图片shape
  inputs_def:
    fields: ['image', 'im_info', 'im_id', 'im_shape']
  dataset:
    # 测试图片所在目录
    !ImageFolder
    anno_path: annotations/instances_val2017.json
  sample_transforms:
  - !DecodeImage
    to_rgb: true
    with_mixup: false
  - !NormalizeImage
    is_channel_first: false
    is_scale: true
    mean: [0.485,0.456,0.406]
    std: [0.229, 0.224,0.225]
  - !ResizeImage
    interp: 1
    max_size: 1333
    target_size: 800
    use_cv2: true
  - !Permute
    channel_first: true
    to_bgr: false
  batch_size: 1
  shuffle: false
  drop_last: false

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

数据处理模块

简介

PaddleDetection的数据处理模块是一个Python模块,所有代码逻辑在ppdet/data/中,数据处理模块用于加载数据并将其转换成适用于物体检测模型的训练、评估、推理所需要的格式。 数据处理模块的主要构成如下架构所示:

  ppdet/data/
  ├── reader.py     # 数据处理模块的总接口
  ├── shared_queue  # 共享内存管理模块
  │   ├── queue.py        # 定义共享内存队列
  │   ├── sharedmemory.py # 负责分配内存
  ├── source  # 数据源管理模块
  │   ├── dataset.py      # 定义数据源基类,各类数据集继承于此
  │   ├── coco.py         # COCO数据集解析与格式化数据
  │   ├── voc.py          # Pascal VOC数据集解析与格式化数据
  │   ├── widerface.py    # WIDER-FACE数据集解析与格式化数据
  ├── tests  # 单元测试模块
  │   ├── test_dataset.py # 对数据集解析、加载等进行单元测试
  │   │   ...
  ├── transform  # 数据预处理模块
  │   ├── batch_operators.py  # 定义各类基于批量数据的预处理算子
  │   ├── op_helper.py    # 预处理算子的辅助函数
  │   ├── operators.py    # 定义各类基于单张图片的预处理算子
  ├── parallel_map.py     # 在多进程/多线程模式中对数据预处理操作进行加速

_images/reader_figure.png

数据准备

PaddleDetection目前支持COCOPascal VOCWIDER-FACE数据源,默认数据集可自动下载,请参考默认数据集安装方法。 同时我们还支持自定义数据源,包括(1)自定义数据源转换成COCO数据集;(2)定义新的数据源。

数据准备分为三步:

下面为您分别介绍下这三步的具体内容:

数据解析

数据解析逻辑在source目录中,其中,dataset.py是数据源定义的基类,所有数据集继承于此,DataSet基类里定义了如下等方法:

方法 输入 输出 备注
load_roidb_and_cname2cid() 加载DataSet中Roidb数据源list, 类别名到id的映射dict
get_roidb() list[dict], Roidb数据源 获取数据源
get_cname2cid() dict,类别名到id的映射 获取标签ID
get_anno() str, 标注文件路径 获取标注文件路径
get_imid2path() dict, 图片路径 获取图片路径

几点解释:

  • load_roidb_and_cname2cid()在Dataset基类中并没有做实际的操作,需要在子类中重写实际操作。
  • roidbs:代表数据源列表。load_roidb_and_cname2cid方法中根据数据集标注文件(anno_path),将每张标注好的图片解析为字典coco_recvoc_rec等:
xxx_rec = {
    'im_file': im_fname,         # 一张图像的完整路径
    'im_id': np.array([img_id]), # 一张图像的ID序号
    'h': im_h,                   # 图像高度
    'w': im_w,                   # 图像宽度
    'is_crowd': is_crowd,        # 是否是群落对象, 默认为0 (VOC中无此字段,为了使个别模型同时适配于COCO与VOC)
    'gt_class': gt_class,        # 标注框标签名称的ID序号
    'gt_bbox': gt_bbox,          # 标注框坐标(xmin, ymin, xmax, ymax)
    'gt_score': gt_score,        # 标注框置信度得分 (此字段为了适配Mixup操作)
    'gt_poly': gt_poly,          # 分割掩码,此字段只在coco_rec中出现,默认为None
    'difficult': difficult       # 是否是困难样本,此字段只在voc_rec中出现,默认为0
}

然后将所有xxx_rec字典封装到records列表中,最后传入self.roidbs中方便后续调用。

  • cname2cid:保存了类别名到id的映射的一个dict。
    • COCO数据集中:会根据COCO API自动加载cname2cid。
    • VOC数据集中:如果在yaml配置文件中设置use_default_label=False,将从label_list.txt中读取类别列表, 反之则可以没有label_list.txt文件,PaddleDetection会使用source/voc.py里的默认类别字典。 label_list.txt的格式如下所示,每一行文本表示一个类别:
aeroplane
bicycle
bird
...
COCO数据源

该数据集目前分为COCO2014和COCO2017,主要由json文件和image文件组成,其组织结构如下所示:

dataset/coco/
├── annotations
│   ├── instances_train2014.json
│   ├── instances_train2017.json
│   ├── instances_val2014.json
│   ├── instances_val2017.json
│   │   ...
├── train2017
│   ├── 000000000009.jpg
│   ├── 000000580008.jpg
│   │   ...
├── val2017
│   ├── 000000000139.jpg
│   ├── 000000000285.jpg
│   │   ...

source/coco.py中定义并注册了COCODataSet数据源类,它继承自DataSet基类,并重写了load_roidb_and_cname2cid

根据标注文件路径(anno_path),调用COCO API加载并解析COCO格式数据源roidbscname2cid

Pascal VOC数据源

该数据集目前分为VOC2007和VOC2012,主要由xml文件和image文件组成,其组织结构如下所示:

dataset/voc/
├── trainval.txt
├── test.txt
├── label_list.txt (optional)
├── VOCdevkit/VOC2007
│   ├── Annotations
│       ├── 001789.xml
│       │   ...
│   ├── JPEGImages
│       ├── 001789.jpg
│       │   ...
│   ├── ImageSets
│       |   ...
├── VOCdevkit/VOC2012
│   ├── Annotations
│       ├── 2011_003876.xml
│       │   ...
│   ├── JPEGImages
│       ├── 2011_003876.jpg
│       │   ...
│   ├── ImageSets
│       │   ...

source/voc.py中定义并注册了VOCDataSet数据源类,它继承自DataSet基类,并重写了load_roidb_and_cname2cid,解析VOC数据集中xml格式标注文件,更新roidbscname2cid

添加新数据源
  • (1)新建./source/xxx.py,定义类XXXDataSet继承自DataSet基类,完成注册与序列化,并重写load_roidb_and_cname2cid方法对roidbscname2cid更新:
@register
@serializable
class XXXDataSet(DataSet):
    def __init__(self,
                 dataset_dir=None,
                 image_dir=None,
                 anno_path=None,
                 ...
                 ):
        self.roidbs = None
        self.cname2cid = None
        ...

    def load_roidb_and_cname2cid(self):
        ...
        省略具体解析数据逻辑
        ...
        self.roidbs, self.cname2cid = records, cname2cid
  • (2)在source/__init__.py中添加引用:
from . import xxx
from .xxx import *

完成以上两步就将新的数据源XXXDataSet添加好了,操作非常简单。

数据预处理
数据增强算子

PaddleDetection中支持了种类丰富的数据增强算子,有单图像数据增强算子与批数据增强算子两种方式,您可选取合适的算子组合使用,已支持的单图像数据增强算子详见下表:

名称 作用
DecodeImage 从图像文件或内存buffer中加载图像,格式为BGR、HWC格式,如果设置to_rgb=True,则转换为RGB格式。
ResizeImage 根据特定的插值方式调整图像大小
RandomFlipImage 随机水平翻转图像
NormalizeImage 对图像像素值进行归一化,如果设置is_scale=True,则先将像素值除以255.0,像素值缩放到到[0-1]区间。
RandomDistort 随机扰动图片亮度、对比度、饱和度和色相
ExpandImage 将原始图片放入用像素均值填充(随后会在减均值操作中减掉)的扩张图中,对此图进行裁剪、缩放和翻转
CropImage 根据缩放比例、长宽比例生成若干候选框,再依据这些候选框和标注框的面积交并比(IoU)挑选出符合要求的裁剪结果
CropImageWithDataAchorSampling 基于CropImage,在人脸检测中,随机将图片尺度变换到一定范围的尺度,大大增强人脸的尺度变化
NormalizeBox 对bounding box进行归一化
Permute 对图像的通道进行排列并转为BGR格式。假如输入是HWC顺序,通道C上是RGB格式,设置channel_first=True,将变成CHW,设置to_bgr=True,通道C上变成BGR格式。
MixupImage 按比例叠加两张图像
RandomInterpImage 使用随机的插值方式调整图像大小
Resize 根据特定的插值方式同时调整图像与bounding box的大小
MultiscaleTestResize 将图像重新缩放为多尺度list的每个尺寸
ColorDistort 根据特定的亮度、对比度、饱和度和色相为图像增加噪声
NormalizePermute 归一化图像并改变图像通道顺序
RandomExpand 原理同ExpandImage,以随机比例与角度对图像进行裁剪、缩放和翻转
RandomCrop 原理同CropImage,以随机比例与IoU阈值进行处理
PadBox 如果bounding box的数量少于num_max_boxes,则将零填充到bbox
BboxXYXY2XYWH 将bounding box从(xmin,ymin,xmax,ymin)形式转换为(xmin,ymin,width,height)格式

几点说明:

  • 上表中的数据增强算子的输入与输出都是单张图片samplesample是由{'image':xx, 'im_info': xxx, ...}组成,来自于上文提到的roidbs中的字典信息。
  • 数据增强算子注册后即可生效,在配置yaml文件中添加即可,配置文件中配置方法见下文。
  • Mixup的操作可参考论文

批数据增强算子列表如下:

名称 输入与输出 作用
RandomShape samples 随机对每个batch的数据图片进行resize操作
PadMultiScaleTest samples 在多尺度测试中对图像进行填充
Gt2YoloTarget samples 通过gt数据生成YOLOv3目标,此OP仅在拆分后的YOLOv3损失模式下使用
  • 批数据增强算子的输入输出都是批数据samples,是一个sample的list。
  • 需要批数据增强算子的原因: CNN计算时需要一个batch内的图像大小相同,而一些数据增强算子,比如随机大小缩放,会随机选择一个缩放尺寸,为了使得一个batch内的图像大小相同,先组成batch,再做随机大小缩放的数据增强。
自定义数据增强算子

假如我们定义一个新的单图像数据增强算子XXXImage

  • transform/operators.py中增加类XXXImage继承自BaseOperator,并注册:
@register_op
class XXXImage(BaseOperator):
    def __init__(self,...):

        super(XXXImage, self).__init__()
        ...

    def __call__(self, sample, context=None):
        ...
        省略对输入的sample具体操作
        ...
        return sample

如此就完成新增单图像数据增强算子XXXImage,操作非常简单。

自定义批量数据增强算子方法同上,在transform/batch_operators.py中定义即可。

组建Reader迭代器

如上面提到,Reader预处理流程为: 单张图像处理 -> 组batch -> batch图像处理。用户一般不需要关注这些方法。 在reader.py中构建了Reader迭代器类,其中包含如下方法:

方法 输入 输出 备注
reset() 重置Reader迭代器
next() list 返回Reader迭代器接下来输出的批数据
worker() bool,list list 数据预处理的接口,输入(drop_empty, batch_samples),输出批数据list
size() int 返回roidbs的长度
drained() bool 判断当前Reader迭代器中数据是否已经读完
stop() 停止Reader迭代器

Reader迭代器的创建使用reader.py中的create_reader方法,在create_reader函数中需要传入cfg参数列表,参数列表详细内容如下:

参数名 类型 含义
sample_transforms list of BaseOperator 使用各种单图像数据增强算子的列表
batch_transforms list of BaseOperator 使用批数据数据增强算子的列表
batch_size int 批数据大小(图像个数/batch)
shuffle bool 是否随机打乱数据集中图像排序,默认False
drop_last bool 是否删除最后一个batch的数据,默认False
drop_empty bool 是否删除空数据,默认True
mixup_epoch int 在第几个epoch使用Mixup数据增强策略,默认不使用(-1)
class_aware_sampling bool 是否使用class-aware数据增强方法,默认False
worker_num int 数据读取中使用多进程的数量
use_process bool 数据读取中是否使用多进程
bufsize int 多进程/多线程缓冲队列的大小,队列中每个元素为一个batch的数据
memsize str 多进程下共享存储队列的大小,默认3G
inputs_def dict 用在网络输入定义中获取输入字段,该字段用于确定返回数据的顺序。

配置及运行

在模型的训练、评估与推理的数据处理,都是通过配置文件来实现,下面为您详细介绍配置的步骤。

训练配置
  • 首先在yml配置文件中定义如下格式的训练-数据处理模块:
TrainReader:
  inputs_def: # 网络输入的定义
    fields: ['image', 'gt_bbox', 'gt_class', 'gt_score']
  dataset:    # 数据源
      !COCODataSet  #序列化COCO数据源
      dataset_dir: dataset/coco   # 数据集根目录
      anno_path: annotations/instances_train2017.json  # 标注文件基于数据集根目录的相对路径
      image_dir: train2017    # 图像数据基于数据集根目录的相对路径
      with_background: false  # 背景是否作为一类标签
  sample_transforms:   # 单图像数据增强算子的列表
    - !DecodeImage     # 序列化DecodeImage算子,详细参数设置参见源码
      to_rgb: true
      with_mixup: true
    - !MixupImage      # 序列化MixupImage算子,详细参数设置参见源码
      alpha: 1.5
      beta: 1.5
    - !ColorDistort {} # 序列化ColorDistort算子,详细参数设置参见源码
    ...
  batch_transforms:   # 批数据数据增强算子的列表 (可选)
    - !RandomShape    # 序列化RandomShape算子,详细参数设置参见源码
      sizes: [320, 352, 384, 416, 448, 480, 512, 544, 576, 608]
      random_inter: True
  ...
  batch_size: 8       # 以下定义见上文Reader参数列表
  shuffle: true  
  mixup_epoch: 250  
  worker_num: 8  
  use_process: true  

几点说明:

  • 训练-数据处理模块的名称统一为TrainReader
  • PaddleDetection的yml配置文件中,使用!直接序列化模块实例(可以是函数、类等);
  • dataset下需要序列化数据源实例,如COCODataSetVOCDataSe和自定义的XXXDataSet
  • inputs_def的具体定义与使用请参考模型技术文档
  • Reader的参数可选择性配置,如未在yml配置文件中定义,则会选取各参数在源码中的默认值。
评估配置
EvalReader:
  inputs_def:
    fields: ['image', 'im_size', 'im_id']
  dataset:
    !COCODataSet
      dataset_dir: dataset/coco
      anno_path: annotations/instances_val2017.json
      image_dir: val2017
      with_background: false
  sample_transforms:
    - !DecodeImage
      to_rgb: True
    ...  
  batch_size: 8
  drop_empty: false

几点说明:

  • 评估-数据处理模块的名称统一为EvalReader
  • 在评估配置中,数据增强需要去除各种含有随机操作的数据处理算子与操作。
推理配置
TestReader:
  inputs_def:
    image_shape: [3, 608, 608]
    fields: ['image', 'im_size', 'im_id']
  dataset:
    !ImageFolder
      anno_path: annotations/instances_val2017.json
      with_background: false
  sample_transforms:
    - !DecodeImage
      to_rgb: True
    ...
  batch_size: 1

几点说明:

  • 推理-数据处理模块的名称统一为TestReader
  • 在推理配置中dataset的数据源一般都设置为ImageFolder数据源。ImageFolder可以指定图片的文件夹地址,将读取该文件夹下的所有图片。

到此就完成了yml配置文件中的TrainReaderEvalReaderTestReader的编写,您也可以将Reader部分封装到单独的yml文件xxx_reader.yml中,利用如下命令进行加载即可:

_READER_: 'xxx_reader.yml'

加载完成后可以重写Reader中的方法,比如:

_READER_: 'xxx_reader.yml'
TrainReader:
  batch_size: 2
  ...
EvalReader:
  ...

这样就可以复用同一份Reader配置文件了,重写更新其中某些参数也很方便。

运行

在PaddleDetection的训练、评估和测试运行程序中,都通过创建Reader迭代器,然后将reader封装在DataLoader对象中, DataLoader的API详见fluid.io.DataLoader。 具体步骤如下:

# 创建DataLoader对象
inputs_def = cfg['TestReader']['inputs_def']
_, loader = model.build_inputs(**inputs_def)
# 创建Reader迭代器
from ppdet.data.reader import create_reader
# train
train_reader = create_reader(cfg.TrainReader, max_iter=0, global_cfg=cfg)
# eval
reader = create_reader(cfg.EvalReader)
# infer
reader = create_reader(cfg.TestReader)
# 将reader设置为DataLoader数据源
loader.set_sample_list_generator(reader, place)

在运行程序中设置完数据处理模块后,就可以开始训练、评估与测试了,具体请参考相应运行程序python源码。

关于数据处理模块,如您有其他问题或建议,请给我们提issue,我们非常欢迎您的反馈。

新增模型算法

为了让用户更好的使用PaddleDetection,本文档中,我们将介绍PaddleDetection的主要模型技术细节及应用, 包括:如何搭建模型,如何定义检测组件和模型配置与运行。

简介

PaddleDetection的网络模型模块所有代码逻辑在ppdet/modeling/中,所有网络模型是以组件的形式进行定义与组合,网络模型模块的主要构成如下架构所示:

  ppdet/modeling/
  ├── architectures      #
  │   ├── faster_rcnn.py # Faster Rcnn模型
  │   ├── ssd.py         # SSD模型
  │   ├── yolov3.py      # YOLOv3模型
  │   │   ...
  ├── anchor_heads       # anchor生成检测头模块
  │   ├── xxx_head.py    # 定义各类anchor生成检测头
  ├── backbones          # 基干网络模块
  │   ├── resnet.py      # ResNet网络
  │   ├── mobilenet.py   # MobileNet网络
  │   │   ...
  ├── losses             # 损失函数模块
  │   ├── xxx_loss.py    # 定义注册各类loss函数
  ├── roi_extractors     # 检测感兴趣区域提取
  │   ├── roi_extractor.py  # FPNRoIAlign等实现
  ├── roi_heads          # 两阶段检测器检测头
  │   ├── bbox_head.py   # Faster-Rcnn系列检测头
  │   ├── cascade_head.py # cascade-Rcnn系列检测头
  │   ├── mask_head.py   # Mask-Rcnn系列检测头
  ├── tests  # 单元测试模块
  │   ├── test_architectures.py  # 对网络结构进行单元测试
  ├── ops.py  # 封装及注册各类PaddlePaddle物体检测相关公共检测组件/算子
  ├── target_assigners.py # 封装bbox/mask等最终结果的公共检测组件

_images/models_figure.png

新增模型

我们以单阶段检测器YOLOv3为例,结合yolov3_darknet.yml配置文件,对建立模型过程进行详细描述, 按照此思路您可以快速搭建新的模型。

搭建新模型的一般步骤是:Backbone编写、检测组件编写与模型组网这三个步骤,下面为您详细介绍:

Backbone编写

1.代码编写: PaddleDetection中现有所有Backbone网络代码都放置在ppdet/modeling/backbones目录下,所以我们在其中新建darknet.py如下:

from ppdet.core.workspace import register

@register
class DarkNet(object):

    __shared__ = ['norm_type', 'weight_prefix_name']

    def __init__(self,
                 depth=53,
                 norm_type='bn',
                 norm_decay=0.,
                 weight_prefix_name=''):
        # 省略内容
        pass

    def __call__(self, input):
        # 省略处理逻辑
        pass

然后在backbones/__init__.py中加入引用:

from . import darknet
from .darknet import *

几点说明:

  • 为了在yaml配置文件中灵活配置网络,所有Backbone、模型组件与architecture类需要利用ppdet.core.workspace里的register进行注册,形式请参考如上示例;
  • 在Backbone中都需定义__init__函数与__call__函数,__init__函数负责初始化参数,在调用此Backbone时会执行__call__函数;
  • __shared__为了实现一些参数的配置全局共享,具体细节请参考配置文件说明文档

2.配置编写: 在yaml文件中以注册好了的DarkNet类名为标题,可选择性的对__init__函数中的参数进行更新,不在配置文件中配置的参数会保持__init__函数中的初始化值:

DarkNet:
  norm_type: sync_bn
  norm_decay: 0.
  depth: 53
检测组件编写

1.代码编写:编写好Backbone后,我们开始编写生成anchor的检测头部分,anchor的检测头代码都在ppdet/modeling/anchor_heads目录下,所以我们在其中新建yolo_head.py如下:

from ppdet.core.workspace import register

@register
class YOLOv3Head(object):

    __inject__ = ['yolo_loss', 'nms']
    __shared__ = ['num_classes', 'weight_prefix_name']

    def __init__(self,
                 num_classes=80,
                 anchors=[[10, 13], [16, 30], [33, 23], [30, 61], [62, 45],
                          [59, 119], [116, 90], [156, 198], [373, 326]],
                 yolo_loss="YOLOv3Loss",
                 nms=MultiClassNMS(
                     score_threshold=0.01,
                     nms_top_k=1000,
                     keep_top_k=100,
                     nms_threshold=0.45,
                     background_label=-1).__dict__):
        # 省略部分内容
        pass

然后在anchor_heads/__init__.py中加入引用:

from . import yolo_head
from .yolo_head import *

几点说明:

  • __inject__表示引入封装好了的检测组件/算子列表,此处yolo_lossnms变量指向外部定义好的检测组件/算子;
  • anchor的检测头实现中类函数需有输出loss接口get_loss与预测框或建议框输出接口get_prediction
  • 两阶段检测器在anchor的检测头里定义的是候选框输出接口get_proposals,之后还会在roi_extractorsroi_heads中进行后续计算,定义方法与如下一致。
  • YOLOv3算法的loss函数比较复杂,所以我们将loss函数进行拆分,具体实现在losses/yolo_loss.py中,也需要注册;
  • nms算法是封装paddlepaddle中现有检测组件/算子,如何定义与注册详见定义公共检测组件/算子部分。

2.配置编写: 在yaml文件中以注册好了的YOLOv3Head类名为标题,可选择性的对__init__函数中的参数进行更新,不在配置文件中配置的参数会保持__init__函数中的初始化值:

YOLOv3Head:
  anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
  anchors: [[10, 13], [16, 30], [33, 23],
            [30, 61], [62, 45], [59, 119],
            [116, 90], [156, 198], [373, 326]]
  norm_decay: 0.
  yolo_loss: YOLOv3Loss
  nms:
    background_label: -1
    keep_top_k: 100
    nms_threshold: 0.45
    nms_top_k: 1000
    normalized: false
    score_threshold: 0.01

YOLOv3Loss:
  batch_size: 8
  ignore_thresh: 0.7
  label_smooth: false

如上配置文件中的YOLOv3Loss是注册好检测组件接口,所以需要在配置文件中也对YOLOv3Loss进行参数设置。

模型组网

本步骤中,我们需要将编写好的Backbone、各个检测组件进行整合拼接,搭建一个完整的物体检测网络能够提供给训练、评估和测试程序去运行。 1.组建architecture: 所有architecture网络代码都放置在ppdet/modeling/architectures目录下,所以我们在其中新建yolov3.py如下:

from ppdet.core.workspace import register

@register
class YOLOv3(object):

    __category__ = 'architecture'
    __inject__ = ['backbone', 'yolo_head']
    __shared__ = ['use_fine_grained_loss']

    def __init__(self,
                 backbone,
                 yolo_head='YOLOv3Head',
                 use_fine_grained_loss=False):
        super(YOLOv3, self).__init__()
        # 省略内容

    def build(self, feed_vars, mode='train'):
        # 省略内容
        pass

    def build_inputs(self, ):
        # 详解见【模型输入设置】章节
        pass

    def train(self, feed_vars):
        return self.build(feed_vars, mode='train')

    def eval(self, feed_vars):
        return self.build(feed_vars, mode='test')

    def test(self, feed_vars):
        return self.build(feed_vars, mode='test')

几点说明:

  • 在组建一个完整的网络时必须要设定__category__ = 'architecture'来表示一个完整的物体检测模型;
  • __init__函数中传入我们上面定义好的backboneyolo_head的名称即可,根据yaml配置文件里这些组件的参数初始化,ppdet.core.workspace会自动解析加载;
  • 在architecture类里必须定义build_inputs函数,为了适配检测网络的输入与Reader模块,具体见模型输入设置模块;
  • 在architecture类里必须定义trainevaltest函数,在训练、评估和测试程序中会分别调用这三个函数来在不同场景中加载网络模型。

2.配置编写:

首先定义网络模型名称:

architecture: YOLOv3

接下来根据网络模型名称YOLOv3来初始化网络组件名称:

YOLOv3:
  backbone: DarkNet
  yolo_head: YOLOv3Head

之后backboneyolo_head的配置步骤在上面已经介绍,完成如上配置就完成了物体检测模型组网的工作。

模型输入设置

在architecture定义的类里必须含有build_inputs函数,这个函数的作用是生成feed_varsloader

1.feed_vars是由key:fluid.data构成的字典,key是由如下yaml文件中fields字段构成,在不同数据集、训练、评估和测试中字段不尽相同, 在使用中需要合理组合。

TrainReader:
  inputs_def:
    fields: ['image', 'gt_bbox', 'gt_class', 'gt_score']

EvalReader:
  inputs_def:
    fields: ['image', 'im_size', 'im_id']
...

数据源解析中已经提到,数据源roidbs会解析为字典的形式,Reader会根据feed_vars所含字段进行解析适配。

2.loader是调用fluid.io.DataLoader 根据feed_vars来完成DataLoader的组建。

定义公共检测组件/算子

为了更好的复用一些公共检测组件/算子,以及可以在yaml配置文件中配置化,检测模型相关检测组件/算子都在ppdet/modeling/ops.py中定义并注册。这部分是选做部分,不是必需的。

(1)基于现有的PaddlePaddle物体检测相关OP进行二次封装注册:

例如fluid.layers.multiclass_nms 在PaddlePaddle已经存在,我们想让它在yaml文件中灵活配置,我们只需要在ops.py中如下配置即可:

from ppdet.core.workspace import register, serializable

@register
@serializable
class MultiClassNMS(object):
    __op__ = fluid.layers.multiclass_nms
    __append_doc__ = True

    def __init__(self,
                 score_threshold=.05,
                 nms_top_k=-1,
                 keep_top_k=100,
                 nms_threshold=.5,
                 normalized=False,
                 nms_eta=1.0,
                 background_label=0):
        super(MultiClassNMS, self).__init__()
        # 省略

注意: 我们是对fluid.layers.multiclass_nms这个OP进行二次封装,在__init__方法中添加所需的可选参数即可,保持默认的参数可以不添加进来。

(2)从零开始定义检测组件/算子:

ops.py中定义xxx函数,然后在相应位置添加from ppdet.modeling.ops import xxx即可调用,无需注册与序列化。

配置及运行

PaddleDetection在ppdet/optimizer.py中注册实现了学习率配置接口类LearningRate、优化器接口类OptimizerBuilder

  • 学习率配置 在yaml文件中可便捷配置学习率各个参数:
LearningRate:
  base_lr: 0.001
  schedulers:
  - !PiecewiseDecay
    gamma: 0.1
    milestones:
    - 400000
    - 450000
  - !LinearWarmup
    start_factor: 0.
    steps: 4000

几点说明:

  • PiecewiseDecayLinearWarmup策略在ppdet/optimizer.py中都已注册。
  • 除了这两个优化器之外,您还可以使用paddlepaddle中所有的优化器paddlepaddle官网文档
  • Optimizer优化器配置:
OptimizerBuilder:
  optimizer:
    momentum: 0.9
    type: Momentum
  regularizer:
    factor: 0.0005
    type: L2
  • 其他配置:在训练、评估与测试阶段,定义了一些所需参数如下:
use_gpu: true         # 是否使用GPU运行程序
max_iters: 500200     # 最大迭代轮数
log_iter: 20          # 日志打印队列长度, 训练时日志每迭代x轮打印一次
save_dir: output      # 模型保存路径
snapshot_iter: 2000   # 训练时第x轮保存/评估
metric: COCO          # 数据集名称
pretrain_weights: xxx # 预训练模型地址(网址/路径)
weights: xxx/model_final # 评估或测试时模型权重的路径
num_classes: 80       # 类别数
看过此文档,您应该对PaddleDetection中模型搭建与配置有了一定经验,结合源码会理解的更加透彻。关于模型技术,如您有其他问题或建议,请给我们提issue,我们非常欢迎您的反馈。

English | 简体中文

迁移学习教程

迁移学习为利用已有知识,对新知识进行学习。例如利用ImageNet分类预训练模型做初始化来训练检测模型,利用在COCO数据集上的检测模型做初始化来训练基于PascalVOC数据集的检测模型。

选择数据

迁移学习需要使用自己的数据集,目前已支持COCO和VOC的数据标注格式,在tools/x2coco.py中给出了voc、labelme和cityscape标注格式转换为COCO格式的脚本,具体使用方式可以参考自定义数据源。数据准备完成后,在配置文件中配置数据路径,对应修改reader中的路径参数即可。

  1. COCO数据集需要修改COCODataSet中的参数,以yolov3_darknet.yml为例,修改yolov3_reader中的配置:
  dataset:
    !COCODataSet
      dataset_dir: custom_data/coco # 自定义数据目录
      image_dir: train2017 # 自定义训练集目录,该目录在dataset_dir中
      anno_path: annotations/instances_train2017.json # 自定义数据标注路径,该目录在dataset_dir中  
      with_background: false
  1. VOC数据集需要修改VOCDataSet中的参数,以yolov3_darknet_voc.yml为例:
  dataset:
    !VOCDataSet
    dataset_dir: custom_data/voc # 自定义数据集目录
    anno_path: trainval.txt # 自定义数据标注路径,该目录在dataset_dir中
    use_default_label: true
    with_background: false

加载预训练模型

在进行迁移学习时,由于会使用不同的数据集,数据类别数与COCO/VOC数据类别不同,导致在加载开源模型(如COCO预训练模型)时,与类别数相关的权重(例如分类模块的fc层)会出现维度不匹配的问题;另外,如果需要结构更加复杂的模型,需要对已有开源模型结构进行调整,对应权重也需要选择性加载。因此,需要在加载模型时不加载不能匹配的权重。

在迁移学习中,对预训练模型进行选择性加载,支持如下两种迁移学习方式:

直接加载预训练权重(推荐方式

模型中和预训练模型中对应参数形状不同的参数将自动被忽略,例如:

export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
python -u tools/train.py -c configs/faster_rcnn_r50_1x.yml \
                           -o pretrain_weights=https://paddlemodels.bj.bcebos.com/object_detection/faster_rcnn_r50_1x.tar
使用finetune_exclude_pretrained_params参数控制忽略参数名

可以显示的指定训练过程中忽略参数的名字,任何参数名均可加入finetune_exclude_pretrained_params中,为实现这一目的,可通过如下方式实现:

  1. 在 YMAL 配置文件中通过设置finetune_exclude_pretrained_params字段。可参考配置文件
  2. 在 train.py的启动参数中设置finetune_exclude_pretrained_params。例如:
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
python -u tools/train.py -c configs/faster_rcnn_r50_1x.yml \
                         -o pretrain_weights=https://paddlemodels.bj.bcebos.com/object_detection/faster_rcnn_r50_1x.tar \
                           finetune_exclude_pretrained_params=['cls_score','bbox_pred'] \
  • 说明:
  1. pretrain_weights的路径为COCO数据集上开源的faster RCNN模型链接,完整模型链接可参考MODEL_ZOO
  2. finetune_exclude_pretrained_params中设置参数字段,如果参数名能够匹配以上参数字段(通配符匹配方式),则在模型加载时忽略该参数。

如果用户需要利用自己的数据进行finetune,模型结构不变,只需要忽略与类别数相关的参数,不同模型类型所对应的忽略参数字段如下表所示:

模型类型 忽略参数字段
Faster RCNN cls_score, bbox_pred
Cascade RCNN cls_score, bbox_pred
Mask RCNN cls_score, bbox_pred, mask_fcn_logits
Cascade-Mask RCNN cls_score, bbox_pred, mask_fcn_logits
RetinaNet retnet_cls_pred_fpn
SSD ^conv2d_
YOLOv3 yolo_output

模型压缩教程

压缩benchmark

在PaddleDetection, 提供了基于PaddleSlim进行模型压缩的完整教程和实验结果。详细教程请参考:

下面给出压缩的benchmark实验结果。

测试环境
  • Python 2.7.1
  • PaddlePaddle >=1.6
  • CUDA 9.0
  • cuDNN >=7.4
  • NCCL 2.1.2
剪裁模型库
训练策略
  • 剪裁模型训练时使用PaddleDetection模型库发布的模型权重作为预训练权重。
  • 剪裁训练使用模型默认配置,即除pretrained_weights外配置不变。
  • 剪裁模型全部为基于敏感度的卷积通道剪裁。
  • YOLOv3模型主要剪裁yolo_head部分,即剪裁参数如下。
--pruned_params="yolo_block.0.0.0.conv.weights,yolo_block.0.0.1.conv.weights,yolo_block.0.1.0.conv.weights,yolo_block.0.1.1.conv.weights,yolo_block.0.2.conv.weights,yolo_block.0.tip.conv.weights,yolo_block.1.0.0.conv.weights,yolo_block.1.0.1.conv.weights,yolo_block.1.1.0.conv.weights,yolo_block.1.1.1.conv.weights,yolo_block.1.2.conv.weights,yolo_block.1.tip.conv.weights,yolo_block.2.0.0.conv.weights,yolo_block.2.0.1.conv.weights,yolo_block.2.1.0.conv.weights,yolo_block.2.1.1.conv.weights,yolo_block.2.2.conv.weights,yolo_block.2.tip.conv.weights"
  • YOLOv3模型剪裁中剪裁策略r578表示yolo_head中三个输出分支一次使用0.5, 0.7, 0.8的剪裁率剪裁,即剪裁率如下。
--pruned_ratios="0.5,0.5,0.5,0.5,0.5,0.5,0.7,0.7,0.7,0.7,0.7,0.7,0.8,0.8,0.8,0.8,0.8,0.8"
  • YOLOv3模型剪裁中剪裁策略sensity表示yolo_head中各参数剪裁率如下,该剪裁率为使用yolov3_mobilnet_v1模型在COCO数据集上敏感度实验分析得出。
--pruned_ratios="0.1,0.2,0.2,0.2,0.2,0.1,0.2,0.3,0.3,0.3,0.2,0.1,0.3,0.4,0.4,0.4,0.4,0.3"
YOLOv3 on COCO
骨架网络 剪裁策略 GFLOPs 模型体积(MB) 输入尺寸 Box AP 下载
ResNet50-vd-dcn baseline 44.71 176.82 608 39.1 下载链接
ResNet50-vd-dcn sensity 37.53(-16.06%) 149.49(-15.46%) 608 39.8(+0.7) 下载链接
ResNet50-vd-dcn r578 29.98(-32.94%) 112.08(-36.61%) 608 38.3(-0.8) 下载链接
MobileNetV1 baseline 20.64 94.60 608 29.3 下载链接
MobileNetV1 baseline 9.66 94.60 416 29.3 下载链接
MobileNetV1 baseline 5.72 94.60 320 27.1 下载链接
MobileNetV1 sensity 13.57(-34.27%) 67.60(-28.54%) 608 30.2(+0.9) 下载链接
MobileNetV1 sensity 6.35(-34.27%) 67.60(-28.54%) 416 29.7(+0.4) 下载链接
MobileNetV1 sensity 3.76(-34.27%) 67.60(-28.54%) 320 27.2(+0.1) 下载链接
MobileNetV1 r578 6.27(-69.64%) 31.30(-66.90%) 608 27.8(-1.5) 下载链接
MobileNetV1 r578 2.93(-69.64%) 31.30(-66.90%) 416 26.8(-2.5) 下载链接
MobileNetV1 r578 1.74(-69.64%) 31.30(-66.90%) 320 24.0(-3.1) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中YOLOv3-MobileNetV1提供了在608/416/320三种不同尺寸下的精度结果
  • 在使用sensity剪裁策略下,YOLOv3-ResNet50-vd-dcnYOLOv3-MobileNetV1分别减少了16.06%34.27%的FLOPs,输入图像尺寸为608时精度分别提高0.70.9
  • 在使用r578剪裁策略下,YOLOv3-ResNet50-vd-dcnYOLOv3-MobileNetV1分别减少了32.98%69.64%的FLOPs,输入图像尺寸为608时精度分别降低0.81.5
YOLOv3 on Pascal VOC
骨架网络 剪裁策略 GFLOPs 模型体积(MB) 输入尺寸 Box AP 下载
MobileNetV1 baseline 20.20 93.37 608 76.2 下载链接
MobileNetV1 baseline 9.46 93.37 416 76.7 下载链接
MobileNetV1 baseline 5.60 93.37 320 75.3 下载链接
MobileNetV1 sensity 13.22(-34.55%) 66.53(-28.74%) 608 78.4(+2.2) 下载链接
MobileNetV1 sensity 6.19(-34.55%) 66.53(-28.74%) 416 78.7(+2.0) 下载链接
MobileNetV1 sensity 3.66(-34.55%) 66.53(-28.74%) 320 76.1(+0.8) 下载链接
MobileNetV1 r578 6.15(-69.57%) 30.81(-67.00%) 608 77.6(+1.4) 下载链接
MobileNetV1 r578 2.88(-69.57%) 30.81(-67.00%) 416 77.7(+1.0) 下载链接
MobileNetV1 r578 1.70(-69.57%) 30.81(-67.00%) 320 75.5(+0.2) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中YOLOv3-MobileNetV1提供了在608/416/320三种不同尺寸下的精度结果
  • 在使用sensityr578剪裁策略下,YOLOv3-MobileNetV1分别减少了34.55%69.57%的FLOPs,输入图像尺寸为608时精度分别提高2.21.4
蒸馏通道剪裁模型

可通过高精度模型蒸馏通道剪裁后模型的方式,训练方法及相关示例见蒸馏通道剪裁模型

COCO数据集上蒸馏通道剪裁模型库如下。

骨架网络 剪裁策略 GFLOPs 模型体积(MB) 输入尺寸 teacher模型 Box AP 下载
ResNet50-vd-dcn baseline 44.71 176.82 608 - 39.1 下载链接
ResNet50-vd-dcn r578 29.98(-32.94%) 112.08(-36.61%) 608 YOLOv3-ResNet50-vd-dcn(39.1) 39.7(+0.6) 下载链接
MobileNetV1 baseline 20.64 94.60 608 - 29.3 下载链接
MobileNetV1 baseline 9.66 94.60 416 - 29.3 下载链接
MobileNetV1 baseline 5.72 94.60 320 - 27.1 下载链接
MobileNetV1 r578 6.27(-69.64%) 31.30(-66.90%) 608 YOLOv3-ResNet34(36.2) 29.0(-0.3) 下载链接
MobileNetV1 r578 2.93(-69.64%) 31.30(-66.90%) 416 YOLOv3-ResNet34(34.3) 28.0(-1.3) 下载链接
MobileNetV1 r578 1.74(-69.64%) 31.30(-66.90%) 320 YOLOv3-ResNet34(31.4) 25.1(-2.0) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中YOLOv3-MobileNetV1提供了在608/416/320三种不同尺寸下的精度结果
  • 在使用r578剪裁策略并使用YOLOv3-ResNet50-vd-dcn作为teacher模型蒸馏,YOLOv3-ResNet50-vd-dcn模型减少了32.94%的FLOPs,输入图像尺寸为608时精度提高0.6
  • 在使用r578剪裁策略并使用YOLOv3-ResNet34作为teacher模型蒸馏下,YOLOv3-MobileNetV1模型减少了69.64%的FLOPs,输入图像尺寸为608时精度降低0.3

Pascal VOC数据集上蒸馏通道剪裁模型库如下。

骨架网络 剪裁策略 GFLOPs 模型体积(MB) 输入尺寸 teacher模型 Box AP 下载
MobileNetV1 baseline 20.20 93.37 608 - 76.2 下载链接
MobileNetV1 baseline 9.46 93.37 416 - 76.7 下载链接
MobileNetV1 baseline 5.60 93.37 320 - 75.3 下载链接
MobileNetV1 r578 6.15(-69.57%) 30.81(-67.00%) 608 YOLOv3-ResNet34(82.6) 78.8(+2.6) 下载链接
MobileNetV1 r578 2.88(-69.57%) 30.81(-67.00%) 416 YOLOv3-ResNet34(81.9) 78.7(+2.0) 下载链接
MobileNetV1 r578 1.70(-69.57%) 30.81(-67.00%) 320 YOLOv3-ResNet34(80.1) 76.3(+2.0) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中YOLOv3-MobileNetV1提供了在608/416/320三种不同尺寸下的精度结果
  • 在使用r578剪裁策略并使用YOLOv3-ResNet34作为teacher模型蒸馏下,YOLOv3-MobileNetV1模型减少了69.57%的FLOPs,输入图像尺寸为608时精度提高2.6
YOLOv3通道剪裁模型推理时延
  • 时延单位均为ms/images
  • Tesla P4时延为单卡并开启TensorRT推理时延
  • 高通835/高通855/麒麟970时延为使用PaddleLite部署,使用arm8架构并使用4线程(4 Threads)推理时延
骨架网络 数据集 剪裁策略 GFLOPs 模型体积(MB) 输入尺寸 Tesla P4 麒麟970 高通835 高通855
MobileNetV1 VOC baseline 20.20 93.37 608 16.556 748.404 734.970 289.878
MobileNetV1 VOC baseline 9.46 93.37 416 9.031 371.214 349.065 140.877
MobileNetV1 VOC baseline 5.60 93.37 320 6.235 221.705 200.498 80.515
MobileNetV1 VOC r578 6.15(-69.57%) 30.81(-67.00%) 608 10.064(-39.21%) 314.531(-57.97%) 323.537(-55.98%) 123.414(-57.43%)
MobileNetV1 VOC r578 2.88(-69.57%) 30.81(-67.00%) 416 5.478(-39.34%) 151.562(-59.17%) 146.014(-58.17%) 56.420(-59.95%)
MobileNetV1 VOC r578 1.70(-69.57%) 30.81(-67.00%) 320 3.880(-37.77%) 91.132(-58.90%) 87.440(-56.39%) 31.470(-60.91%)
ResNet50-vd-dcn COCO baseline 44.71 176.82 608 36.127 - - -
ResNet50-vd-dcn COCO sensity 37.53(-16.06%) 149.49(-15.46%) 608 33.245(-7.98%) - - -
ResNet50-vd-dcn COCO r578 29.98(-32.94%) 112.08(-36.61%) 608 29.138(-19.35%) - - -
  • 在使用r578剪裁策略下,YOLOv3-MobileNetV1模型减少了69.57%的FLOPs,输入图像尺寸为608时在单卡Tesla P4(TensorRT)推理时间减少39.21%,在麒麟970/高通835/高通855上推理时延分别减少57.97%, 55.98%57.43%
  • 在使用sensityr578剪裁策略下,YOLOv3-ResNet50-vd-dcn模型分别减少了16.06%32.94%的FLOPs,输入图像尺寸为608时在单卡Tesla P4(TensorRT)推理时间分别减少7.98%19.35%
蒸馏模型库
训练策略
  • 蒸馏模型训练时teacher模型使用PaddleDetection模型库发布的模型权重作为预训练权重。
  • 蒸馏模型训练时student模型使用backbone的预训练权重
  • 蒸馏策略l2_distiil为使用teacher模型和student模型特征图的L2损失作为蒸馏损失进行蒸馏,为slim/distillation/distill.py的默认策略
  • 蒸馏策略split_distiil为使用YOLOv3细粒度损失进行蒸馏,通过-o use_fine_grained_loss=true指定
YOLOv3 on COCO
骨架网络 蒸馏策略 输入尺寸 teacher模型 Box AP 下载
MobileNetV1 baseline 608 - 29.3 下载链接
MobileNetV1 baseline 416 - 29.3 下载链接
MobileNetV1 baseline 320 - 27.1 下载链接
MobileNetV1 split_distiil 608 YOLOv3-ResNet34(36.2) 31.4(+2.1) 下载链接
MobileNetV1 split_distiil 416 YOLOv3-ResNet34(34.3) 30.0(+0.7) 下载链接
MobileNetV1 split_distiil 320 YOLOv3-ResNet34(31.4) 27.1(+0.0) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中YOLOv3-MobileNetV1提供了在608/416/320三种不同尺寸下的精度结果
  • 在使用YOLOv3-ResNet34模型通过split_distiil策略蒸馏下,输入图像尺寸为608时YOLOv3-MobileNetV1模型精度提高2.1
YOLOv3 on Pascal VOC
骨架网络 蒸馏策略 输入尺寸 teacher模型 Box AP 下载
MobileNetV1 baseline 608 - 76.2 下载链接
MobileNetV1 baseline 416 - 76.7 下载链接
MobileNetV1 baseline 320 - 75.3 下载链接
MobileNetV1 l2_distiil 608 YOLOv3-ResNet34(82.6) 79.0(+2.8) 下载链接
MobileNetV1 l2_distiil 416 YOLOv3-ResNet34(81.9) 78.2(+1.5) 下载链接
MobileNetV1 l2_distiil 320 YOLOv3-ResNet34(80.1) 75.5(+0.2) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中YOLOv3-MobileNetV1提供了在608/416/320三种不同尺寸下的精度结果
  • 在使用YOLOv3-ResNet34模型通过l2_distiil策略蒸馏下,输入图像尺寸为608时YOLOv3-MobileNetV1模型精度提高2.8
量化模型库
训练策略
  • 量化策略post为使用离线量化得到的模型,aware为在线量化训练得到的模型。
YOLOv3 on COCO
骨架网络 预训练权重 量化策略 输入尺寸 Box AP 下载
MobileNetV1 ImageNet baseline 608 29.3 下载链接
MobileNetV1 ImageNet baseline 416 29.3 下载链接
MobileNetV1 ImageNet baseline 320 27.1 下载链接
MobileNetV1 ImageNet post 608 27.9(-1.4) 下载链接
MobileNetV1 ImageNet post 416 28.0(-1.3) 下载链接
MobileNetV1 ImageNet post 320 26.0(-1.1) 下载链接
MobileNetV1 ImageNet aware 608 28.1(-1.2) 下载链接
MobileNetV1 ImageNet aware 416 28.2(-1.1) 下载链接
MobileNetV1 ImageNet aware 320 25.8(-1.3) 下载链接
ResNet34 ImageNet baseline 608 36.2 下载链接
ResNet34 ImageNet baseline 416 34.3 下载链接
ResNet34 ImageNet baseline 320 31.4 下载链接
ResNet34 ImageNet post 608 35.7(-0.5) 下载链接
ResNet34 ImageNet aware 608 35.2(-1.1) 下载链接
ResNet34 ImageNet aware 416 33.3(-1.0) 下载链接
ResNet34 ImageNet aware 320 30.3(-1.1) 下载链接
R50vd-dcn object365 baseline 608 41.4 下载链接
R50vd-dcn object365 aware 608 40.6(-0.8) 下载链接
R50vd-dcn object365 aware 416 37.5(-) 下载链接
R50vd-dcn object365 aware 320 34.1(-) 下载链接
  • YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型权重不同尺寸图片,表中部分模型提供了在608/416/320三种不同尺寸下的精度结果
  • YOLOv3-MobileNetV1使用离线(post)和在线(aware)两种量化方式,输入图像尺寸为608时精度分别降低1.41.2
  • YOLOv3-ResNet34使用离线(post)和在线(aware)两种量化方式,输入图像尺寸为608时精度分别降低0.51.1
  • YOLOv3-R50vd-dcn使用在线(aware)量化方式,输入图像尺寸为608时精度降低0.8
BlazeFace on WIDER FACE
模型 量化策略 输入尺寸 Easy Set Medium Set Hard Set 下载
BlazeFace baseline 640 91.5 89.2 79.7 下载链接
BlazeFace post 640 87.8(-3.7) 85.1(-3.9) 74.9(-4.8) 下载链接
BlazeFace aware 640 90.5(-1.0) 87.9(-1.3) 77.6(-2.1) 下载链接
BlazeFace-Lite baseline 640 90.9 88.5 78.1 下载链接
BlazeFace-Lite post 640 89.4(-1.5) 86.7(-1.8) 75.7(-2.4) 下载链接
BlazeFace-Lite aware 640 89.7(-1.2) 87.3(-1.2) 77.0(-1.1) 下载链接
BlazeFace-NAS baseline 640 83.7 80.7 65.8 下载链接
BlazeFace-NAS post 640 81.6(-2.1) 78.3(-2.4) 63.6(-2.2) 下载链接
BlazeFace-NAS aware 640 83.1(-0.6) 79.7(-1.0) 64.2(-1.6) 下载链接
  • BlazeFace系列模型中在线(aware)量化性能明显优于离线(post)量化
  • BlazeFace模型使用在线(aware)量化方式,在Easy/Medium/Hard数据集上精度分别降低1.0, 1.32.1
  • BlazeFace-Lite模型使用在线(aware)量化方式,在Easy/Medium/Hard数据集上精度分别降低1.2, 1.21.1
  • BlazeFace-NAS模型使用在线(aware)量化方式,在Easy/Medium/Hard数据集上精度分别降低0.6, 1.01.6

模型蒸馏

运行该示例前请安装PaddleSlim和Paddle1.6或更高版本
模型蒸馏教程
概述

该示例使用PaddleSlim提供的蒸馏策略对检测库中的模型进行蒸馏训练。 在阅读该示例前,建议您先了解以下内容:

已发布蒸馏模型见压缩模型库

安装PaddleSlim

可按照PaddleSlim使用文档中的步骤安装PaddleSlim

蒸馏策略说明

关于蒸馏API如何使用您可以参考PaddleSlim蒸馏API文档

MobileNetV1-YOLOv3在VOC数据集上的蒸馏

这里以ResNet34-YOLOv3蒸馏训练MobileNetV1-YOLOv3模型为例,首先,为了对student modelteacher model有个总体的认识,进一步确认蒸馏的对象,我们通过以下命令分别观察两个网络变量(Variables)的名称和形状:

# 观察student model的Variables
student_vars = []
for v in fluid.default_main_program().list_vars():
    try:
        student_vars.append((v.name, v.shape))
    except:
        pass
print("="*50+"student_model_vars"+"="*50)
print(student_vars)
# 观察teacher model的Variables
teacher_vars = []
for v in teacher_program.list_vars():
    try:
        teacher_vars.append((v.name, v.shape))
    except:
        pass
print("="*50+"teacher_model_vars"+"="*50)
print(teacher_vars)

经过对比可以发现,student modelteacher model输入到3个yolov3_loss的特征图分别为:

# student model
conv2d_20.tmp_1, conv2d_28.tmp_1, conv2d_36.tmp_1
# teacher model
conv2d_6.tmp_1, conv2d_14.tmp_1, conv2d_22.tmp_1

它们形状两两相同,且分别处于两个网络的输出部分。所以,我们用l2_loss对这几个特征图两两对应添加蒸馏loss。需要注意的是,teacher的Variable在merge过程中被自动添加了一个name_prefix,所以这里也需要加上这个前缀"teacher_",merge过程请参考蒸馏API文档

dist_loss_1 = l2_loss('teacher_conv2d_6.tmp_1', 'conv2d_20.tmp_1')
dist_loss_2 = l2_loss('teacher_conv2d_14.tmp_1', 'conv2d_28.tmp_1')
dist_loss_3 = l2_loss('teacher_conv2d_22.tmp_1', 'conv2d_36.tmp_1')

我们也可以根据上述操作为蒸馏策略选择其他loss,PaddleSlim支持的有FSP_loss, L2_loss, softmax_with_cross_entropy_loss 以及自定义的任何loss。

MobileNetV1-YOLOv3在COCO数据集上的蒸馏

这里以ResNet34-YOLOv3作为蒸馏训练的teacher网络, 对MobileNetV1-YOLOv3结构的student网络进行蒸馏。

COCO数据集作为目标检测任务的训练目标难度更大,意味着teacher网络会预测出更多的背景bbox,如果直接用teacher的预测输出作为student学习的soft label会有严重的类别不均衡问题。解决这个问题需要引入新的方法,详细背景请参考论文:Object detection at 200 Frames Per Second

为了确定蒸馏的对象,我们首先需要找到student和teacher网络得到的x,y,w,h,cls.objness等变量在PaddlePaddle框架中的实际名称(var.name)。进而根据名称取出这些变量,用teacher得到的结果指导student训练。找到的所有变量如下:

yolo_output_names = [
        'strided_slice_0.tmp_0', 'strided_slice_1.tmp_0',
        'strided_slice_2.tmp_0', 'strided_slice_3.tmp_0',
        'strided_slice_4.tmp_0', 'transpose_0.tmp_0', 'strided_slice_5.tmp_0',
        'strided_slice_6.tmp_0', 'strided_slice_7.tmp_0',
        'strided_slice_8.tmp_0', 'strided_slice_9.tmp_0', 'transpose_2.tmp_0',
        'strided_slice_10.tmp_0', 'strided_slice_11.tmp_0',
        'strided_slice_12.tmp_0', 'strided_slice_13.tmp_0',
        'strided_slice_14.tmp_0', 'transpose_4.tmp_0'
    ]

然后,就可以根据论文<<Object detection at 200 Frames Per Second>>的方法为YOLOv3中分类、回归、objness三个不同的head适配不同的蒸馏损失函数,并对分类和回归的损失函数用objness分值进行抑制,以解决前景背景类别不均衡问题。

训练

根据PaddleDetection/tools/train.py编写压缩脚本distill.py。 在该脚本中定义了teacher_model和student_model,用teacher_model的输出指导student_model的训练

执行示例

step1: 设置GPU卡

export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7

step2: 开始训练

# yolov3_mobilenet_v1在voc数据集上蒸馏
python slim/distillation/distill.py \
    -c configs/yolov3_mobilenet_v1_voc.yml \
    -t configs/yolov3_r34_voc.yml \
    --teacher_pretrained https://paddlemodels.bj.bcebos.com/object_detection/yolov3_r34_voc.tar
# yolov3_mobilenet_v1在COCO数据集上蒸馏
python slim/distillation/distill.py \
    -c configs/yolov3_mobilenet_v1.yml \
    -o use_fine_grained_loss=true \
    -t configs/yolov3_r34.yml \
    --teacher_pretrained https://paddlemodels.bj.bcebos.com/object_detection/yolov3_r34.tar

如果要调整训练卡数,需要调整配置文件yolov3_mobilenet_v1_voc.yml中的以下参数:

  • max_iters: 训练过程迭代总步数。
  • YOLOv3Loss.batch_size: 该参数表示单张GPU卡上的batch_size, 总batch_size是GPU卡数乘以这个值, batch_size的设定受限于显存大小。
  • LeaningRate.base_lr: 根据多卡的总batch_size调整base_lr,两者大小正相关,可以简单的按比例进行调整。
  • LearningRate.schedulers.PiecewiseDecay.milestones: 请根据batch size的变化对其调整。
  • LearningRate.schedulers.PiecewiseDecay.LinearWarmup.steps: 请根据batch size的变化对其进行调整。

以下为4卡训练示例,通过命令行-o参数覆盖yolov3_mobilenet_v1_voc.yml中的参数, 修改GPU卡数后应尽量确保总batch_size(GPU卡数*YoloTrainFeed.batch_size)不变, 以确保训练效果不因bs大小受影响:

# yolov3_mobilenet_v1在VOC数据集上蒸馏
CUDA_VISIBLE_DEVICES=0,1,2,3
python slim/distillation/distill.py \
    -c configs/yolov3_mobilenet_v1_voc.yml \
    -t configs/yolov3_r34_voc.yml \
    -o YOLOv3Loss.batch_size=16 \
    --teacher_pretrained https://paddlemodels.bj.bcebos.com/object_detection/yolov3_r34_voc.tar
# yolov3_mobilenet_v1在COCO数据集上蒸馏
CUDA_VISIBLE_DEVICES=0,1,2,3
python slim/distillation/distill.py \
    -c configs/yolov3_mobilenet_v1.yml \
    -t configs/yolov3_r34.yml \
    -o use_fine_grained_loss=true YOLOv3Loss.batch_size=16 \
    --teacher_pretrained https://paddlemodels.bj.bcebos.com/object_detection/yolov3_r34.tar
保存断点(checkpoint)

蒸馏任务执行过程中会自动保存断点。如果需要从断点继续训练请用-r参数指定checkpoint路径,示例如下:

# yolov3_mobilenet_v1在VOC数据集上恢复断点
python -u slim/distillation/distill.py \
-c configs/yolov3_mobilenet_v1_voc.yml \
-t configs/yolov3_r34_voc.yml \
-r output/yolov3_mobilenet_v1_voc/10000 \
--teacher_pretrained https://paddlemodels.bj.bcebos.com/object_detection/yolov3_r34_voc.tar
# yolov3_mobilenet_v1在COCO数据集上恢复断点
python -u slim/distillation/distill.py \
-c configs/yolov3_mobilenet_v1.yml \
-t configs/yolov3_r34.yml \
-o use_fine_grained_loss=true \
-r output/yolov3_mobilenet_v1/10000 \
--teacher_pretrained https://paddlemodels.bj.bcebos.com/object_detection/yolov3_r34.tar
评估

每隔snap_shot_iter步后会保存一个checkpoint模型可以用于评估,使用PaddleDetection目录下tools/eval.py评估脚本,并指定weights为训练得到的模型路径

运行命令为:

# yolov3_mobilenet_v1在VOC数据集上评估
export CUDA_VISIBLE_DEVICES=0
python -u tools/eval.py -c configs/yolov3_mobilenet_v1_voc.yml \
       -o weights=output/yolov3_mobilenet_v1_voc/model_final \
# yolov3_mobilenet_v1在COCO数据集上评估
export CUDA_VISIBLE_DEVICES=0
python -u tools/eval.py -c configs/yolov3_mobilenet_v1.yml \
       -o weights=output/yolov3_mobilenet_v1/model_final \
预测

每隔snap_shot_iter步后保存的checkpoint模型也可以用于预测,使用PaddleDetection目录下tools/infer.py评估脚本,并指定weights为训练得到的模型路径

Python预测

运行命令为:

# 使用yolov3_mobilenet_v1_voc模型进行预测
export CUDA_VISIBLE_DEVICES=0
python -u tools/infer.py -c configs/yolov3_mobilenet_v1_voc.yml \
                    --infer_img=demo/000000570688.jpg \
                    --output_dir=infer_output/ \
                    --draw_threshold=0.5 \
                    -o weights=output/yolov3_mobilenet_v1_voc/model_final
# 使用yolov3_mobilenet_v1_coco模型进行预测
export CUDA_VISIBLE_DEVICES=0
python -u tools/infer.py -c configs/yolov3_mobilenet_v1.yml \
                    --infer_img=demo/000000570688.jpg \
                    --output_dir=infer_output/ \
                    --draw_threshold=0.5 \
                    -o weights=output/yolov3_mobilenet_v1/model_final
示例结果
MobileNetV1-YOLO-V3-VOC
FLOPS 输入尺寸 每张GPU图片个数 推理时间(fps) Box AP 下载
baseline 608 16 104.291 76.2 下载链接
蒸馏后 608 16 106.914 79.0 下载链接
baseline 416 16 - 76.7 下载链接
蒸馏后 416 16 - 78.2 下载链接
baseline 320 16 - 75.3 下载链接
蒸馏后 320 16 - 75.5 下载链接
蒸馏后的结果用ResNet34-YOLO-V3做teacher,4GPU总batch_size64训练90000 iter得到
MobileNetV1-YOLO-V3-COCO
FLOPS 输入尺寸 每张GPU图片个数 推理时间(fps) Box AP 下载
baseline 608 16 78.302 29.3 下载链接
蒸馏后 608 16 78.523 31.4 下载链接
baseline 416 16 - 29.3 下载链接
蒸馏后 416 16 - 30.0 下载链接
baseline 320 16 - 27.0 下载链接
蒸馏后 320 16 - 27.1 下载链接
蒸馏后的结果用ResNet34-YOLO-V3做teacher,4GPU总batch_size64训练600000 iter得到

模型量化

运行该示例前请安装Paddle1.6或更高版本和PaddleSlim
模型量化压缩教程
概述

该示例使用PaddleSlim提供的量化压缩API对检测模型进行压缩。 在阅读该示例前,建议您先了解以下内容:

已发布量化模型见压缩模型库

安装PaddleSlim

可按照PaddleSlim使用文档中的步骤安装PaddleSlim。

训练

根据 tools/train.py 编写压缩脚本train.py。脚本中量化的步骤如下。

定义量化配置

config = { 'weight_quantize_type': 'channel_wise_abs_max', 'activation_quantize_type': 'moving_average_abs_max', 'quantize_op_types': ['depthwise_conv2d', 'mul', 'conv2d'], 'not_quant_pattern': ['yolo_output'] }

如何配置以及含义请参考PaddleSlim 量化API

插入量化反量化OP

使用PaddleSlim quant_aware API在Program中插入量化和反量化OP。

train_prog = quant_aware(train_prog, place, config, for_test=False)
关闭一些训练策略

因为量化要对Program做修改,所以一些会修改Program的训练策略需要关闭。sync_batch_norm 和量化多卡训练同时使用时会出错,原因暂不知,因此也需要将其关闭。

build_strategy.fuse_all_reduce_ops = False
build_strategy.sync_batch_norm = False
开始训练

您可以通过运行以下命令运行该示例。(该示例是在COCO数据集上训练yolov3-mobilenetv1, 替换模型和数据集的方法和检测库类似,直接替换相应的配置文件即可)

step1: 设置gpu卡

export CUDA_VISIBLE_DEVICES=0

step2: 开始训练

请在PaddleDetection根目录下运行。

python slim/quantization/train.py --not_quant_pattern yolo_output \
    --eval \
    -c ./configs/yolov3_mobilenet_v1.yml \
    -o max_iters=30000 \
    save_dir=./output/mobilenetv1 \
    LearningRate.base_lr=0.0001 \
    LearningRate.schedulers="[!PiecewiseDecay {gamma: 0.1, milestones: [10000]}]" \
    pretrain_weights=https://paddlemodels.bj.bcebos.com/object_detection/yolov3_mobilenet_v1.tar

注意: 目前量化训练中只支持边训练边评估,所以训练时必需携带--eval参数,否则无法训练与保存模型。这个量化中的问题未来会持续改进。

通过命令行覆设置max_iters选项,因为量化的训练轮次比正常训练小很多,所以需要修改此选项。 如果要调整训练卡数,可根据需要调整配置文件yolov3_mobilenet_v1_voc.yml中的以下参数:
  • max_iters: 训练的总轮次。
  • LeaningRate.base_lr: 根据多卡的总batch_size调整base_lr,两者大小正相关,可以简单的按比例进行调整。
  • LearningRate.schedulers.PiecewiseDecay.milestones: 请根据batch size的变化对其调整。

通过python slim/quantization/train.py --help查看可配置参数。 通过python ./tools/configure.py help ${option_name}查看如何通过命令行覆盖配置文件中的参数。

PACT自定义量化
python slim/quantization/train.py \
    --eval \
    -c ./configs/yolov3_mobilenet_v3.yml \
    -o max_iters=30000 \
    save_dir=./output/mobilenetv3 \
    LearningRate.base_lr=0.0001 \
    LearningRate.schedulers="[!PiecewiseDecay {gamma: 0.1, milestones: [10000]}]" \
    pretrain_weights=https://paddlemodels.bj.bcebos.com/object_detection/yolov3_mobilenet_v3.pdparams \
    --use_pact=True
  • 在量化训练时,将--use_pact=True,即可选择PACT自定义量化
训练时的模型结构

PaddleSlim 量化API文档中介绍了paddleslim.quant.quant_awarepaddleslim.quant.convert两个接口。 paddleslim.quant.quant_aware 作用是在网络中的conv2d、depthwise_conv2d、mul等算子的各个输入前插入连续的量化op和反量化op,并改变相应反向算子的某些输入。示例图如下:


图1:应用 paddleslim.quant.quant_aware 后的结果

保存断点(checkpoint)

在脚本中使用保存checkpoint的代码为:

# insert quantize op in eval_prog
eval_prog = quant_aware(eval_prog, place, config, for_test=True)
checkpoint.save(exe, eval_prog, os.path.join(save_dir, save_name))
边训练边测试

在脚本中边训练边测试得到的测试精度是基于图1中的网络结构进行的。

评估
最终评估模型

paddleslim.quant.convert 主要用于改变Program中量化op和反量化op的顺序,即将类似图1中的量化op和反量化op顺序改变为图2中的布局。除此之外,paddleslim.quant.convert 还会将conv2ddepthwise_conv2dmul等算子参数变为量化后的int8_t范围内的值(但数据类型仍为float32),示例如图2:


图2:paddleslim.quant.convert 后的结果

所以在调用 paddleslim.quant.convert 之后,才得到最终的量化模型。此模型可使用PaddleLite进行加载预测,可参见教程Paddle-Lite如何加载运行量化模型

评估脚本

使用脚本slim/quantization/eval.py进行评估。

  • 定义配置。使用和训练脚本中一样的量化配置,以得到和量化训练时同样的模型。
  • 使用 paddleslim.quant.quant_aware 插入量化和反量化op。
  • 使用 paddleslim.quant.convert 改变op顺序,得到最终量化模型进行评估。

评估命令:

python slim/quantization/eval.py --not_quant_pattern yolo_output  -c ./configs/yolov3_mobilenet_v1.yml \
-o weights=./output/mobilenetv1/yolov3_mobilenet_v1/best_model
导出模型

使用脚本slim/quantization/export_model.py导出模型。

  • 定义配置。使用和训练脚本中一样的量化配置,以得到和量化训练时同样的模型。
  • 使用 paddleslim.quant.quant_aware 插入量化和反量化op。
  • 使用 paddleslim.quant.convert 改变op顺序,得到最终量化模型进行评估。

导出模型命令:

 python slim/quantization/export_model.py --not_quant_pattern yolo_output  -c ./configs/yolov3_mobilenet_v1.yml --output_dir ${save path} \
-o weights=./output/mobilenetv1/yolov3_mobilenet_v1/best_model
预测
python预测

在脚本slim/quantization/infer.py中展示了如何使用fluid python API加载使用预测模型进行预测。

运行命令示例:

python slim/quantization/infer.py --not_quant_pattern yolo_output \
-c ./configs/yolov3_mobilenet_v1.yml \
--infer_dir ./demo \
-o weights=./output/mobilenetv1/yolov3_mobilenet_v1/best_model
PaddleLite预测

导出模型步骤中导出的FP32模型可使用PaddleLite进行加载预测,可参见教程Paddle-Lite如何加载运行量化模型

量化模型
训练策略
  • 量化策略post为使用离线量化得到的模型,aware为在线量化训练得到的模型。
YOLOv3 on COCO
骨架网络 预训练权重 量化策略 输入尺寸 Box AP 下载
MobileNetV1 ImageNet post 608 27.9 下载链接
MobileNetV1 ImageNet post 416 28.0 下载链接
MobileNetV1 ImageNet post 320 26.0 下载链接
MobileNetV1 ImageNet aware 608 28.1 下载链接
MobileNetV1 ImageNet aware 416 28.2 下载链接
MobileNetV1 ImageNet aware 320 25.8 下载链接
ResNet34 ImageNet post 608 35.7 下载链接
ResNet34 ImageNet aware 608 35.2 下载链接
ResNet34 ImageNet aware 416 33.3 下载链接
ResNet34 ImageNet aware 320 30.3 下载链接
R50vd-dcn object365 aware 608 40.6 下载链接
R50vd-dcn object365 aware 416 37.5 下载链接
R50vd-dcn object365 aware 320 34.1 下载链接
FAQ

神经网络搜索

运行该示例前请安装Paddle1.6或更高版本
神经网络搜索(NAS)教程
概述

我们选取人脸检测的BlazeFace模型作为神经网络搜索示例,该示例使用PaddleSlim 辅助完成神经网络搜索实验,具体技术细节,请您参考神经网络搜索策略
基于PaddleSlim进行搜索实验过程中,搜索限制条件可以选择是浮点运算数(FLOPs)限制还是硬件延时(latency)限制,硬件延时限制需要提供延时表。本示例提供一份基于blazeface搜索空间的硬件延时表,名称是latency_855.txt(基于PaddleLite在骁龙855上测试的延时),可以直接用该表进行blazeface的硬件延时搜索实验。
硬件延时表每个字段的含义可以参考:硬件延时表说明

定义搜索空间

在BlazeFace模型的搜索实验中,我们采用了SANAS的方式进行搜索,本次实验会对网络模型中的通道数和卷积核尺寸进行搜索。 所以我们定义了如下搜索空间:

  • 初始化通道模块blaze_filter_num1:定义了BlazeFace第一个模块中通道数变化区间,人为定义了较小的通道数区间;
  • 单blaze模块blaze_filter_num2: 定义了BlazeFace单blaze模块中通道数变化区间,人为定义了适中的通道数区间;
  • 过渡blaze模块mid_filter_num:定义了BlazeFace由单blaze模块到双blaze模块的过渡区间;
  • 双blaze模块double_filter_num:定义了BlazeFace双blaze模块中通道数变化区间,人为定义了较大的通道数区间;
  • 卷积核尺寸use_5x5kernel:定义了BlazeFace中卷积和尺寸大小是3x3或者5x5。由于提供的延时表中只统计了3x3卷积的延时,所以启动硬件延时搜索实验时,需要把卷积核尺寸固定为3x3。

根据定义的搜索空间各个区间,我们的搜索空间tokens共9位,变化区间在([0, 0, 0, 0, 0, 0, 0, 0, 0], [7, 9, 12, 12, 6, 6, 6, 6, 2])范围内。硬件延时搜索实验时,token的变化区间在([0, 0, 0, 0, 0, 0, 0, 0, 0], [7, 9, 12, 12, 6, 6, 6, 6, 1])范围内。

9位tokens分别表示:

  • tokens[0]:初始化通道数 = blaze_filter_num1[tokens[0]]
  • tokens[1]:单blaze模块通道数 = blaze_filter_num2[tokens[1]]
  • tokens[2]-tokens[3]:双blaze模块起始通道数 = double_filter_num[tokens[2/3]]
  • tokens[4]-tokens[7]:过渡blaze模块通道数 = [tokens[4/5/6/7]]
  • tokens[8]:卷积核尺寸使用5x5 = True if use_5x5kernel[tokens[8]] else False

我们人为定义三个单blaze模块与4个双blaze模块,定义规则如下:

blaze_filters = [[self.blaze_filter_num1[tokens[0]], self.blaze_filter_num1[tokens[0]]],
                [self.blaze_filter_num1[tokens[0]], self.blaze_filter_num2[tokens[1]], 2],
                [self.blaze_filter_num2[tokens[1]], self.blaze_filter_num2[tokens[1]]]]

double_blaze_filters = [
       [self.blaze_filter_num2[tokens[1]], self.mid_filter_num[tokens[4]], self.double_filter_num[tokens[2]], 2],
       [self.double_filter_num[tokens[2]], self.mid_filter_num[tokens[5]], self.double_filter_num[tokens[2]]],
       [self.double_filter_num[tokens[2]], self.mid_filter_num[tokens[6]], self.double_filter_num[tokens[3]], 2],
       [self.double_filter_num[tokens[3]], self.mid_filter_num[tokens[7]], self.double_filter_num[tokens[3]]]]

blaze_filters与double_blaze_filters字段请参考blazenet.py中定义。

初始化tokens为:[2, 1, 3, 8, 2, 1, 2, 1, 1]。

开始搜索

首先需要安装PaddleSlim,请参考安装教程

然后进入 slim/nas目录中,修改blazeface.yml配置,配置文件中搜索配置字段含义请参考NAS-API文档

配置文件blazeface.yml中的Constraint字段表示当前搜索实验的搜索限制条件实例:

  • ctype:具体的限制条件,可以设置为flops或者latency,分别表示浮点运算数限制和硬件延时限制。
  • max_constraint:限制条件的最大值。
  • min_constraint:限制条件的最小值。
  • table_file:读取的硬件延时表文件的路径,这个字段只有在硬件延时搜索实验中才会用到。

然后开始搜索实验:

cd slim/nas
python -u train_nas.py -c blazeface.yml

注意:

搜索过程中为了加速,在blazeface.yml中去掉了数据预处理CropImageWithDataAchorSampling的操作。

训练完成后会获得最佳tokens,以及对应的BlazeFace-NAS的网络结构:

------------->>> BlazeFace-NAS structure start: <<<----------------
BlazeNet:
  blaze_filters: XXX
  double_blaze_filters: XXX
  use_5x5kernel: XXX
  with_extra_blocks: XXX
  lite_edition: XXX
-------------->>> BlazeFace-NAS structure end! <<<-----------------
训练、评估与预测
  • (1)修改配置文件:

根据搜索得到的BlazeFace-NAS的网络结构修改blazeface.yml中的BlazeNet模块。

  • (2)训练、评估与预测:

启动完整的训练评估实验,可参考PaddleDetection的训练、评估与预测流程

实验结果

请参考人脸检测模型库中BlazeFace-NAS的实验结果。

FAQ
  • 运行报错:socket.error: [Errno 98] Address already in use

解决方法:当前端口被占用,请修改blazeface.yml中的server_port端口。

  • 运行报错:not enough space for reason[failed to malloc 601 pages...

解决方法:当前reader的共享存储队列空间不足,请增大blazeface.yml中的memsize

模型剪枝

卷积层通道剪裁教程

请确保已正确安装PaddleDetection及其依赖。

该文档介绍如何使用PaddleSlim的卷积通道剪裁接口对检测库中的模型的卷积层的通道数进行剪裁。

在检测库中,可以直接调用PaddleDetection/slim/prune/prune.py脚本实现剪裁,在该脚本中调用了PaddleSlim的paddleslim.prune.Pruner接口。

该教程中所示操作,如无特殊说明,均在PaddleDetection/路径下执行。

已发布裁剪模型见压缩模型库

1. 数据准备

请参考检测库数据下载文档准备数据。

2. 模型选择

通过-c选项指定待裁剪模型的配置文件的相对路径,更多可选配置文件请参考: 检测库配置文件

对于剪裁任务,原模型的权重不一定对剪裁后的模型训练的重训练有贡献,所以加载原模型的权重不是必需的步骤。

通过-o pretrain_weights指定模型的预训练权重,可以指定url或本地文件系统的路径。如下所示:

-o pretrain_weights=https://paddlemodels.bj.bcebos.com/object_detection/yolov3_mobilenet_v1_voc.tar

-o weights=output/yolov3_mobilenet_v1_voc/model_final

官方已发布的模型请参考: 模型库

3. 确定待分析参数

我们通过剪裁卷积层参数达到缩减卷积层通道数的目的,在剪裁之前,我们需要确定待裁卷积层的参数的名称。 通过以下命令查看当前模型的所有参数:

python slim/prune/prune.py \
-c ./configs/yolov3_mobilenet_v1_voc.yml \
--print_params

通过观察参数名称和参数的形状,筛选出所有卷积层参数,并确定要裁剪的卷积层参数。

4. 分析待剪裁参数敏感度

可通过敏感度分析脚本分析待剪裁参数敏感度得到合适的剪裁率,敏感度分析工具见敏感度分析

5. 启动剪裁任务

使用prune.py启动裁剪任务时,通过--pruned_params选项指定待裁剪的参数名称列表,参数名之间用空格分隔,通过--pruned_ratios选项指定各个参数被裁掉的比例。

python slim/prune/prune.py \
-c ./configs/yolov3_mobilenet_v1_voc.yml \
--pruned_params "yolo_block.0.0.0.conv.weights,yolo_block.0.0.1.conv.weights,yolo_block.0.1.0.conv.weights" \
--pruned_ratios="0.2,0.3,0.4"
6. 评估剪裁模型

训练剪裁任务完成后,可通过eval.py评估剪裁模型精度,通过--pruned_params--pruned_ratios指定裁剪的参数名称列表和各参数裁剪比例。

python slim/prune/eval.py \
-c ./configs/yolov3_mobilenet_v1_voc.yml \
--pruned_params "yolo_block.0.0.0.conv.weights,yolo_block.0.0.1.conv.weights,yolo_block.0.1.0.conv.weights" \
--pruned_ratios="0.2,0.3,0.4" \
-o weights=output/yolov3_mobilenet_v1_voc/model_final
7. 模型导出

如果想要将剪裁模型接入到C++预测库或者Serving服务,可通过export_model.py导出该模型。

python slim/prune/export_model.py \
-c ./configs/yolov3_mobilenet_v1_voc.yml \
--pruned_params "yolo_block.0.0.0.conv.weights,yolo_block.0.0.1.conv.weights,yolo_block.0.1.0.conv.weights" \
--pruned_ratios="0.2,0.3,0.4" \
-o weights=output/yolov3_mobilenet_v1_voc/model_final
8. 扩展模型

如果需要对自己的模型进行修改,可以参考prune.py中对paddleslim.prune.Pruner接口的调用方式,基于自己的模型训练脚本进行修改。 本节我们介绍的剪裁示例,需要用户根据先验知识指定每层的剪裁率,除此之外,PaddleSlim还提供了敏感度分析等功能,协助用户选择合适的剪裁率。更多详情请参考:PaddleSlim使用文档

9. 更多示例与注意事项
9.1 faster_rcnn与mask_rcnn

当前PaddleSlim的剪裁功能不支持剪裁循环体或条件判断语句块内的卷积层,请避免剪裁循环和判断语句块前的一个卷积和语句块内部的卷积。

对于faster_rcnn_r50mask_rcnn_r50网络,请剪裁卷积res4f_branch2c之前的卷积。

faster_rcnn_r50剪裁示例如下:

# demo for faster_rcnn_r50
python slim/prune/prune.py -c ./configs/faster_rcnn_r50_1x.yml --pruned_params "res4f_branch2b_weights,res4f_branch2a_weights" --pruned_ratios="0.3,0.4" --eval

mask_rcnn_r50剪裁示例如下:

# demo for mask_rcnn_r50
python slim/prune/prune.py -c ./configs/mask_rcnn_r50_1x.yml --pruned_params "res4f_branch2b_weights,res4f_branch2a_weights" --pruned_ratios="0.2,0.3" --eval
卷积层敏感度分析教程

请确保已正确安装PaddleDetection及其依赖。

该文档介绍如何使用PaddleSlim的敏感度分析接口对检测库中的模型的卷积层进行敏感度分析。

在检测库中,可以直接调用PaddleDetection/slim/sensitive/sensitive.py脚本实现敏感度分析,在该脚本中调用了PaddleSlim的paddleslim.prune.sensitivity接口。

该教程中所示操作,如无特殊说明,均在PaddleDetection/slim/sensitive/路径下执行。

数据准备

请参考检测库数据模块文档准备数据。

模型选择

通过-c选项指定待分析模型的配置文件的相对路径,更多可选配置文件请参考: 检测库配置文件

通过-o weights指定模型的权重,可以指定url或本地文件系统的路径。如下所示:

-o weights=https://paddlemodels.bj.bcebos.com/object_detection/yolov3_mobilenet_v1_voc.tar

-o weights=output/yolov3_mobilenet_v1_voc/model_final

官方已发布的模型请参考: 模型库

确定待分析参数

在计算敏感度之前,需要查出待分析的卷积层的参数的名称。通过以下命令查看当前模型的所有参数:

python sensitive.py \
-c ../../configs/yolov3_mobilenet_v1_voc.yml \
--print_params

通过观察参数名称和参数的形状,筛选出所有卷积层参数,并确定要分析的卷积层参数。

执行分析

通过选项--pruned_params指定待分析的卷积层参数名,参数名间以英文字符逗号分割。 通过选项--sensitivities_file指定敏感度信息保存的文件,敏感度信息会追加到该文件中。重启敏感度计算任务,该文件中已计算的信息不会再被计算。

示例如下:

nohup python sensitive.py \
-c ../../configs/yolov3_mobilenet_v1_voc.yml \
--pruned_params "yolo_block.0.0.0.conv.weights,yolo_block.0.0.1.conv.weights,yolo_block.0.1.0.conv.weights,yolo_block.0.1.1.conv.weights,yolo_block.0.2.conv.weights,yolo_block.0.tip.conv.weights,yolo_block.1.0.0.conv.weights,yolo_block.1.0.1.conv.weights,yolo_block.1.1.0.conv.weights,yolo_block.1.1.1.conv.weights,yolo_block.1.2.conv.weights,yolo_block.1.tip.conv.weights,yolo_block.2.0.0.conv.weights,yolo_block.2.0.1.conv.weights,yolo_block.2.1.0.conv.weights,yolo_block.2.1.1.conv.weights,yolo_block.2.2.conv.weights,yolo_block.2.tip.conv.weights" \
--sensitivities_file "./demo.data"

执行python sensitive.py --help查看更多选项。

分析敏感度信息

可以通过paddleslim.prune.load_sensitivities从文件中加载敏感度信息,并使用Python数据分析工具画图分析。下图展示了MobileNetv1-YOLOv3-VOC模型在VOC数据上的敏感度信息:

通过画图分析,可以确定一组合适的剪裁率,或者通过paddleslim.prune.get_ratios_by_loss获得合适的剪裁率。

分布式计算敏感度信息

如果模型评估速度比较慢,可以考虑使用多进程加速敏感度计算的过程。 通过--pruned_ratios指定当前进程计算敏感度时用的剪裁率,默认为"0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9"。可以将该组剪切率分配到不同的进程进行计算,如下所示:

# 进程1
nohup python sensitive.py \
-c ../../configs/yolov3_mobilenet_v1_voc.yml \
--pruned_params "yolo_block.0.0.0.conv.weights" \
--pruned_ratios "0.1 0.2 0.3 0.4 0.5"
--sensitivities_file "./demo.data.1"
# 进程2
nohup python sensitive.py \
-c ../../configs/yolov3_mobilenet_v1_voc.yml \
--pruned_params "yolo_block.0.0.0.conv.weights" \
--pruned_ratios "0.6 0.7 0.8 0.9"
--sensitivities_file "./demo.data.2"

待以上两个进程执行完毕,通过paddleslim.prune.merge_sensitivedemo.data.1demo.data.2两个文件合并分析。

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

特色模型

YOLOv3增强模型


简介

YOLOv3 是由 Joseph RedmonAli Farhadi 提出的单阶段检测器, 该检测 器与达到同样精度的传统目标检测方法相比,推断速度能达到接近两倍.

PaddleDetection实现版本中使用了 Bag of Freebies for Training Object Detection Neural Networks 中提出的图像增强和label smooth等优化方法,精度优于darknet框架的实现版本,在COCO-2017数据集上,YOLOv3(DarkNet)达到mAP(0.50:0.95)= 38.9的精度,比darknet实现版本的精度(33.0)要高5.9。同时,在推断速度方面,基于Paddle预测库的加速方法,推断速度比darknet高30%。

在此基础上,PaddleDetection对YOLOv3进一步改进,进一步提升了速度和精度,最终在COCO mAP上可以达到43.2。

方法描述

1.将YOLOv3骨架网络更换为ResNet50-VD。ResNet50-VD网络相比原生的DarkNet53网络在速度和精度上都有一定的优势,且相较DarkNet53 ResNet系列更容易扩展,针对自己业务场景可以选择ResNet18、34、101等不同结构作为检测模型的主干网络。

2.引入Deformable Convolution v2(可变形卷积)替代原始卷积操作,Deformable Convolution已经在多个视觉任务中广泛验证过其效果,在Yolo v3增强模型中考虑到速度与精度的平衡,我们仅使用Deformable Convolution替换了主干网络中Stage5部分的3x3卷积。

3.在FPN部分增加DropBlock模块,提高模型泛化能力。Dropout操作如下图(b)中所示是分类网络中广泛使用的增强模型泛化能力的重要手段之一。DropBlock算法相比于Dropout算法,在Drop特征的时候会集中Drop掉某一块区域,更适应于在检测任务中提高网络泛化能力。

_images/dropblock.pngimage-20200204141739840

4.Yolo v3作为一阶段检测网络,在定位精度上相比Faster RCNN,Cascade RCNN等网络结构有着其天然的劣势,增加IoU Loss分支,可以一定程度上提高BBox定位精度,缩小一阶段和两阶段检测网络的差距。

5.增加IoU Aware分支,预测输出BBox和真实BBox的IoU,修正用于NMS的评分,可进一步提高YOLOV3的预测性能。

6.使用Object365数据集训练得到的模型作为coco数据集上的预训练模型,Object365数据集包含约60万张图片以及365种类别,相比coco数据集进行预训练可以进一步提高YOLOv3的精度。

使用方法

模型训练
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
python tools/train.py -c configs/dcn/yolov3_r50vd_dcn_db_iouloss_obj365_pretrained_coco.yml

更多模型参数请使用python tools/train.py --help查看,或参考训练、评估及参数说明文档

模型效果
模型 预训练模型 验证集 mAP V100 python 预测速度(FPS)1 V100 paddle预测库速度(ms/image)2 P4 paddle预测库速度(ms/image) 2 下载 配置文件
YOLOv3 DarkNet DarkNet pretrain 38.9 48.55 原生:19.63
tensorRT-FP32: 18.01
tensorRT-FP16: 11.47
原生:54.10
tensorRT-FP32: 47.44
下载链接 配置文件
YOLOv3 ResNet50_vd DCN ImageNet pretrain 39.1 50.80 原生:17.04
tensorRT-FP32: 16.28
tensorRT-FP16: 11.16
原生:40.01
tensorRT-FP32: 36.66
下载链接 配置文件
YOLOv3 ResNet50_vd DCN Object365 pretrain 42.5 50.41 原生:16.76
tensorRT-FP32: 16.04
tensorRT-FP16: 10.70
原生:39.64
tensorRT-FP32: 35.93
下载链接 配置文件
YOLOv3 ResNet50_vd DCN DropBlock Object365 pretrain 42.8 49.97 原生:16.55
tensorRT-FP32: 16.07
tensorRT-FP16: 10.69
原生:39.72
tensorRT-FP32: 35.98
下载链接 配置文件
YOLOv3 ResNet50_vd DCN DropBlock IoULoss Object365 pretrain 43.2 49.91 原生:16.46
tensorRT-FP32: 15.83
tensorRT-FP16: 10.80
原生:39.58
tensorRT-FP32: 35.61
下载链接 配置文件
YOLOv3 ResNet50_vd DCN DropBlock IoU-Aware Object365 pretrain 43.6 48.19 原生:17.74
tensorRT-FP32: 16.73
tensorRT-FP16: 11.74
原生:41.39
tensorRT-FP32: 37.75
下载链接 配置文件

[1]V100 python 预测速度是在一张Tesla V100的GPU上通过tools/eval.py测试所有验证集得到,单位是fps(图片数/秒), cuDNN版本是7.5,包括数据加载、网络前向执行和后处理, batch size是1。

[2]paddle预测库测试时,输入图片大小为640x640; 去掉前10轮warmup时间,测试100轮的平均时间; 开启了参数FLAGS_cudnn_exhaustive_search=True;使用代码deploy/python/infer.py测试

English | 简体中文

移动端模型库

模型

PaddleDetection目前提供一系列针对移动应用进行优化的模型,主要支持以下结构:

骨干网络 结构 输入大小 图片/gpu 1 学习率策略 Box AP 下载 PaddleLite模型下载
MobileNetV3 Small SSDLite 320 64 400K (cosine) 16.2 链接 链接
MobileNetV3 Small SSDLite Quant 2 320 64 400K (cosine) 15.4 链接 链接
MobileNetV3 Large SSDLite 320 64 400K (cosine) 23.3 链接 链接
MobileNetV3 Large SSDLite Quant 2 320 64 400K (cosine) 22.6 链接 链接
MobileNetV3 Large w/ FPN Cascade RCNN 320 2 500k (cosine) 25.0 链接 链接
MobileNetV3 Large w/ FPN Cascade RCNN 640 2 500k (cosine) 30.2 链接 链接
MobileNetV3 Large YOLOv3 320 8 500K 27.1 链接 链接
MobileNetV3 Large YOLOv3 Prune 3 320 8 - 24.6 链接 链接

注意:

评测结果

  • 模型使用 Paddle-Lite 2.6 (即将发布) 在下列平台上进行了测试
    • Qualcomm Snapdragon 625
    • Qualcomm Snapdragon 835
    • Qualcomm Snapdragon 845
    • Qualcomm Snapdragon 855
    • HiSilicon Kirin 970
    • HiSilicon Kirin 980
  • 单CPU线程 (单位: ms)
SD625 SD835 SD845 SD855 Kirin 970 Kirin 980
SSDLite Large 289.071 134.408 91.933 48.2206 144.914 55.1186
SSDLite Large Quant
SSDLite Small 122.932 57.1914 41.003 22.0694 61.5468 25.2106
SSDLite Small Quant
YOLOv3 baseline 1082.5 435.77 317.189 155.948 536.987 178.999
YOLOv3 prune 253.98 131.279 89.4124 48.2856 122.732 55.8626
Cascade RCNN 320 286.526 125.635 87.404 46.184 149.179 52.9994
Cascade RCNN 640 1115.66 495.926 351.361 189.722 573.558 207.917
  • 4 CPU线程 (单位: ms)
SD625 SD835 SD845 SD855 Kirin 970 Kirin 980
SSDLite Large 107.535 51.1382 34.6392 20.4978 50.5598 24.5318
SSDLite Large Quant
SSDLite Small 51.5704 24.5156 18.5486 11.4218 24.9946 16.7158
SSDLite Small Quant
YOLOv3 baseline 413.486 184.248 133.624 75.7354 202.263 126.435
YOLOv3 prune 98.5472 53.6228 34.4306 21.3112 44.0722 31.201
Cascade RCNN 320 131.515 59.6026 39.4338 23.5802 58.5046 36.9486
Cascade RCNN 640 473.083 224.543 156.205 100.686 231.108 138.391

SSDLite量化说明

在SSDLite模型中我们采用完整量化训练的方式对模型进行训练,在8卡GPU下共训练40万轮,训练中将res_conv1se_block固定不训练,执行指令为:

python slim/quantization/train.py --not_quant_pattern res_conv1 se_block \
        -c configs/ssd/ssdlite_mobilenet_v3_large.yml \
        --eval

更多量化教程请参考模型量化压缩教程

YOLOv3剪裁说明

首先对YOLO检测头进行剪裁,然后再使用 YOLOv3-ResNet34 作为teacher网络对剪裁后的模型进行蒸馏, teacher网络在COCO上的mAP为31.4 (输入大小320*320).

可以使用如下两种方式进行剪裁:

  • 固定比例剪裁, 整体剪裁率是86%

    --pruned_params="yolo_block.0.0.0.conv.weights,yolo_block.0.0.1.conv.weights,yolo_block.0.1.0.conv.weights,yolo_block.0.1.1.conv.weights,yolo_block.0.2.conv.weights,yolo_block.0.tip.conv.weights,yolo_block.1.0.0.conv.weights,yolo_block.1.0.1.conv.weights,yolo_block.1.1.0.conv.weights,yolo_block.1.1.1.conv.weights,yolo_block.1.2.conv.weights,yolo_block.1.tip.conv.weights,yolo_block.2.0.0.conv.weights,yolo_block.2.0.1.conv.weights,yolo_block.2.1.0.conv.weights,yolo_block.2.1.1.conv.weights,yolo_block.2.2.conv.weights,yolo_block.2.tip.conv.weights" \
    --pruned_ratios="0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.875,0.875,0.875,0.875,0.875,0.875"
    
  • 使用 FPGM 算法剪裁:

    --prune_criterion=geometry_median
    

敬请关注后续发布

  • [ ] 更多模型
  • [ ] 量化模型

服务器端实用目标检测方案

简介

  • 近年来,学术界和工业界广泛关注图像中目标检测任务。基于PaddleClas中SSLD蒸馏方案训练得到的ResNet50_vd预训练模型(ImageNet1k验证集上Top1 Acc为82.39%),结合PaddleDetection中的丰富算子,飞桨提供了一种面向服务器端实用的目标检测方案PSS-DET(Practical Server Side Detection)。基于COCO2017目标检测数据集,V100单卡预测速度为为61FPS时,COCO mAP可达41.6%;预测速度为20FPS时,COCO mAP可达47.8%。
  • 以标准的Faster RCNN ResNet50_vd FPN为例,下表给出了PSS-DET不同的模块的速度与精度收益。
Trick Train scale Test scale COCO mAP Infer speed/FPS
baseline 640x640 640x640 36.4% 43.589
+test proposal=pre/post topk 500/300 640x640 640x640 36.2% 52.512
+fpn channel=64 640x640 640x640 35.1% 67.450
+ssld pretrain 640x640 640x640 36.3% 67.450
+ciou loss 640x640 640x640 37.1% 67.450
+DCNv2 640x640 640x640 39.4% 60.345
+3x, multi-scale training 640x640 640x640 41.0% 60.345
+auto augment 640x640 640x640 41.4% 60.345
+libra sampling 640x640 640x640 41.6% 60.345

基于该实验结论,PaddleDetection结合Cascade RCNN,使用更大的训练与评估尺度(1000x1500),最终在单卡V100上速度为20FPS,COCO mAP达47.8%。下图给出了目前类似速度的目标检测方法的速度与精度指标。

_images/pssdet.pngpssdet

注意

这里为了更方便地对比,统一将V100的预测耗时乘以1.2倍,近似转化为Titan V的预测耗时。

模型库

骨架网络 网络类型 每张GPU图片个数 学习率策略 推理时间(fps) Box AP Mask AP 下载 配置文件
ResNet50-vd-FPN-Dcnv2 Faster 2 3x 61.425 41.6 - 下载链接 配置文件
ResNet50-vd-FPN-Dcnv2 Cascade Faster 2 3x 20.001 47.8 - 下载链接 配置文件
ResNet101-vd-FPN-Dcnv2 Cascade Faster 2 3x 19.523 49.4 - 下载链接 配置文件

:generic文件夹下面的配置文件对应的预训练模型均只支持预测,不支持训练与评估。

Anchor Free系列模型

简介

目前主流的检测算法大体分为两类: single-stage和two-stage,其中single-stage的经典算法包括SSD, YOLO等,two-stage方法有RCNN系列模型,两大类算法在PaddleDetection Model Zoo中均有给出,它们的共同特点是先定义一系列密集的,大小不等的anchor区域,再基于这些先验区域进行分类和回归,这种方式极大的受限于anchor自身的设计。随着CornerNet的提出,涌现了多种anchor free方法,PaddleDetection也集成了一系列anchor free算法。

模型库与基线

下表中展示了PaddleDetection当前支持的网络结构,具体细节请参考算法细节

ResNet50 ResNet50-vd Hourglass104 DarkNet53
CornerNet-Squeeze x x
FCOS x x x
TTFNet x x x
模型库
COCO数据集上的mAP
网络结构 骨干网络 图片个数/GPU 预训练模型 mAP FPS 模型下载 配置文件
CornerNet-Squeeze Hourglass104 14 34.5 35.5 下载链接 配置文件
CornerNet-Squeeze ResNet50-vd 14 faster_rcnn_r50_vd_fpn_2x 32.7 47.01 下载链接 配置文件
CornerNet-Squeeze-dcn ResNet50-vd 14 faster_rcnn_dcn_r50_vd_fpn_2x 34.9 40.43 下载链接 配置文件
CornerNet-Squeeze-dcn-mixup-cosine* ResNet50-vd 14 faster_rcnn_dcn_r50_vd_fpn_2x 38.2 39.70 下载链接 配置文件
FCOS ResNet50 2 ResNet50_cos_pretrained 39.8 18.85 下载链接 配置文件
FCOS+multiscale_train ResNet50 2 ResNet50_cos_pretrained 42.0 19.05 下载链接 配置文件
FCOS+DCN ResNet50 2 ResNet50_cos_pretrained 44.4 13.66 下载链接 配置文件
TTFNet DarkNet53 12 DarkNet53_pretrained 32.9 85.92 下载链接 配置文件

注意:

  • 模型FPS在Tesla V100单卡环境中通过tools/eval.py进行测试
  • CornerNet-Squeeze要求使用PaddlePaddle1.8及以上版本或适当的develop版本
  • CornerNet-Squeeze中使用ResNet结构的骨干网络时,加入了FPN结构,骨干网络的输出feature map采用FPN中的P3层输出。
  • *CornerNet-Squeeze-dcn-mixup-cosine是基于原版CornerNet-Squeeze优化效果最好的模型,在ResNet的骨干网络基础上增加mixup预处理和使用cosine_decay
  • FCOS使用GIoU loss、用location分支预测centerness、左上右下角点偏移量归一化和ground truth中心匹配策略
  • Cornernet-Squeeze模型依赖corner_pooling op,该op在ppdet/ext_op中编译得到,具体编译方式请参考自定义OP的编译过程

算法细节

CornerNet-Squeeze

简介: CornerNet-SqueezeCornernet基础上进行改进,预测目标框的左上角和右下角的位置,同时参考SqueezeNet和MobileNet的特点,优化了CornerNet骨干网络Hourglass-104,大幅提升了模型预测速度,相较于原版YOLO-v3,在训练精度和推理速度上都具备一定优势。

特点:

  • 使用corner_pooling获取候选框左上角和右下角的位置
  • 替换Hourglass-104中的residual block为SqueezeNet中的fire-module
  • 替换第二层3x3卷积为3x3深度可分离卷积
FCOS

简介: FCOS是一种密集预测的anchor-free检测算法,使用RetinaNet的骨架,直接在feature map上回归目标物体的长宽,并预测物体的类别以及centerness(feature map上像素点离物体中心的偏移程度),centerness最终会作为权重来调整物体得分。

特点:

  • 利用FPN结构在不同层预测不同scale的物体框,避免了同一feature map像素点处有多个物体框重叠的情况
  • 通过center-ness单层分支预测当前点是否是目标中心,消除低质量误检

TTFNet

简介: TTFNet是一种用于实时目标检测且对训练时间友好的网络,对CenterNet收敛速度慢的问题进行改进,提出了利用高斯核生成训练样本的新方法,有效的消除了anchor-free head中存在的模糊性。同时简单轻量化的网络结构也易于进行任务扩展。

特点:

  • 结构简单,仅需要两个head检测目标位置和大小,并且去除了耗时的后处理操作
  • 训练时间短,基于DarkNet53的骨干网路,V100 8卡仅需要训练2个小时即可达到较好的模型效果

如何贡献代码

我们非常欢迎您可以为PaddleDetection中的Anchor Free检测模型提供代码,您可以提交PR供我们review;也十分感谢您的反馈,可以提交相应issue,我们会及时解答。

YOLO v4 模型

简介

YOLO v4的Paddle实现版本,要求使用PaddlePaddle2.0.0及以上版本或适当的develop版本

目前转换了darknet中YOLO v4的权重,可以直接对图片进行预测,在test-dev2019中精度为43.5%。另外,支持VOC数据集上finetune,精度达到85.5%

目前支持YOLO v4的多个模块:

  • mish激活函数
  • PAN模块
  • SPP模块
  • ciou loss
  • label_smooth
  • grid_sensitive

目前支持YOLO系列的Anchor聚类算法

python tools/anchor_cluster.py -c ${config} -m ${method} -s ${size}

主要参数配置参考下表 | 参数 | 用途 | 默认值 | 备注 | |:------:|:------:|:------:|:------:| | -c/--config | 模型的配置文件 | 无默认值 | 必须指定 | | -n/--n | 聚类的簇数 | 9 | Anchor的数目 | | -s/--size | 图片的输入尺寸 | None | 若指定,则使用指定的尺寸,如果不指定, 则尝试从配置文件中读取图片尺寸 | | -m/--method | 使用的Anchor聚类方法 | v2 | 目前只支持yolov2/v5的聚类算法 | | -i/--iters | kmeans聚类算法的迭代次数 | 1000 | kmeans算法收敛或者达到迭代次数后终止 | | -gi/--gen_iters | 遗传算法的迭代次数 | 1000 | 该参数只用于yolov5的Anchor聚类算法 | | -t/--thresh| Anchor尺度的阈值 | 0.25 | 该参数只用于yolov5的Anchor聚类算法 |

模型库

下表中展示了当前支持的网络结构。

GPU个数 测试集 骨干网络 精度 模型下载 配置文件
YOLO v4 - test-dev2019 CSPDarkNet53 43.5 下载链接 配置文件
YOLO v4 VOC 2 VOC2007 CSPDarkNet53 85.5 下载链接 配置文件

注意:

  • 由于原版YOLO v4使用coco trainval2014进行训练,训练样本中包含部分评估样本,若使用val集会导致精度虚高,因此使用coco test集对模型进行评估。
  • YOLO v4模型仅支持coco test集评估和图片预测,由于test集不包含目标框的真实标注,评估时会将预测结果保存在json文件中,请将结果提交至cocodataset上查看最终精度指标。
  • coco测试集使用test2017,下载请参考coco2017

未来工作

  1. mish激活函数优化
  2. mosaic数据预处理实现

如何贡献代码

我们非常欢迎您可以为PaddleDetection提供代码,您可以提交PR供我们review;也十分感谢您的反馈,可以提交相应issue,我们会及时解答。

竞赛冠军模型

CACascade RCNN

简介

CACascade RCNN是百度视觉技术部在Objects365 2019 Challenge上夺冠的最佳单模型之一,Objects365是在通用物体检测领域的一个全新的数据集,旨在促进对自然场景不同对象的检测研究。Objects365在63万张图像上标注了365个对象类,训练集中共有超过1000万个边界框。这里放出的是Full Track任务中最好的单模型之一。

_images/obj365_gt.png

方法描述

针对大规模物体检测算法的特点,我们提出了一种基于图片包含物体类别的数量的采样方式(Class Aware Sampling)。基于这种方式进行训练模型可以在更短的时间使模型收敛到更好的效果。

_images/cas.png

本次公布的最好单模型是一个基于Cascade RCNN的两阶段检测模型,在此基础上将Backbone替换为更加强大的SENet154模型,Deformable Conv模块以及更复杂二阶段网络结构,针对BatchSize比较小的情况增加了Group Normalization操作并同时使用了多尺度训练,最终达到了非常理想的效果。预训练模型先后分别在ImageNet和COCO数据集上进行了训练,其中在COCO数据集上训练时增加了Mask分支,其余结构与CACascade RCNN相同, 会在启动训练时自动下载。

使用方法

1.准备数据

数据需要通过Objects365官方网站进行申请下载,数据下载后将数据放置在dataset目录中。

${THIS REPO ROOT}
  \--dataset
      \-- objects365
           \-- annotations
                |-- train.json
                |-- val.json
           \-- train
           \-- val

2.启动训练模型

python tools/train.py -c configs/obj365/cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas.yml

3.模型预测结果

模型 验证集 mAP 下载链接 配置文件
CACascadeRCNN SE154 31.6 model 配置文件
模型效果

_images/obj365_pred.png

CascadeCA RCNN

简介

CascadeCA RCNN是百度视觉技术部在Google AI Open Images 2019-Object Detction比赛中的最佳单模型,该单模型助力团队在500多参数队伍中取得第二名。Open Images Dataset V5(OIDV5)包含500个类别、173W训练图像和超过1400W个标注边框,是目前已知规模最大的目标检测公开数据集,数据集地址:https://storage.googleapis.com/openimages/web/index.html。团队在比赛中的技术方案报告地址:https://arxiv.org/pdf/1911.07171.pdf

_images/oidv5_gt.png

方法描述

该模型结合了当前较优的检测方法。具体地,它将ResNet200-vd作为检测模型的骨干网络,其imagenet分类预训练模型可以在这里下载;结合了CascadeCA RCNN、Feature Pyramid Networks、Non-local、Deformable V2等方法。在这里需要注意的是,标准的CascadeRCNN是只预测2个框(前景和背景,使用得分信息去判断最终前景所属的类别),而该模型对每个类别都单独预测了一个框(Cascade Class Aware)。最终模型框图如下图所示。

_images/oidv5_model_framework.png

由于OIDV5的类别不均衡现象比较严重,在训练时采用了动态采样的策略去选择样本并进行训练;多尺度训练被用于解决边框面积范围太大的情况;此外,团队使用Libra loss替代Smooth L1 loss,来计算预测框的loss;在预测时,使用SoftNMS方法进行后处理,保证更多的框可以被召回。

Objects365 Dataset和OIDV5有大约189个类别是重复的,因此将两个数据集合并进行训练,用于扩充OIDV5的训练数据,最终该模型与其性能指标如下表所示。更具体的模型训练和融合策略可以见:OIDV5技术报告

OIDV5模型训练结果如下。

模型结构 Public/Private Score 下载链接 配置文件
CascadeCARCNN-FPN-Dcnv2-Nonlocal ResNet200-vd 0.62690/0.59459 模型 配置文件

此外,为验证模型的性能,PaddleDetection基于该模型结构,也训练了针对COCO2017和Objects365 Dataset的模型,模型和验证集指标如下表。

模型结构 数据集 验证集mAP 下载链接 配置文件
CascadeCARCNN-FPN-Dcnv2-Nonlocal ResNet200-vd COCO2017 51.7% 模型 配置文件
CascadeCARCNN-FPN-Dcnv2-Nonlocal ResNet200-vd Objects365 34.5% 模型 配置文件

COCO和Objects365 Dataset数据格式相同,目前只支持预测和评估。

使用方法

OIDV5数据集格式与COCO不同,目前仅支持单张图片的预测。OIDV5的模型评估方法可以参考文档

  1. 下载模型并解压。
  2. 运行预测程序。
python -u tools/infer.py -c configs/oidv5/cascade_rcnn_cls_aware_r200_vd_fpn_dcnv2_nonlocal_softnms.yml -o weights=./oidv5_cascade_rcnn_cls_aware_r200_vd_fpn_dcnv2_nonlocal_softnms/ --infer_img=demo/000000570688.jpg

其中模型所在文件夹需要根据自己放置的位置进行修改。

检测结果图像可以在output文件夹中查看。

模型检测效果

_images/oidv5_pred.jpg

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

English | 简体中文

人脸检测模型

简介

FaceDetection的目标是提供高效、高速的人脸检测解决方案,包括最先进的模型和经典模型。

_images/12_Group_Group_12_Group_Group_12_935.jpg

模型库与基线

下表中展示了PaddleDetection当前支持的网络结构,具体细节请参考算法细节

原始版本 Lite版本 1 NAS版本 2
BlazeFace
FaceBoxes x

[1] Lite版本表示减少网络层数和通道数。[2] NA版本表示使用 神经网络搜索方法来构建网络结构。

模型库
WIDER-FACE数据集上的mAP
网络结构 类型 输入尺寸 图片个数/GPU 学习率策略 Easy Set Medium Set Hard Set 下载 配置文件
BlazeFace 原始版本 640 8 32w 0.915 0.892 0.797 模型 配置文件
BlazeFace Lite版本 640 8 32w 0.909 0.885 0.781 模型 配置文件
BlazeFace NAS版本 640 8 32w 0.837 0.807 0.658 模型 配置文件
BlazeFace NAS_V2版本 640 8 32W 0.870 0.837 0.685 模型 配置文件
FaceBoxes 原始版本 640 8 32w 0.878 0.851 0.576 模型 配置文件
FaceBoxes Lite版本 640 8 32w 0.901 0.875 0.760 模型 配置文件

注意:

  • 我们使用tools/face_eval.py中多尺度评估策略得到Easy/Medium/Hard Set里的mAP。具体细节请参考在WIDER-FACE数据集上评估
  • BlazeFace-Lite的训练与测试使用 blazeface.yml配置文件并且设置:lite_edition: true
FDDB数据集上的mAP
网络结构 Type Size DistROC ContROC
BlazeFace 原始版本 640 0.992 0.762
BlazeFace Lite版本 640 0.990 0.756
BlazeFace NAS版本 640 0.981 0.741
FaceBoxes 原始版本 640 0.987 0.736
FaceBoxes Lite版本 640 0.988 0.751

注意:

推理时间和模型大小比较
网络结构 类型 输入尺寸 P4(trt32) (ms) CPU (ms) CPU (ms)(enable_mkldmm) 高通骁龙855(armv8) (ms) 模型大小(MB)
BlazeFace 原始版本 128 1.387 23.461 4.92 6.036 0.777
BlazeFace Lite版本 128 1.323 12.802 7.16 6.193 0.68
BlazeFace NAS版本 128 1.03 6.714 3.641 2.7152 0.234
BlazeFace NAS_V2版本 128 0.909 9.58 7.903 3.499 0.383
FaceBoxes 原始版本 128 3.144 14.972 9,852 19.2196 3.6
FaceBoxes Lite版本 128 2.295 11.276 6.969 8.5278 2
BlazeFace 原始版本 320 3.01 132.408 20.762 70.6916 0.777
BlazeFace Lite版本 320 2.535 69.964 35.612 69.9438 0.68
BlazeFace NAS版本 320 2.392 36.962 14.443 39.8086 0.234
BlazeFace NAS_V2版本 320 1.487 52.038 38.693 56.137 0.383
FaceBoxes 原始版本 320 7.556 84.531 48.465 52.1022 3.6
FaceBoxes Lite版本 320 18.605 78.862 46.488 59.8996 2
BlazeFace 原始版本 640 8.885 519.364 78.825 149.896 0.777
BlazeFace Lite版本 640 6.988 284.13 131.385 149.902 0.68
BlazeFace NAS版本 640 7.448 142.91 56.725 69.8266 0.234
BlazeFace NAS_V2版本 640 4.201 197.695 153.626 88.278 0.383
FaceBoxes 原始版本 640 78.201 394.043 239.201 169.877 3.6
FaceBoxes Lite版本 640 59.47 313.683 168.73 139.918 2

注意:

  • CPU: Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz。
  • P4(trt32)和CPU的推理时间测试基于PaddlePaddle-1.8.0版本。
  • ARM测试环境:
    • 高通骁龙855(armv8);
    • 单线程;
    • Paddle-Lite develop版本。

快速开始

数据准备

我们使用WIDER-FACE数据集进行训练和模型测试,官方网站提供了详细的数据介绍。

  • WIDER-Face数据源:使用如下目录结构加载wider_face类型的数据集:

    dataset/wider_face/
    ├── wider_face_split
    │   ├── wider_face_train_bbx_gt.txt
    │   ├── wider_face_val_bbx_gt.txt
    ├── WIDER_train
    │   ├── images
    │   │   ├── 0--Parade
    │   │   │   ├── 0_Parade_marchingband_1_100.jpg
    │   │   │   ├── 0_Parade_marchingband_1_381.jpg
    │   │   │   │   ...
    │   │   ├── 10--People_Marching
    │   │   │   ...
    ├── WIDER_val
    │   ├── images
    │   │   ├── 0--Parade
    │   │   │   ├── 0_Parade_marchingband_1_1004.jpg
    │   │   │   ├── 0_Parade_marchingband_1_1045.jpg
    │   │   │   │   ...
    │   │   ├── 10--People_Marching
    │   │   │   ...
    
  • 手动下载数据集: 要下载WIDER-FACE数据集,请运行以下命令:

cd dataset/wider_face && ./download.sh
  • 自动下载数据集: 如果已经开始训练,但是数据集路径设置不正确或找不到路径, PaddleDetection会从WIDER-FACE数据集自动下载它们, 下载后解压的数据集将缓存在~/.cache/paddle/dataset/中,并且之后的训练测试会自动加载它们。
数据增强方法
  • 尺度变换(Data-anchor-sampling): 具体操作是:根据随机选择的人脸高和宽,获取到$v=\sqrt{width * height}$,之后再判断v的值范围,其中v值位于缩放区间[16,32,64,128] 假设v=45,则选定32<v<64, 以均匀分布的概率选取[16,32,64]中的任意一个值。若选中64,则该人脸的缩放区间在[64 / 2, min(v * 2, 64 * 2)]中选定。
  • 其他方法: 包括随机扰动、翻转、裁剪等。具体请参考READER.md
训练与推理

训练流程与推理流程方法与其他算法一致,请参考GETTING_STARTED_cn.md注意:

  • BlazeFaceFaceBoxes训练是以每卡batch_size=8在4卡GPU上进行训练(总batch_size是32),并且训练320000轮 (如果你的GPU数达不到4,请参考学习率计算规则表)。
  • 人脸检测模型目前我们不支持边训练边评估。
评估

目前我们支持在WIDER FACE数据集和FDDB数据集上评估。首先运行tools/face_eval.py生成评估结果文件,其次使用matlab(WIDER FACE) 或OpenCV(FDDB)计算具体的评估指标。其中,运行tools/face_eval.py的参数列表如下:

  • -f 或者 --output_eval: 评估生成的结果文件保存路径,默认是: output/pred
  • -e 或者 --eval_mode: 评估模式,包括 widerfacefddb,默认是widerface
  • --multi_scale: 如果在命令中添加此操作按钮,它将选择多尺度评估。默认值为False,它将选择单尺度评估。
在WIDER-FACE数据集上评估

评估并生成结果文件:

export CUDA_VISIBLE_DEVICES=0
python -u tools/face_eval.py -c configs/face_detection/blazeface.yml \
       -o weights=output/blazeface/model_final \
       --eval_mode=widerface

评估完成后,将在output/pred中生成txt格式的测试结果。

  • 下载官方评估脚本来评估AP指标:
wget http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/support/eval_script/eval_tools.zip
unzip eval_tools.zip && rm -f eval_tools.zip
  • eval_tools/wider_eval.m中修改保存结果路径和绘制曲线的名称:
# Modify the folder name where the result is stored.
pred_dir = './pred';  
# Modify the name of the curve to be drawn
legend_name = 'Fluid-BlazeFace';
  • wider_eval.m 是评估模块的主要执行程序。运行命令如下:
matlab -nodesktop -nosplash -nojvm -r "run wider_eval.m;quit;"
在FDDB数据集上评估

我们提供了一套FDDB数据集的评估流程(目前仅支持Linux系统),其他具体细节请参考FDDB官网

  • 1)下载安装opencv:下载OpenCV: 进入OpenCV library手动下载安装OpenCV:请参考OpenCV官方安装教程通过源码安装。
  • 2)下载数据集、评估代码以及格式化数据:
./dataset/fddb/download.sh
  • 3)编译FDDB评估代码: 进入dataset/fddb/evaluation目录下,修改MakeFile文件中内容如下:
evaluate: $(OBJS)
    $(CC) $(OBJS) -o $@ $(LIBS)

修改common.hpp中内容为如下形式:

#define __IMAGE_FORMAT__ ".jpg"
//#define __IMAGE_FORMAT__ ".ppm"
#define __CVLOADIMAGE_WORKING__

根据grep -r "CV_RGB"命令找到含有CV_RGB的代码段,将CV_RGB改成Scalar,并且在cpp中加入using namespace cv;, 然后编译:

make clean && make
  • 4)开始评估:修改config文件中dataset_dirannotation字段内容:
EvalReader:
  ...
  dataset:
    dataset_dir: dataset/fddb
    anno_path: FDDB-folds/fddb_annotFile.txt
    ...

评估并生成结果文件:

python -u tools/face_eval.py -c configs/face_detection/blazeface.yml \
       -o weights=output/blazeface/model_final \
       --eval_mode=fddb

评估完成后,将在output/pred/pred_fddb_res.txt中生成txt格式的测试结果。生成ContROC与DiscROC数据:

cd dataset/fddb/evaluation
./evaluate -a ./FDDB-folds/fddb_annotFile.txt \
           -f 0 -i ./ -l ./FDDB-folds/filePath.txt -z .jpg \
           -d {RESULT_FILE} \
           -r {OUTPUT_DIR}

注意:(1)RESULT_FILEtools/face_eval.py输出的FDDB预测结果文件;(2)OUTPUT_DIR是FDDB评估输出结果文件前缀,会生成两个文件{OUTPUT_DIR}ContROC.txt{OUTPUT_DIR}DiscROC.txt;(3)参数用法及注释可通过执行./evaluate --help来获取。

人脸关键点检测

(1)下载PaddleDetection开放的WIDER-FACE数据集人脸关键点标注文件(链接),并拷贝至wider_face/wider_face_split文件夹中:

cd dataset/wider_face/wider_face_split/
wget https://dataset.bj.bcebos.com/wider_face/wider_face_train_bbx_lmk_gt.txt

(2)使用configs/face_detection/blazeface_keypoint.yml配置文件进行训练与评估,使用方法与上一节内容一致。

模型评估
网络结构 输入尺寸 图片个数/GPU 学习率策略 Easy Set Medium Set Hard Set 下载 配置文件
BlazeFace Keypoint 640 16 16w 0.852 0.816 0.662 模型 配置文件

_images/12_Group_Group_12_Group_Group_12_84.jpg

算法细节

BlazeFace

简介:BlazeFace 是Google Research发布的人脸检测模型。它轻巧并且性能良好, 专为移动GPU推理量身定制。在旗舰设备上,速度可达到200-1000+FPS。

特点:

  • 锚点策略在8×8(输入128x128)的特征图上停止,在该分辨率下每个像素点6个锚点;
  • 5个单BlazeBlock和6个双BlazeBlock:5×5 depthwise卷积,可以保证在相同精度下网络层数更少;
  • 用混合策略替换非极大值抑制算法,该策略将边界框的回归参数估计为重叠预测之间的加权平均值。

版本信息:

  • 原始版本: 参考原始论文复现;
  • Lite版本: 使用3x3卷积替换5x5卷积,更少的网络层数和通道数;
  • NAS版本: 使用神经网络搜索算法构建网络结构,相比于Lite版本,NAS版本需要更少的网络层数和通道数。
  • NAS_V2版本: 基于PaddleSlim中SANAS算法在blazeface-NAS的基础上搜索出来的结构,相比NAS版本,NAS_V2版本的精度平均高出3个点,在855芯片上的硬件延时相对NAS版本仅增加5%。
FaceBoxes

简介:FaceBoxes 由Shifeng Zhang等人提出的高速和高准确率的人脸检测器, 被称为“高精度CPU实时人脸检测器”。 该论文收录于IJCB(2017)。

特点:

  • 锚点策略分别在20x20、10x10、5x5(输入640x640)执行,每个像素点分别是3、1、1个锚点,对应密度系数是1, 2, 4(20x20)、4(10x10)、4(5x5);
  • 在基础网络中个别block中使用CReLU和inception的结构;
  • 使用密度先验盒(density_prior_box)可提高检测精度。

版本信息:

  • 原始版本: 参考原始论文进行修改;
  • Lite版本: 使用更少的网络层数和通道数,具体可参考代码

如何贡献代码

我们非常欢迎您可以为PaddleDetection中的人脸检测模型提供代码,您可以提交PR供我们review;也十分感谢您的反馈,可以提交相应issue,我们会及时解答。

English | 简体中文

特色垂类检测模型

我们提供了针对不同场景的基于PaddlePaddle的检测模型,用户可以下载模型进行使用。

任务 算法 精度(Box AP) 下载 配置文件
车辆检测 YOLOv3 54.5 下载链接 配置文件
行人检测 YOLOv3 51.8 下载链接 配置文件

车辆检测(Vehicle Detection)

车辆检测的主要应用之一是交通监控。在这样的监控场景中,待检测的车辆多为道路红绿灯柱上的摄像头拍摄所得。

1. 模型结构

Backbone为Dacknet53的YOLOv3。

2. 训练参数配置

PaddleDetection提供了使用COCO数据集对YOLOv3进行训练的参数配置文件yolov3_darnet.yml,与之相比,在进行车辆检测的模型训练时,我们对以下参数进行了修改:

  • max_iters: 120000
  • num_classes: 6
  • anchors: [[8, 9], [10, 23], [19, 15], [23, 33], [40, 25], [54, 50], [101, 80], [139, 145], [253, 224]]
  • label_smooth: false
  • nms/nms_top_k: 400
  • nms/score_threshold: 0.005
  • milestones: [60000, 80000]
  • dataset_dir: dataset/vehicle
3. 精度指标

模型在我们内部数据上的精度指标为:

IOU=.50:.05:.95时的AP为 0.545。

IOU=.5时的AP为 0.764。

4. 预测

用户可以使用我们训练好的模型进行车辆检测:

export CUDA_VISIBLE_DEVICES=0
python -u tools/infer.py -c contrib/VehicleDetection/vehicle_yolov3_darknet.yml \
                         -o weights=https://paddlemodels.bj.bcebos.com/object_detection/vehicle_yolov3_darknet.tar \
                         --infer_dir contrib/VehicleDetection/demo \
                         --draw_threshold 0.2 \
                         --output_dir contrib/VehicleDetection/demo/output

预测结果示例:

_images/VehicleDetection_001.jpeg

_images/VehicleDetection_005.png

行人检测(Pedestrian Detection)

行人检测的主要应用有智能监控。在监控场景中,大多是从公共区域的监控摄像头视角拍摄行人,获取图像后再进行行人检测。

1. 模型结构

Backbone为Dacknet53的YOLOv3。

2. 训练参数配置

PaddleDetection提供了使用COCO数据集对YOLOv3进行训练的参数配置文件yolov3_darknet.yml,与之相比,在进行行人检测的模型训练时,我们对以下参数进行了修改:

  • max_iters: 200000
  • num_classes: 1
  • snapshot_iter: 5000
  • milestones: [150000, 180000]
  • dataset_dir: dataset/pedestrian
2. 精度指标

模型在我们针对监控场景的内部数据上精度指标为:

IOU=.5时的AP为 0.792。

IOU=.5-.95时的AP为 0.518。

3. 预测

用户可以使用我们训练好的模型进行行人检测:

export CUDA_VISIBLE_DEVICES=0
python -u tools/infer.py -c contrib/PedestrianDetection/pedestrian_yolov3_darknet.yml \
                         -o weights=https://paddlemodels.bj.bcebos.com/object_detection/pedestrian_yolov3_darknet.tar \
                         --infer_dir contrib/PedestrianDetection/demo \
                         --draw_threshold 0.3 \
                         --output_dir contrib/PedestrianDetection/demo/output

预测结果示例:

_images/PedestrianDetection_001.png

_images/PedestrianDetection_004.png

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。

模型库和基线

测试环境

  • Python 2.7.1
  • PaddlePaddle >=1.5
  • CUDA 9.0
  • cuDNN >=7.4
  • NCCL 2.1.2

通用设置

  • 所有模型均在COCO17数据集中训练和测试。
  • 除非特殊说明,所有ResNet骨干网络采用ResNet-B结构。
  • 对于RCNN和RetinaNet系列模型,训练阶段仅使用水平翻转作为数据增强,测试阶段不使用数据增强。
  • 推理时间(fps): 推理时间是在一张Tesla V100的GPU上通过'tools/eval.py'测试所有验证集得到,单位是fps(图片数/秒), cuDNN版本是7.5,包括数据加载、网络前向执行和后处理, batch size是1。

训练策略

  • 我们采用和Detectron相同的训练策略。
  • 1x 策略表示:在总batch size为16时,初始学习率为0.02,在6万轮和8万轮后学习率分别下降10倍,最终训练9万轮。在总batch size为8时,初始学习率为0.01,在12万轮和16万轮后学习率分别下降10倍,最终训练18万轮。
  • 2x 策略为1x策略的两倍,同时学习率调整位置也为1x的两倍。

ImageNet预训练模型

Paddle提供基于ImageNet的骨架网络预训练模型。所有预训练模型均通过标准的Imagenet-1k数据集训练得到。下载链接

  • 注:ResNet50模型通过余弦学习率调整策略训练得到。下载链接

基线

Faster & Mask R-CNN

骨架网络 网络类型 每张GPU图片个数 学习率策略 推理时间(fps) Box AP Mask AP 下载 配置文件
ResNet50 Faster 1 1x 12.747 35.2 - 下载链接 配置文件
ResNet50 Faster 1 2x 12.686 37.1 - 下载链接 配置文件
ResNet50 Mask 1 1x 11.615 36.5 32.2 下载链接 配置文件
ResNet50 Mask 1 2x 11.494 38.2 33.4 下载链接 配置文件
ResNet50-vd Faster 1 1x 12.575 36.4 - 下载链接 配置文件
ResNet34-FPN Faster 2 1x - 36.7 - 下载链接 配置文件
ResNet34-vd-FPN Faster 2 1x - 37.4 - 下载链接 配置文件
ResNet50-FPN Faster 2 1x 22.273 37.2 - 下载链接 配置文件
ResNet50-FPN Faster 2 2x 22.297 37.7 - 下载链接 配置文件
ResNet50-FPN Mask 1 1x 15.184 37.9 34.2 下载链接 配置文件
ResNet50-FPN Mask 1 2x 15.881 38.7 34.7 下载链接 配置文件
ResNet50-FPN Cascade Faster 2 1x 17.507 40.9 - 下载链接 配置文件
ResNet50-FPN Cascade Mask 1 1x 12.43 41.3 35.5 下载链接 配置文件
ResNet50-vd-FPN Faster 2 2x 21.847 38.9 - 下载链接 配置文件
ResNet50-vd-FPN Mask 1 2x 15.825 39.8 35.4 下载链接 配置文件
CBResNet50-vd-FPN Faster 2 1x - 39.7 - 下载链接 配置文件
ResNet101 Faster 1 1x 9.316 38.3 - 下载链接 配置文件
ResNet101-FPN Faster 1 1x 17.297 38.7 - 下载链接 配置文件
ResNet101-FPN Faster 1 2x 17.246 39.1 - 下载链接 配置文件
ResNet101-FPN Mask 1 1x 12.983 39.5 35.2 下载链接 配置文件
ResNet101-vd-FPN Faster 1 1x 17.011 40.5 - 下载链接 配置文件
ResNet101-vd-FPN Faster 1 2x 16.934 40.8 - 下载链接 配置文件
ResNet101-vd-FPN Mask 1 1x 13.105 41.4 36.8 下载链接 配置文件
CBResNet101-vd-FPN Faster 2 1x - 42.7 - 下载链接 配置文件
ResNeXt101-vd-FPN Faster 1 1x 8.815 42.2 - 下载链接 配置文件
ResNeXt101-vd-FPN Faster 1 2x 8.809 41.7 - 下载链接 配置文件
ResNeXt101-vd-FPN Mask 1 1x 7.689 42.9 37.9 下载链接 配置文件
ResNeXt101-vd-FPN Mask 1 2x 7.859 42.6 37.6 下载链接 配置文件
SENet154-vd-FPN Faster 1 1.44x 3.408 42.9 - 下载链接 配置文件
SENet154-vd-FPN Mask 1 1.44x 3.233 44.0 38.7 下载链接 配置文件
ResNet101-vd-FPN CascadeClsAware Faster 2 1x - 44.7(softnms) - 下载链接 配置文件
ResNet101-vd-FPN CascadeClsAware Faster 2 1x - 46.5(multi-scale test) - 下载链接 配置文件

Deformable 卷积网络v2

骨架网络 网络类型 卷积 每张GPU图片个数 学习率策略 推理时间(fps) Box AP Mask AP 下载 配置文件
ResNet50-FPN Faster c3-c5 2 1x 19.978 41.0 - 下载链接 配置文件
ResNet50-vd-FPN Faster c3-c5 2 2x 19.222 42.4 - 下载链接 配置文件
ResNet101-vd-FPN Faster c3-c5 2 1x 14.477 44.1 - 下载链接 配置文件
ResNeXt101-vd-FPN Faster c3-c5 1 1x 7.209 45.2 - 下载链接 配置文件
ResNet50-FPN Mask c3-c5 1 1x 14.53 41.9 37.3 下载链接 配置文件
ResNet50-vd-FPN Mask c3-c5 1 2x 14.832 42.9 38.0 下载链接 配置文件
ResNet101-vd-FPN Mask c3-c5 1 1x 11.546 44.6 39.2 下载链接 配置文件
ResNeXt101-vd-FPN Mask c3-c5 1 1x 6.45 46.2 40.4 下载链接 配置文件
ResNet50-FPN Cascade Faster c3-c5 2 1x - 44.2 - 下载链接 配置文件
ResNet101-vd-FPN Cascade Faster c3-c5 2 1x - 46.4 - 下载链接 配置文件
ResNeXt101-vd-FPN Cascade Faster c3-c5 2 1x - 47.3 - 下载链接 配置文件
SENet154-vd-FPN Cascade Mask c3-c5 1 1.44x - 51.9 43.9 下载链接 配置文件
ResNet200-vd-FPN-Nonlocal CascadeClsAware Faster c3-c5 1 2.5x 3.103 51.7%(softnms) - 下载链接 配置文件
CBResNet200-vd-FPN-Nonlocal Cascade Faster c3-c5 1 2.5x 1.68 53.3%(softnms) - 下载链接 配置文件

注意事项:

HRNet

Res2Net

IOU loss

GCNet

Libra R-CNN

Auto Augmentation

Group Normalization

骨架网络 网络类型 每张GPU图片个数 学习率策略 Box AP Mask AP 下载 配置文件
ResNet50-FPN Faster 2 2x 39.7 - 下载链接 配置文件
ResNet50-FPN Mask 1 2x 40.1 35.8 下载链接 配置文件

注意事项:

YOLO v3

骨架网络 预训练数据集 输入尺寸 加入deformable卷积 每张GPU图片个数 学习率策略 推理时间(fps) Box AP 下载 配置文件
DarkNet53 (paper) ImageNet 608 8 270e - 33.0 - -
DarkNet53 (paper) ImageNet 416 8 270e - 31.0 - -
DarkNet53 (paper) ImageNet 320 8 270e - 28.2 - -
DarkNet53 ImageNet 608 8 270e 45.571 38.9 下载链接 配置文件
DarkNet53 ImageNet 416 8 270e - 37.5 下载链接 配置文件
DarkNet53 ImageNet 320 8 270e - 34.8 下载链接 配置文件
MobileNet-V1 ImageNet 608 8 270e 78.302 29.3 下载链接 配置文件
MobileNet-V1 ImageNet 416 8 270e - 29.3 下载链接 配置文件
MobileNet-V1 ImageNet 320 8 270e - 27.1 下载链接 配置文件
MobileNet-V3 ImageNet 608 8 270e - 31.6 下载链接 配置文件
MobileNet-V3 ImageNet 416 8 270e - 29.9 下载链接 配置文件
MobileNet-V3 ImageNet 320 8 270e - 27.1 下载链接 配置文件
ResNet34 ImageNet 608 8 270e 63.356 36.2 下载链接 配置文件
ResNet34 ImageNet 416 8 270e - 34.3 下载链接 配置文件
ResNet34 ImageNet 320 8 270e - 31.4 下载链接 配置文件
ResNet50_vd ImageNet 608 8 270e - 39.1 下载链接 配置文件
ResNet50_vd Object365 608 8 270e - 41.4 下载链接 配置文件

YOLO v3 基于Pasacl VOC数据集

骨架网络 输入尺寸 每张GPU图片个数 学习率策略 推理时间(fps) Box AP 下载 配置文件
DarkNet53 608 8 270e 54.977 83.5 下载链接 配置文件
DarkNet53 416 8 270e - 83.6 下载链接 配置文件
DarkNet53 320 8 270e - 82.2 下载链接 配置文件
DarkNet53 Diou-Loss 608 8 270e - 83.5 下载链接 配置文件
MobileNet-V1 608 8 270e 104.291 76.2 下载链接 配置文件
MobileNet-V1 416 8 270e - 76.7 下载链接 配置文件
MobileNet-V1 320 8 270e - 75.3 下载链接 配置文件
ResNet34 608 8 270e 82.247 82.6 下载链接 配置文件
ResNet34 416 8 270e - 81.9 下载链接 配置文件
ResNet34 320 8 270e - 80.1 下载链接 配置文件

注意事项:

  • 上表中也提供了原论文YOLOv3中YOLOv3-DarkNet53的精度,我们的实现版本主要从在bounding box的宽度和高度回归上使用了L1损失,图像mixup和label smooth等方法优化了其精度。
  • YOLO v3在8卡,总batch size为64下训练270轮。数据增强包括:mixup, 随机颜色失真,随机剪裁,随机扩张,随机插值法,随机翻转。YOLO v3在训练阶段对minibatch采用随机reshape,可以采用相同的模型测试不同尺寸图片,我们分别提供了尺寸为608/416/320大小的测试结果。deformable卷积作用在骨架网络5阶段。
  • 在YOLOv3-DarkNet53模型基础上使用Diou-Loss后,在VOC数据集上该模型平均mAP比原模型高大约2%。
  • YOLO v3增强版模型通过引入可变形卷积,dropblock,IoU loss和Iou aware,将精度进一步提升至43.6, 详情见YOLOv3增强模型

RetinaNet

骨架网络 每张GPU图片个数 学习率策略 推理时间(fps) Box AP 下载 配置文件
ResNet50-FPN 2 1x - 36.0 下载链接 配置文件
ResNet101-FPN 2 1x - 37.3 下载链接 配置文件
ResNeXt101-vd-FPN 1 1x - 40.5 下载链接 配置文件

注意事项: RetinaNet系列模型中,在总batch size为16下情况下,初始学习率改为0.01。

EfficientDet

尺度 每张GPU图片个数 学习率策略 Box AP 下载 配置文件
EfficientDet-D0 16 300 epochs 33.8 下载链接 配置文件

注意事项: 在总batch size为128(8x16)时,基础学习率改为0.16。

SSDLite

骨架网络 输入尺寸 每张GPU图片个数 学习率策略 推理时间(fps) Box AP 下载 配置文件
MobileNet_v1 300 64 Cosine decay(40w) - 23.6 下载链接 配置文件
MobileNet_v3 small 320 64 Cosine decay(40w) - 16.2 下载链接 配置文件
MobileNet_v3 large 320 64 Cosine decay(40w) - 23.3 下载链接 配置文件
MobileNet_v3 small w/ FPN 320 64 Cosine decay(40w) - 18.9 下载链接 配置文件
MobileNet_v3 large w/ FPN 320 64 Cosine decay(40w) - 24.3 下载链接 配置文件
GhostNet 320 64 Cosine decay(40w) - 23.3 下载链接 配置文件

注意事项: SSDLite模型使用学习率余弦衰减策略在8卡GPU下总batch size为512。

SSD

骨架网络 输入尺寸 每张GPU图片个数 学习率策略 推理时间(fps) Box AP 下载 配置文件
VGG16 300 8 40万 81.613 25.1 下载链接 配置文件
VGG16 512 8 40万 46.007 29.1 下载链接 配置文件

注意事项: VGG-SSD在总batch size为32下训练40万轮。

SSD 基于Pascal VOC数据集

骨架网络 输入尺寸 每张GPU图片个数 学习率策略 推理时间(fps) Box AP 下载 配置文件
MobileNet v1 300 32 120e 159.543 73.2 下载链接 配置文件
VGG16 300 8 240e 117.279 77.5 下载链接 配置文件
VGG16 512 8 240e 65.975 80.2 下载链接 配置文件

注意事项: MobileNet-SSD在2卡,总batch size为64下训练120周期。VGG-SSD在总batch size为32下训练240周期。数据增强包括:随机颜色失真,随机剪裁,随机扩张,随机翻转。

人脸检测

详细请参考人脸检测模型

基于Open Images V5数据集的物体检测

详细请参考Open Images V5数据集基线模型

Anchor Free系列模型

详细请参考Anchor Free系列模型

版本更新信息

最新版本信息

2.0-rc(02.23/2021)

  • 动态图模型丰富度提升:
    • 优化RCNN模型组网及训练方式,RCNN系列模型精度提升(依赖Paddle develop或2.0.1版本)
    • 新增支持SSDLite,FCOS,TTFNet,SOLOv2系列模型
    • 新增行人和车辆垂类目标检测模型
  • 新增动态图基础模块:
    • 新增MobileNetV3,HRNet骨干网络
    • 优化RoIAlign计算逻辑,RCNN系列模型精度提升(依赖Paddle develop或2.0.1版本)
    • 新增支持Synchronized Batch Norm
    • 新增支持Modulated Deformable Convolution
  • 预测部署:
    • 发布动态图python、C++、Serving部署解决方案及文档,支持Faster RCNN,Mask RCNN,YOLOv3,PP-YOLO,SSD,TTFNet,FCOS,SOLOv2等系列模型预测部署
    • 动态图预测部署支持TensorRT模式FP32,FP16推理加速
  • 检测模型压缩:
    • 裁剪:新增动态图裁剪支持,并发布YOLOv3-MobileNetV1裁剪模型
    • 量化:新增动态图量化支持,并发布YOLOv3-MobileNetV1和YOLOv3-MobileNetV3量化模型
  • 文档:
    • 新增动态图入门教程文档:包含安装说明,快速开始,准备数据,训练/评估/预测流程文档
    • 新增动态图进阶教程文档:包含模型压缩、推理部署文档
    • 新增动态图模型库文档

v2.0-beta(12.20/2020)

  • 动态图支持:
    • 支持Faster-RCNN, Mask-RCNN, FPN, Cascade Faster/Mask RCNN, YOLOv3和SSD模型,试用版本。
  • 模型提升:
    • 更新PP-YOLO MobileNetv3 large和small模型,精度提升,并新增裁剪和蒸馏后的模型。
  • 新功能:
    • 支持VisualDL可视化数据预处理图片。
  • Bug修复:
    • 修复BlazeFace人脸关键点预测bug。

历史版本信息

v0.5.0(11/2020)

  • 模型丰富度提升:
    • 发布SOLOv2系列模型,其中SOLOv2-Light-R50-VD-DCN-FPN 模型在单卡V100上达到 38.6 FPS,加速24% ,COCO验证集精度达到38.8%, 提升2.4绝对百分点。
    • 新增Android移动端检测demo,包括SSD、YOLO系列模型,可直接扫码安装体验。
  • 移动端模型优化:
    • 新增PACT新量化策略,YOLOv3-Mobilenetv3在COCO数据集上比普通量化相比提升0.7%。
  • 易用性提升及功能组件:
    • 增强generate_proposal_labels算子功能,规避模型出nan风险。
    • 修复deploy下python与C++预测若干问题。
    • 统一COCO与VOC数据集下评估流程,支持输出单类AP和P-R曲线。
    • PP-YOLO支持矩形输入图像。
  • 文档:
    • 新增目标检测全流程教程,新增Jetson平台部署教程。

v0.4.0(07/2020)

  • 模型丰富度提升:
    • 发布PPYOLO模型,COCO数据集精度达到45.2%,单卡V100预测速度达到72.9 FPS,精度和预测速度优于YOLOv4模型。
    • 新增TTFNet模型,base版本对齐竞品,COCO数据集精度达到32.9%。
    • 新增HTC模型,base版本对齐竞品,COCO数据集精度达到42.2%。
    • 新增BlazeFace人脸关键点检测模型,在Wider-Face数据集的Easy-Set精度达到85.2%。
    • 新增ACFPN模型, COCO数据集精度达到39.6%。
    • 发布服务器端通用目标检测模型(包含676类),相同策略在COCO数据集上,V100为19.5FPS时,COCO mAP可以达到49.4%。
  • 移动端模型优化:
    • 新增SSDLite系列优化模型,包括新增GhostNet的Backbone,新增FPN组件等,精度提升0.5%-1.5%。
  • 易用性提升及功能组件:
    • 新增GridMask, RandomErasing数据增强方法。
    • 新增Matrix NMS支持。
    • 新增EMA(Exponential Moving Average)训练支持。
    • 新增多机训练方法,两机相对于单机平均加速比80%,多机训练支持待进一步验证。

v0.3.0(05/2020)

  • 模型丰富度提升:
    • 添加Efficientdet-D0模型,速度与精度优于竞品。
    • 新增YOLOv4预测模型,精度对齐竞品;新增YOLOv4在Pascal VOC数据集上微调训练,精度达到85.5%。
    • YOLOv3新增MobileNetV3骨干网络,COCO数据集精度达到31.6%。
    • 添加Anchor-free模型FCOS,精度优于竞品。
    • 添加Anchor-free模型CornernetSqueeze,精度优于竞品,优化模型的COCO数据集精度38.2%, +3.7%,速度较YOLOv3-Darknet53快5%。
    • 添加服务器端实用目标检测模型CascadeRCNN-ResNet50vd模型,速度与精度优于竞品EfficientDet。
  • 移动端推出3种模型:
    • SSDLite系列模型:SSDLite-Mobilenetv3 small/large模型,精度优于竞品。
    • YOLOv3移动端方案: YOLOv3-MobileNetv3模型压缩后加速3.5倍,速度和精度均领先于竞品的SSDLite模型。
    • RCNN移动端方案:CascadeRCNN-MobileNetv3经过系列优化, 推出输入图像分别为320x320和640x640的模型,速度与精度具有较高性价比。
  • 预测部署重构:
    • 新增Python预测部署流程,支持RCNN,YOLO,SSD,RetinaNet,人脸系列模型,支持视频预测。
    • 重构C++预测部署,提高易用性。
  • 易用性提升及功能组件:
    • 增加AutoAugment数据增强。
    • 升级检测库文档结构。
    • 支持迁移学习自动进行shape匹配。
    • 优化mask分支评估阶段内存占用。

v0.2.0(02/2020)

  • 新增模型:
    • 新增基于CBResNet模型。
    • 新增LibraRCNN模型。
    • 进一步提升YOLOv3模型精度,基于COCO数据精度达到43.2%,相比上个版本提升1.4%。
  • 新增基础模块:
    • 主干网络: 新增CBResNet。
    • loss模块: YOLOv3的loss支持细粒度op组合。
    • 正则模块: 新增DropBlock模块。
  • 功能优化和改进:
    • 加速YOLOv3数据预处理,整体训练提速40%。
    • 优化数据预处理逻辑,提升易用性。
    • 增加人脸检测预测benchmark数据。
    • 增加C++预测引擎Python API预测示例。
  • 检测模型压缩 :
    • 裁剪: 发布MobileNet-YOLOv3裁剪方案和模型,基于VOC数据FLOPs - 69.6%, mAP + 1.4%,基于COCO数据FLOPS-28.8%, mAP + 0.9%; 发布ResNet50vd-dcn-YOLOv3裁剪方案和模型,基于COCO数据集FLOPS - 18.4%, mAP + 0.8%。
    • 蒸馏: 发布MobileNet-YOLOv3蒸馏方案和模型,基于VOC数据mAP + 2.8%,基于COCO数据mAP + 2.1%。
    • 量化: 发布YOLOv3-MobileNet和BlazeFace的量化模型。
    • 裁剪+蒸馏: 发布MobileNet-YOLOv3裁剪+蒸馏方案和模型,基于COCO数据FLOPS - 69.6%,基于TensorRT预测加速64.5%,mAP - 0.3 %; 发布ResNet50vd-dcn-YOLOv3裁剪+蒸馏方案和模型,基于COCO数据FLOPS - 43.7%,基于TensorRT预测加速24.0%,mAP + 0.6 %。
    • 搜索: 开源BlazeFace-Nas的完成搜索方案。
  • 预测部署:
    • 集成 TensorRT,支持FP16、FP32、INT8量化推理加速。
  • 文档:
    • 增加详细的数据预处理模块介绍文档以及实现自定义数据Reader文档。
    • 增加如何新增算法模型的文档。
    • 文档部署到网站: https://paddledetection.readthedocs.io

12/2019

  • 增加Res2Net模型。
  • 增加HRNet模型。
  • 增加GIOU loss和DIOU loss。

21/11/2019

  • 增加CascadeClsAware RCNN模型。
  • 增加CBNet,ResNet200和Non-local模型。
  • 增加SoftNMS。
  • 增加Open Image V5数据集和Objects365数据集模型。

10/2019

  • 增加增强版YOLOv3模型,精度高达41.4%。
  • 增加人脸检测模型BlazeFace、Faceboxes。
  • 丰富基于COCO的模型,精度高达51.9%。
  • 增加Objects365 2019 Challenge上夺冠的最佳单模型之一CACascade-RCNN。
  • 增加行人检测和车辆检测预训练模型。
  • 支持FP16训练。
  • 增加跨平台的C++推理部署方案。
  • 增加模型压缩示例。

2/9/2019

  • 增加GroupNorm模型。
  • 增加CascadeRCNN+Mask模型。

5/8/2019

  • 增加Modulated Deformable Convolution系列模型。

29/7/2019

  • 增加检测库中文文档
  • 修复R-CNN系列模型训练同时进行评估的问题
  • 新增ResNext101-vd + Mask R-CNN + FPN模型
  • 新增基于VOC数据集的YOLOv3模型

3/7/2019

  • 首次发布PaddleDetection检测库和检测模型库
  • 模型包括:Faster R-CNN, Mask R-CNN, Faster R-CNN+FPN, Mask R-CNN+FPN, Cascade-Faster-RCNN+FPN, RetinaNet, YOLOv3, 和SSD.

FAQ(常见问题)

Q: 为什么我使用单GPU训练loss会出NaN?
A: 默认学习率是适配多GPU训练(8x GPU),若使用单GPU训练,须对应调整学习率(例如,除以8)。 计算规则表如下所示,它们是等价的,表中变化节点即为piecewise decay里的boundaries:

GPU数 学习率 最大轮数 变化节点
2 0.0025 720000 [480000, 640000]
4 0.005 360000 [240000, 320000]
8 0.01 180000 [120000, 160000]

Q: 如何减少GPU显存使用率?
A: 可通过设置环境变量FLAGS_conv_workspace_size_limit为较小的值来减少显存消耗,并且不 会影响训练速度。以Mask-RCNN(R50)为例,设置export FLAGS_conv_workspace_size_limit = 512, batch size可以达到每GPU 4 (Tesla V100 16GB)。

Q: 哪些参数会影响内存使用量?
A: 会影响内存使用量的参数有:是否使用多进程use_process、 batch_size、reader中的bufsize、reader中的memsize、数据预处理中的RandomExpand ratio参数、以及图像本身大小等。

Q: 如何修改数据预处理?
A: 可在配置文件中设置 sample_transform。注意需要在配置文件中加入完整预处理 例如RCNN模型中DecodeImage, NormalizeImage and Permute

Q: affine_channel和batch norm是什么关系?
A: 在RCNN系列模型加载预训练模型初始化,有时候会固定住batch norm的参数, 使用预训练模型中的全局均值和方式,并且batch norm的scale和bias参数不更新,已发布的大多ResNet系列的RCNN模型采用这种方式。这种情况下可以在config中设置norm_type为bn或affine_channel, freeze_norm为true (默认为true),两种方式等价。affne_channel的计算方式为scale * x + bias。只不过设置affine_channel时,内部对batch norm的参数自动做了融合。如果训练使用的affine_channel,用保存的模型做初始化,训练其他任务时,既可使用affine_channel, 也可使用batch norm, 参数均可正确加载。

Q: 某些配置项会在多个模块中用到(如 num_classes),如何避免在配置文件中多次重复设置?
A: 框架提供了 __shared__ 标记来实现配置的共享,用户可以标记参数,如 __shared__ = ['num_classes'] ,配置数值作用规则如下:

  1. 如果模块配置中提供了 num_classes ,会优先使用其数值。
  2. 如果模块配置中未提供 num_classes ,但配置文件中存在全局键值,那么会使用全局键值。
  3. 两者均为配置的情况下,将使用默认值(81)。

Q: 在配置文件中设置use_process=True,并且运行报错:not enough space for reason[failed to malloc 601 pages...
A: 当前Reader的共享存储队列空间不足,请增大配置文件xxx.yml中的memsize,如memsize: 3G->memsize: 6G。或者配置文件中设置use_process=False

注解

文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。