欢迎使用 PaddleDetection!¶
入门使用教程¶
安装说明¶
安装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,安装方式如下:
# 安装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
文件夹下生成一个画有预测结果的同名图像。
结果如下图:
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
结果如下图:
二、准备数据¶
数据集参考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
结果如下图:
入门使用¶
关于配置运行环境,请参考安装指南
训练/评估/预测¶
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 \
也可以显示的指定忽略参数名,可采用如下两种方式:
- 在YAML配置文件中设置
finetune_exclude_pretrained_params
- 在命令行中添加-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']
详细说明请参考迁移学习文档
- 在YAML配置文件中设置
使用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_type
由 affine_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/VOC2007
或VOCdevkit/VOC2012
文件夹,该文件夹中需有Annotations
,JPEGImages
和ImageSets/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.txt
和test.txt
列表文件:
python dataset/voc/create_list.py -d path/to/dataset
参数说明:
-d
或--dataset_dir
:VOC格式数据集所在文件夹路径
2.选择模型¶
PaddleDetection中提供了丰富的模型库,具体可在模型库中查看各个模型的指标,您可依据实际部署算力的情况,选择合适的模型:
- 算力资源小时,推荐您使用移动端模型,PaddleDetection中的移动端模型经过迭代优化,具有较高性价比。
- 算力资源强大时,推荐您使用服务器端模型,该模型是PaddleDetection提出的面向服务器端实用的目标检测方案。
同时也可以根据使用场景不同选择合适的模型:
- 当小物体检测时,推荐您使用两阶段检测模型,比如Faster RCNN系列模型,具体可在模型库中找到。
- 当在交通领域使用,如行人,车辆检测时,推荐您使用特色垂类检测模型。
- 当在竞赛中使用,推荐您使用竞赛冠军模型CACascadeRCNN与OIDV5_BASELINE_MODEL。
- 当在人脸检测中使用,推荐您使用人脸检测模型。
同时也可以尝试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.数据准备中准备好的路径,配置
TrainReader
、EvalReader
和TestReader
的路径。- 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.开始训练与部署¶
- 参数配置完成后,就可以开始训练模型了,具体可参考训练/评估/预测入门文档。
- 训练测试完成后,根据需要可以进行模型部署:首先需要导出可预测的模型,可参考导出模型教程;导出模型后就可以进行C++预测部署或者python端预测部署。
附:一个自定义数据集demo¶
我们以AI识虫数据集
为例,对自定义数据集上训练过程进行演示,该数据集提供了2183张图片,其中训练集1693张,验证集与测试集分别有245张,共包含7种昆虫。下载链接为:数据集链接, 在AIStudio上也有很多用户公开了此数据集,您可以进行搜索并下载,如:链接1,链接2等。
第一步:准备数据¶
由于该数据集标注文件都是xml文件,所以在准备数据步骤中选择方式二:将数据集转换为VOC格式。
由于该数据集中缺少已标注图片名列表文件trainval.txt和test.txt,所以需要进行生成,利用如下python脚本,在数据集根目录下执行,便可生成
trainval.txt
和test.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
文件夹并进入其中,之后新建Annotations
、JPEGImages
和ImageSets
文件夹,最后进入ImageSets
文件夹中新建Main
文件夹,至此完成VOC数据集目录结构的建立。将该数据集中的
train/annotations/xmls
与val/annotations/xmls
下的所有xml标注文件拷贝到VOCdevkit/VOC2007/Annotations
中,将该数据集中的train/images/
与val/images/
下的所有图片拷贝到VOCdevkit/VOC2007/JPEGImages
中,将第一步生成的trainval.txt
和test.txt
文件移动到VOCdevkit/VOC2007/ImageSets/Main
中。最后在数据集根目录下输出最终的
trainval.txt
和test.txt
文件:python dataset/voc/create_list.py -d path/to/dataset
** 注意:** 最终的trainval.txt
和test.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_iters
。milestones
(学习率变化界限)也是同理。原配置文件中总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
预测结果如下图所示:
如仍有疑惑,欢迎给我们提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的预测脚本,方便用户直接集成部署。
- Executor:Executor
- AnalysisPredictor:AnalysisPredictor
主要包含两个步骤:
- 导出预测模型
- 基于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
训练的模型导出后,即可基于本项目快速运行,也可以快速集成代码结合到自己的项目实际应用中去。
主要设计的目标包括以下四点:
- 跨平台,支持在
Windows
和Linux
完成编译、二次开发集成和部署运行 - 可扩展性,支持用户针对新模型开发自己特殊的数据预处理等逻辑
- 高性能,除了
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 导出模型¶
请确认您已经基于PaddleDetection
的export_model.py导出您的模型,并妥善保存到合适的位置。导出模型细节请参考 导出模型教程。
模型导出后, 目录结构如下(以yolov3_darknet
为例):
yolov3_darknet # 模型目录
├── infer_cfg.yml # 模型配置信息
├── __model__ # 模型文件
└── __params__ # 参数文件
预测时,该目录所在的路径会作为程序的输入参数。
推理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方式搜索卷积计算算法。
- 为了方便比较不同模型的推理速度,输入采用同样大小的图片,为 3x640x640,采用
推理速度¶
模型 | 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 |
- RCNN系列模型Fluid-TensorRT速度相比Fluid预测没有优势,原因是: TensorRT仅支持定长输入,当前基于ResNet系列的RCNN模型,只有backbone部分采用了TensorRT子图计算,比较耗时的stage-5没有基于TensorRT计算。 Fluid对CNN模型也做了一系列的融合优化。后续TensorRT版本升级、或有其他优化策略时再更新数据。
- YOLO v3系列模型,Fluid-TensorRT相比Fluid预测加速5% - 10%不等。
- SSD和YOLOv3系列模型 TensorRT-FP16预测速度有一定的优势,加速约20% - 40%不等。具体如下图。
注解
文中超链接以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
andmerge_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包,均为可选安装。
- typeguard 在Python 3中用来进行数据类型验证。
- docstring_parser 用来解析注释。
如需安装,运行下面命令即可。
pip install typeguard http://github.com/willthefrog/docstring_parser/tarball/master
相关工具¶
为了方便用户配置,PaddleDection提供了一个工具 (tools/configure.py
), 共支持四个子命令:
list
: 列出当前已注册的模块,如需列出具体类别的模块,可以使用--category
指定。help
: 显示指定模块的帮助信息,如描述,配置项,配置文件模板及命令行示例。analyze
: 检查配置文件中的缺少或者多余的配置项以及依赖缺失,如果给出type hint, 还可以检查配置项中错误的数据类型。非默认配置也会高亮显示。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 # 在多进程/多线程模式中对数据预处理操作进行加速
数据准备¶
PaddleDetection目前支持COCO、Pascal VOC 和WIDER-FACE数据源,默认数据集可自动下载,请参考默认数据集安装方法。 同时我们还支持自定义数据源,包括(1)自定义数据源转换成COCO数据集;(2)定义新的数据源。
数据准备分为三步:
- (1)数据解析
- (2)数据预处理
- (3)组建Reader迭代器
下面为您分别介绍下这三步的具体内容:
数据解析¶
数据解析逻辑在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_rec
和voc_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格式数据源roidbs
和cname2cid
。
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格式标注文件,更新roidbs
和cname2cid
。
添加新数据源¶
- (1)新建
./source/xxx.py
,定义类XXXDataSet
继承自DataSet
基类,完成注册与序列化,并重写load_roidb_and_cname2cid
方法对roidbs
与cname2cid
更新:
@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)格式 |
几点说明:
- 上表中的数据增强算子的输入与输出都是单张图片
sample
,sample
是由{'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
下需要序列化数据源实例,如COCODataSet
、VOCDataSe
和自定义的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配置文件中的TrainReader
、EvalReader
和TestReader
的编写,您也可以将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等最终结果的公共检测组件
新增模型¶
我们以单阶段检测器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_loss
与nms
变量指向外部定义好的检测组件/算子;- anchor的检测头实现中类函数需有输出loss接口
get_loss
与预测框或建议框输出接口get_prediction
; - 两阶段检测器在anchor的检测头里定义的是候选框输出接口
get_proposals
,之后还会在roi_extractors
与roi_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__
函数中传入我们上面定义好的backbone
与yolo_head
的名称即可,根据yaml配置文件里这些组件的参数初始化,ppdet.core.workspace
会自动解析加载; - 在architecture类里必须定义
build_inputs
函数,为了适配检测网络的输入与Reader模块,具体见模型输入设置模块; - 在architecture类里必须定义
train
、eval
和test
函数,在训练、评估和测试程序中会分别调用这三个函数来在不同场景中加载网络模型。
2.配置编写:
首先定义网络模型名称:
architecture: YOLOv3
接下来根据网络模型名称YOLOv3
来初始化网络组件名称:
YOLOv3:
backbone: DarkNet
yolo_head: YOLOv3Head
之后backbone
、yolo_head
的配置步骤在上面已经介绍,完成如上配置就完成了物体检测模型组网的工作。
模型输入设置¶
在architecture定义的类里必须含有build_inputs
函数,这个函数的作用是生成feed_vars
和loader
。
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
几点说明:
PiecewiseDecay
与LinearWarmup
策略在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中的路径参数即可。
- 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
- 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
中,为实现这一目的,可通过如下方式实现:
- 在 YMAL 配置文件中通过设置
finetune_exclude_pretrained_params
字段。可参考配置文件 - 在 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'] \
- 说明:
- pretrain_weights的路径为COCO数据集上开源的faster RCNN模型链接,完整模型链接可参考MODEL_ZOO
- 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-dcn
和YOLOv3-MobileNetV1
分别减少了16.06%
和34.27%
的FLOPs,输入图像尺寸为608时精度分别提高0.7
和0.9
- 在使用
r578
剪裁策略下,YOLOv3-ResNet50-vd-dcn
和YOLOv3-MobileNetV1
分别减少了32.98%
和69.64%
的FLOPs,输入图像尺寸为608时精度分别降低0.8
和1.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
三种不同尺寸下的精度结果 - 在使用
sensity
和r578
剪裁策略下,YOLOv3-MobileNetV1
分别减少了34.55%
和69.57%
的FLOPs,输入图像尺寸为608时精度分别提高2.2
和1.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%
- 在使用
sensity
和r578
剪裁策略下,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.4
和1.2
YOLOv3-ResNet34
使用离线(post)和在线(aware)两种量化方式,输入图像尺寸为608时精度分别降低0.5
和1.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.3
和2.1
BlazeFace-Lite
模型使用在线(aware)量化方式,在Easy/Medium/Hard
数据集上精度分别降低1.2
,1.2
和1.1
BlazeFace-NAS
模型使用在线(aware)量化方式,在Easy/Medium/Hard
数据集上精度分别降低0.6
,1.0
和1.6
模型蒸馏¶
运行该示例前请安装PaddleSlim和Paddle1.6或更高版本
模型蒸馏教程¶
安装PaddleSlim¶
可按照PaddleSlim使用文档中的步骤安装PaddleSlim
蒸馏策略说明¶
关于蒸馏API如何使用您可以参考PaddleSlim蒸馏API文档
这里以ResNet34-YOLOv3蒸馏训练MobileNetV1-YOLOv3模型为例,首先,为了对student model
和teacher 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 model
和teacher 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。
这里以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
蒸馏任务执行过程中会自动保存断点。如果需要从断点继续训练请用-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
为训练得到的模型路径
运行命令为:
# 使用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
示例结果¶
模型量化¶
运行该示例前请安装Paddle1.6或更高版本和PaddleSlim
模型量化压缩教程¶
安装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。
使用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}
查看如何通过命令行覆盖配置文件中的参数。
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_aware
和paddleslim.quant.convert
两个接口。
paddleslim.quant.quant_aware
作用是在网络中的conv2d、depthwise_conv2d、mul等算子的各个输入前插入连续的量化op和反量化op,并改变相应反向算子的某些输入。示例图如下:
图1:应用 paddleslim.quant.quant_aware 后的结果
在脚本中使用保存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
还会将conv2d
、depthwise_conv2d
、mul
等算子参数变为量化后的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
预测¶
在脚本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
导出模型步骤中导出的FP32模型可使用PaddleLite进行加载预测,可参见教程Paddle-Lite如何加载运行量化模型
量化模型¶
- 量化策略
post
为使用离线量化得到的模型,aware
为在线量化训练得到的模型。
骨架网络 | 预训练权重 | 量化策略 | 输入尺寸 | 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的训练、评估与预测流程
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/
路径下执行。
已发布裁剪模型见压缩模型库
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
通过观察参数名称和参数的形状,筛选出所有卷积层参数,并确定要裁剪的卷积层参数。
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_r50或mask_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_sensitive将demo.data.1
和demo.data.2
两个文件合并分析。
注解
文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。
注解
文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。
特色模型¶
YOLOv3增强模型¶
简介¶
YOLOv3 是由 Joseph Redmon 和 Ali 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掉某一块区域,更适应于在检测任务中提高网络泛化能力。
image-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 | 链接 | 链接 |
注意:
- [1] 模型统一使用8卡训练。
- [2] 参考下面关于SSDLite量化的说明。
- [3] 参考下面关于YOLO剪裁的说明。
评测结果¶
- 模型使用 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_conv1
与se_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%。下图给出了目前类似速度的目标检测方法的速度与精度指标。
pssdet
注意
这里为了更方便地对比,统一将V100的预测耗时乘以1.2倍,近似转化为Titan V的预测耗时。
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-Squeeze 在Cornernet基础上进行改进,预测目标框的左上角和右下角的位置,同时参考SqueezeNet和MobileNet的特点,优化了CornerNet骨干网络Hourglass-104,大幅提升了模型预测速度,相较于原版YOLO-v3,在训练精度和推理速度上都具备一定优势。
特点:
- 使用corner_pooling获取候选框左上角和右下角的位置
- 替换Hourglass-104中的residual block为SqueezeNet中的fire-module
- 替换第二层3x3卷积为3x3深度可分离卷积
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
未来工作¶
- mish激活函数优化
- mosaic数据预处理实现
如何贡献代码¶
我们非常欢迎您可以为PaddleDetection提供代码,您可以提交PR供我们review;也十分感谢您的反馈,可以提交相应issue,我们会及时解答。
竞赛冠军模型¶
CACascade RCNN¶
简介¶
CACascade RCNN是百度视觉技术部在Objects365 2019 Challenge上夺冠的最佳单模型之一,Objects365是在通用物体检测领域的一个全新的数据集,旨在促进对自然场景不同对象的检测研究。Objects365在63万张图像上标注了365个对象类,训练集中共有超过1000万个边界框。这里放出的是Full Track任务中最好的单模型之一。
方法描述¶
针对大规模物体检测算法的特点,我们提出了一种基于图片包含物体类别的数量的采样方式(Class Aware Sampling)。基于这种方式进行训练模型可以在更短的时间使模型收敛到更好的效果。
本次公布的最好单模型是一个基于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 | 配置文件 |
模型效果¶
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
方法描述¶
该模型结合了当前较优的检测方法。具体地,它将ResNet200-vd作为检测模型的骨干网络,其imagenet分类预训练模型可以在这里下载;结合了CascadeCA RCNN、Feature Pyramid Networks、Non-local、Deformable V2等方法。在这里需要注意的是,标准的CascadeRCNN是只预测2个框(前景和背景,使用得分信息去判断最终前景所属的类别),而该模型对每个类别都单独预测了一个框(Cascade Class Aware)。最终模型框图如下图所示。
由于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的模型评估方法可以参考文档
- 下载模型并解压。
- 运行预测程序。
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
文件夹中查看。
模型检测效果¶
注解
文中超链接以GitHub中展示为准,如出现超链接无法访问,请点击网页右上角「Edit on github」查看源文件进行索引,有任何问题欢迎在 GitHub 上提issue。
English | 简体中文
人脸检测模型¶
模型库与基线¶
下表中展示了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 |
注意:
- 我们在FDDB数据集上使用多尺度测试的方法得到mAP,具体细节请参考在FDDB数据集上评估。
推理时间和模型大小比较¶
网络结构 | 类型 | 输入尺寸 | 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/
中,并且之后的训练测试会自动加载它们。
训练与推理¶
训练流程与推理流程方法与其他算法一致,请参考GETTING_STARTED_cn.md。注意:
BlazeFace
和FaceBoxes
训练是以每卡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
: 评估模式,包括widerface
和fddb
,默认是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_dir
和annotation
字段内容:
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_FILE
是tools/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
配置文件进行训练与评估,使用方法与上一节内容一致。
算法细节¶
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
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
预测结果示例:
行人检测(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
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
预测结果示例:
注解
文中超链接以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) | - | 下载链接 | 配置文件 |
注意事项:
- Deformable卷积网络v2(dcn_v2)参考自论文Deformable ConvNets v2.
c3-c5
意思是在resnet模块的3到5阶段增加dcn
.- 详细的配置文件在configs/dcn
Res2Net¶
- 详情见Res2Net模型库。
IOU loss¶
- 目前模型库中包括GIOU loss和DIOU loss,详情见IOU loss模型库.
Libra R-CNN¶
- 详情见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 | 下载链接 | 配置文件 |
注意事项:
- Group Normalization参考论文Group Normalization.
- 详细的配置文件在configs/gn
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']
,配置数值作用规则如下:
- 如果模块配置中提供了
num_classes
,会优先使用其数值。 - 如果模块配置中未提供
num_classes
,但配置文件中存在全局键值,那么会使用全局键值。 - 两者均为配置的情况下,将使用默认值(
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。