1. PaddleDetection介绍

PaddleDetection是由百度推出的目标检测开源模型库;

1.1 常见格式

.pdparams:保存参数权重的文件格式。

2. 安装PaddleDetection

Python版本:python <= 3.10;

PaddlePaddle

PaddlePaddle版本:[PaddlePaddle/PaddleDetection],需要到安装说明中查看,一般是在满足最低版本要求后安装最新的稳定版本;
PaddlePaddle安装:开始使用_飞桨

3. 数据集设置:COCO

数据集目录结构如下:

PaddleDetection
└── dataset
    └── coco
        ├── train2017
        ├── val2017 
        └── annotations  

4. 模型训练/评估/预测

train.py —— 模型训练

python -m paddle.distributed.launch --gpus 0,1,2,3,4,5,6,7 tools/train.py -c configs/ppyoloe/ppyoloe_plus_crn_l_80e_coco.yml --eval --amp

-c:指定配置文件

-r: resume,恢复训练

后面加上存档的epoch索引(从0开始);

infer.py —— 模型预测

# 预测
python tools/infer.py -c configs/faster_rcnn_r50_1x.yml --infer_img=demo/000000570688.jpg

# 在CPU上进行推理
python tools/infer.py -c configs/ppyolo/ppyolo_r50vd_dcn_1x_coco.yml -o use_gpu=false weights=https://paddledet.bj.bcebos/models/ppyolo_r50vd_dcn_1x_coco.pdparams --infer_img=demo/000000014439.jpg
# CPU推理需要显式指定:use_gpu=false
# demo/000000014439.jpg已经内置在PaddleDetection的repo文件夹中

Note:在output目录下生成的同名的测试文件会被替换。

4 模型配置说明

4.2 模型设置:model.yml

在PaddleDetection使用model.yml来配置模型的结构,配置文件的路径一般如下所示:

PaddleDetection/configs/model/model_***_coco.yml

模型参数:

  • Model:模型整体设置
  • Backbone:主干网络设置
  • PostProcess:后处理操作,(仅用于“CornerNet”模型)

4.2.1 模型类设置:Model

输入参数:

  • backbone:主干网络类名
  • neck:检测颈类名
  • head:检测头类名

4.2.2 主干类设置:Backbone

输入参数:

  • depth:主干网络深度
  • variant:变体型号
  • norm_type:归一化层类名

4.2.2 检测颈设置:Neck

输入参数:

  • in_channelslist,输入通道数
  • out_channelint,输出通道数(所有输出stage的通道数一样)
  • extra_stage:额外输出的层数

FPN:特征金字塔

Note
FPN模块在初始化时,会使用backbone输出的out_shape更新FPN的输入参数,而导致config中FPN.in_channels的设置失效。

4.3 优化器设置:optimizer.yml

参数描述
TrainReader.batch_size每张卡上的batch-size

5 代码文件说明

5.1 configs/rotate:旋转框数据集处理

5.1.1 configs/rotate/tools:旋转框处理工具

configs/rotate/tools/prepare_data.py: 进行DOTA数据集的切图处理

5.2 ppdet/utils:训练和调优的工具类和函数

5.2.1 utils/checkpoint.py

load_weight():载入模型权重

存档权重的格式要求是.pdparams

5.2 ppdet/optimizer.py:优化器设置

ppdet/optimizer.py包含了PaddleDetection优化器的设置代码;

ClassDescription
OptimizerBuilder根据config的设置构建优化器

5.3 tools/infer.py

用于进行图像的预测

5.3.1 路径预设代码

import os, sys
# add python path of PadleDetection to sys.path
parent_path = os.path.abspath(os.path.join(__file__, *(['..'] * 2)))
if parent_path not in sys.path:
    sys.path.append(parent_path)
    # 使用sys.path.append添加环境变量,在脚本执行完成之后则会失效

5.4 utils/post_process.py

用于目标检测的后处理;

5.4.1 corner_post_process()

用于CornerNet的后处理函数;
参数:

  • results:
    dict{‘bbox’, ‘im_id’},检测结果;其中字典中的属性含义如下:
    • bbox: 检测框信息,包含类别和坐标信息
    • im_id: 图像id

代码说明:

def corner_post_process(results, config, num_classes):
    detections = results['bbox'][0]
    keep_inds = (detections[:, 1] > -1)
    detections = detections[keep_inds]
    labels = detections[:, 0]
    scores = detections[:, 1]
    boxes = detections[:, 2:6]
    cls_boxes = get_nms_result(
        boxes, scores, config, num_classes, background_label=-1, labels=labels)
    results.update({'bbox': (cls_boxes, [[len(cls_boxes)]])})

6 函数和类说明

6.1 数据集处理函数

process_single_sample():处理单个样本

def process_single_sample(info, image_id, class_names):
    image_file = info['image_file']
    single_image = dict()
    single_image['file_name'] = os.path.split(image_file)[-1]
    single_image['id'] = image_id
    image = cv2.imread(image_file)
    height, width, _ = image.shape
    single_image['width'] = width
    single_image['height'] = height

    # process annotation field
    single_objs = []
    objects = info['annotation']
    for obj in objects:
        poly, name, difficult = obj['poly'], obj['name'], obj['difficult']
        if difficult == '2':
            continue

        single_obj = dict()
        single_obj['category_id'] = class_names.index(name) + 1
        single_obj['segmentation'] = [poly]
        single_obj['iscrowd'] = 0
        xmin, ymin, xmax, ymax = min(poly[0::2]), min(poly[1::2]), max(poly[
            0::2]), max(poly[1::2])
        # 使用间隔索引的方法获得四个点的X或Y坐标,并取最小值和最大值,作为bbox的坐标
        width, height = xmax - xmin, ymax - ymin
        single_obj['bbox'] = [xmin, ymin, width, height]
        single_obj['area'] = height * width
        single_obj['image_id'] = image_id
        single_objs.append(single_obj)

    return (single_image, single_objs)

6.2 预处理和数据增广:sample_transforms

官方文档:数据预处理算子 - PaddleDetection/READER.md at release/2.5

6.2.1 Decode:图像解码操作(从文件中读取图像)

7 PaddlePaddle学习笔记

7.1 张量

7.1.1 Paddle张量不支持括号索引:img_tensor[:, (2, 1, 0), :, :]

今天在使用Paddle时,使用括号索引改变颜色分量顺序时,代码报错了,
期望改变图像张量的颜色分量顺序:

img_tensor = img_tensor[:, (2, 1, 0), :, :]

Paddle报错:

...
  File "D:\Professional\Paddle\Paddle_oriented_reppoints\ppdet\engine\train_aligner.py", line 461, in train
    img_tensor = img_tensor[:, (2, 1, 0), :, :]
  File "C:\Users\songyuc\.conda\envs\conda-paddle\lib\site-packages\paddle\fluid\dygraph\varbase_patch_methods.py", line 753, in __getitem__
    return self._getitem_index_not_tensor(item)
ValueError: (InvalidArgument) Currently, Tensor.__indices__() only allows indexing by Integers,
Slices, Ellipsis, None, tuples of these types and list of Bool and Integers, but received tuple in
2th slice item (at ..\paddle/fluid/pybind/slice_utils.h:295)

感觉好像就是Paddle不支持这种索引操作;

8 PP-YOLOE

关于PP-YOLOE的论文学习笔记,请参考《PP-YOLOE的译读笔记》;
学习资料:
Paddle目标检测算法课程——PPYOLOE
Paddle目标检测算法课程——PPYOLOE | PPT
技术一览表:

名称超参数
Input size640
Down sampleAdaptiveAvgPool2d
(目前是在Head部分的代码中看到此算子作为下采样的方式)
ActSwish (SiLU)
HeadPPYOLOEHead
OptimizerSGD with momentum and L2-regularization
Weight decay0.0005

5.1 PyTorch实现:[miemie2013/miemiedetection]

关于这个repo的说明文档,请参阅《PPYOLO、PPYOLOv2、PPYOLOE的pytorch实现三合一!尽在miemiedetection!》;

5.2 学习笔记

PP-YOLOE对bias项的weight_decay是怎么处理的呢?

关于PP-YOLOE对bias项weight_decay的处理,请参考[PaddleDetection | backbones/cspresnet.py];
总的来说,就是对BN层的所有参数不使用weight_decay,即:

self.bn = nn.BatchNorm2D(
    ch_out,
    weight_attr=ParamAttr(regularizer=L2Decay(0.0)),
    bias_attr=ParamAttr(regularizer=L2Decay(0.0)))

如何在使用PyTorch实现L2Decay呢?

这里我们参考的是[miemie2013/miemiedetection]的实现方法:[miemiedetection]是从[mmdetection]中移植过来的,这里继承了mmdetection的书写方式[code – add_param_group]:

这里的model.add_param_group调用的是模型的.add_param_group()方法[ppyoloe.py – add_param_group()];

7 自定义 Paddle-C++算子

数据类型宏转换

Paddle文档:《自定义C++算子-PaddlePaddle文档 | 支持多种数据类型》

更多推荐

PaddleDetection的学习笔记