paddle学习赛——钢铁目标检测(yolov5ppyoloe+,Faster-RCNN)

Posted 神洛华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了paddle学习赛——钢铁目标检测(yolov5ppyoloe+,Faster-RCNN)相关的知识,希望对你有一定的参考价值。

文章目录

参考:

一、赛事简介

  • 比赛地址:https://aistudio.baidu.com/aistudio/competition/detail/114/0/introduction
  • 赛题介绍:本次比赛为图像目标识别比赛,要求参赛选手识别出钢铁表面出现缺陷的位置,并给出锚点框的坐标,同时对不同的缺陷进行分类。
  • 数据简介:本数据集来自NEU表面缺陷检测数据集,收集了6种典型的热轧带钢表面缺陷,即氧化铁皮压入(RS)、斑块(Pa)、开裂(Cr)、点蚀(PS)、夹杂(In)和划痕(Sc)。下图为六种典型表面缺陷的示例,每幅图像的分辨率为200 * 200像素。
  • 训练集图片1400张,测试集图片400张

提交内容及格式:

  • 结果文件命名:submission.csv(否则无法成功提交)
  • 结果文件格式:.csv(否则无法成功提交)
  • 结果文件内容:submission.csv结果文件需包含多行记录,每行包括4个字段,内容示例如下:
image_id		bbox		    category_id			confidence
1400		    [0, 0, 0, 0]		    0			    1

各字段含义如下:

  • image_id(int): 图片id
  • bbox(list[float]): 检测框坐标(XMin, YMin, XMax, YMax)
  • category_id: 缺陷所属类别(int),类别对应字典为:‘ crazing’:0,’inclusion’:1, ’pitted_surface’:2, ,’scratches’:3,’patches’:4,’rolled-in_scale’:5
  • confidence(float): 置信度
    备注: 每一行记录1个检测框,并给出对应的category_id;同张图片中检测到的多个检测框,需分别记录在不同的行内。

二、ppyoloe+l模型,41.32分 (PaddleDetection-voc)

2.1 安装PaddleDetection

《PaddleDetection-MaskRcnn相关结构以及优化器》

  • 克隆PaddleDetection
  • 安装PaddleDetection文件夹的requirements.txt(python依赖)
  • 编译安装paddledet
  • 安装后确认测试通过
%cd ~/work

#!git clone https://github.com/PaddlePaddle/PaddleDetection.git
#如果github下载代码较慢,可尝试使用gitee
#git clone https://gitee.com/paddlepaddle/PaddleDetection

# 安装其他依赖
%cd PaddleDetection
!pip install -r requirements.txt
# 编译安装paddledet
!python setup.py install

#安装后确认测试通过:
!python ppdet/modeling/tests/test_architectures.py
!python ppdet/modeling/tests/test_architectures.py
W1001 15:08:57.768669  1185 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 11.2
W1001 15:08:57.773610  1185 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
.......
----------------------------------------------------------------------
Ran 7 tests in 2.142s

OK

2.2 数据预处理

2.2.1 解压数据集

# 解压到work下的dataset文件夹

!mkdir dataset
!unzip ../data/test.zip -d dataset
!unzip ../data/train.zip -d dataset

# 重命名为annotations和images
!mv dataset/train/IMAGES dataset/train/images
!mv dataset/train/ANNOTATIONS dataset/train/annotations

2.2.2 自定义数据集(感觉很麻烦,暂时放弃)

  • PaddleDetection的数据处理模块的所有代码逻辑在ppdet/data/中,数据处理模块用于加载数据并将其转换成适用于物体检测模型的训练、评估、推理所需要的格式。
  • 数据集定义在source目录下,其中dataset.py中定义了数据集的基类DetDataSet, 所有的数据集均继承于基类,DetDataset基类里定义了如下等方法:
  • 当一个数据集类继承自DetDataSet,那么它只需要实现parse_dataset函数即可

parse_dataset根据数据集设置:

  • 数据集根路径dataset_dir
  • 图片文件夹image_dir
  • 标注文件路径anno_path

  取出所有的样本,并将其保存在一个列表roidbs中,每一个列表中的元素为一个样本xxx_rec(比如coco_rec或者voc_rec),用dict表示,dict中包含样本的image, gt_bbox, gt_class等字段。COCO和Pascal-VOC数据集中的xxx_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中无此字段)
    'gt_class': gt_class,        # 标注框标签名称的ID序号
    'gt_bbox': gt_bbox,          # 标注框坐标(xmin, ymin, xmax, ymax)
    'gt_poly': gt_poly,          # 分割掩码,此字段只在coco_rec中出现,默认为None
    'difficult': difficult       # 是否是困难样本,此字段只在voc_rec中出现,默认为0

  • xxx_rec中的内容也可以通过DetDataSet的data_fields参数来控制,即可以过滤掉一些不需要的字段,但大多数情况下不需要修改,按照configs/dataset中的默认配置即可。

  • 此外,在parse_dataset函数中,保存了类别名到id的映射的一个字典cname2cid。在coco数据集中,会利用COCO API从标注文件中加载数据集的类别名,并设置此字典。在voc数据集中,如果设置use_default_label=False,将从label_list.txt中读取类别列表,反之将使用voc默认的类别列表。

2.2.3 准备VOC数据集(直接用这个)

参考:《如何准备训练数据》

  1. 尝试coco数据集

    • COCO数据标注是将所有训练图像的标注都存放到一个json文件中。数据以字典嵌套的形式存放
    • 用户数据集转成COCO数据后目录结构如下:
    dataset/xxx/
    ├── annotations
    │   ├── train.json  # coco数据的标注文件
    │   ├── valid.json  # coco数据的标注文件
    ├── images
    │   ├── xxx1.jpg
    │   ├── xxx2.jpg
    │   ├── xxx3.jpg
    │   |   ...
    ...
    
    • json格式标注文件,得自己生成,目前我知道的就是用paddledetection./tools/中提供的x2coco.py,将VOC数据集、labelme标注的数据集或cityscape数据集转换为COCO数据(生成json标准为文件)。这样太麻烦,还不如直接用VOC格式训练。
  2. 尝试自定义数据集(参考《数据处理模块》,重写parse_dataset感觉也很麻烦)

  3. 准备voc数据集(最简单,麻烦一点的就是生成txt文件)

    • 模仿VOC数据集目录结构,新建VOCdevkit文件夹并进入其中,然后继续新建VOC2007文件夹并进入其中,之后新建AnnotationsJPEGImagesImageSets文件夹,最后进入ImageSets文件夹中新建Main文件夹,至此完成VOC数据集目录结构的建立。

    • 将该数据集中的train/annotations/xmlsval/annotations/xmls(如果有val验证集的话)下的所有xml标注文件拷贝到VOCdevkit/VOC2007/Annotations中,

    • 将该数据集中的train/images/val/images/下的所有图片拷贝到VOCdevkit/VOC2007/JPEGImages

    • 最后在数据集根目录下输出最终的trainval.txt和test.txt文件(可用pandas完成,一会说):

  4. 生成VOC格式目录。
    如果觉得后面移动文件很麻烦,可以先生成VOC目录,再将数据集解压到VOC2007中,将其图片和标注文件夹分别重命名为AnnotationsJPEGImages

%cd work
!mkdir VOCdevkit
%cd VOCdevkit
!mkdir VOC2007
%cd VOC2007
!mkdir Annotations JPEGImages ImageSets
%cd ImageSets
!mkdir Main
%cd ../../
  1. 生成trainval.txtval.txt
    由于该数据集中缺少已标注图片名列表文件trainval.txtval.txt,所以需要进行生成,用pandas处理更直观
# 遍历图片和标注文件夹,将所有文件后缀正确的文件添加到列表中
import os
import pandas as pd
ls_xml,ls_image=[],[]
for xml in os.listdir('dataset/train/annotations'):
    if xml.split('.')[1]=='xml':
        ls_xml.append(xml)

for image in os.listdir('dataset/train/images'):
    if image.split('.')[1]=='jpg':
        ls_image.append(image)

读取xml文件列表和image文件名列表之后,要先进行排序。

  • 直接df.sort_values([‘image’,‘xml’],inplace=True)是先对image排序,再对xml排序,是整个表排序而不是单列分别排序,这样的结果是不对的
  • 直接分别排序再合并,结果也不对。因为添加xml列的时候,默认是按key=index来合并的,而两个列表的文件都是乱序的,这样排序后index也不相同,所以需要分别排序后重设索引,且丢弃原先索引,最后再合并。
df=pd.DataFrame(ls_image,columns=['image'])
df.sort_values('image',inplace=True)
df=df.reset_index(drop=True)
s=pd.Series(ls_xml).sort_values().reset_index(drop=True)
df['xml']=s
df.head(3)
	image	xml
0	0.jpg	0.xml
1	1.jpg	1.xml
2	10.jpg	10.xml

训练时,文件都是相对路径,所以要加前缀VOC2007/JPEGImages/VOC2007/Annotations/

%cd VOCdevkit
trainval=df.sample(frac=1)
trainval.image=trainval.image.apply(lambda x : 'VOC2007/JPEGImages/'+str(x))
trainval.xml=trainval.xml.apply(lambda x : 'VOC2007/Annotations/'+str(x))
trainval.to_csv('trainval.txt',sep=' ',index=0,header=0)

# 划分出训练集和验证集,保存为txt格式,中间用空格隔开
train_df=trainval[:1200]
val_df=trainval[1200:]
train_df.to_csv('train.txt',sep=' ',index=0,header=0)
val_df.to_csv('val.txt',sep=' ',index=0,header=0)

!cp -r train/annotations/* ../VOCdevkit/VOC2007/Annotations
!cp -r train/images/* ../VOCdevkit/VOC2007/JPEGImages

查看一张图片信息:

from PIL import Image
image = Image.open('dataset/train/images/0.jpg')
print('width: ', image.width)
print('height: ', image.height)
print('size: ', image.size)
print('mode: ', image.mode)
print('format: ', image.format)
print('category: ', image.category)
print('readonly: ', image.readonly)
print('info: ', image.info)
image.show()

2.3 修改配置文件,准备训练

  • 模型效果请参考ppyolo文档
  • 配置参数参考yolo配置参数说明《如何更好的理解reader和自定义修改reader文件》
  • PaddleYOLO库集成了yolo系列模型,包括yolov5/6/7/X,后续可以试试。
  • 修改配置文件
    • 手动复制一个configs/ppyoloe/ppyoloe_plus_crn_m_80e_coco.yml文件的副本,其它类似,防止改错了无法还原
    • configs/datasets/voc.yml不用复制,免得下次重新写,修改后如下:(TestDataset最好不要写dataset_dir字段,否则后面infer.py推断的时候,选择参数save_results=True会报错label_list label_list.txt not a file
      metric: VOC
      map_type: 11point
      num_classes: 6
      
      TrainDataset:
        !VOCDataSet
          dataset_dir: ../VOCdevkit
          anno_path: train.txt
          label_list: label_list.txt
          data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
      
      EvalDataset:
        !VOCDataSet
          dataset_dir: ../VOCdevkit
          anno_path: val.txt
          label_list: label_list.txt
          data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
      
      TestDataset:
        !ImageFolder
          anno_path: ../VOCdevkit/label_list.txt
      
    • 学习率改为0.00025,epoch=60,max_epochs=72,!LinearWarmup下的epoch改为4。
    • reader部分训练验证集的batch_size从8改为16,推理时bs也改为16,大大加快推理速度(之前默认为1,特别慢)
    • PP-YOLOE+支持混合精度训练,请添加--amp.
    • 使用YOLOv3模型如何通过yml文件修改输入图片尺寸
      • Multi-Scale Training:多尺度训练 。yolov3中作者认为网络输入尺寸固定的话,模型鲁棒性受限,所以考虑多尺度训练。具体的,在训练过程中每隔10个batches,重新随机选择输入图片的尺寸[320,352,416…608](Darknet-19最终将图片缩放32倍,所以一般选择32的倍数)。
      • 模型预测部署需要用到指定的尺寸时,首先在训练前需要修改configs/_base_/yolov3_reader.yml中的TrainReaderBatchRandomResizetarget_size包含指定的尺寸,训练完成后,在评估或者预测时,需要将EvalReaderTestReader中的Resizetarget_size修改成对应的尺寸,如果是需要模型导出(export_model),则需要将TestReader中的image_shape修改为对应的图片输入尺寸 。
      • 如果只改了训练集入网尺寸,验证测试集尺寸不变,会报错
    • Paddle中支持的优化器Optimizer在PaddleDetection中均支持,需要手动修改下配置文件即可

ppyoloe_plus_reader.yml修改如下:(图片都很小,把默认的入网尺寸改了)

worker_num: 4
eval_height: &eval_height 224
eval_width: &eval_width 224
eval_size: &eval_size [*eval_height, *eval_width]

TrainReader:
  sample_transforms:
    - Decode: 
    - RandomDistort: 
    - RandomExpand: fill_value: [123.675, 116.28, 103.53]
    - RandomCrop: 
    - RandomFlip: 
  batch_transforms:
    - BatchRandomResize: target_size: [96, 128, 160, 192, 224, 256, 288,320,352], random_size: True, random_interp: True, keep_ratio: False
    - NormalizeImage: mean: [0., 0., 0.], std: [1., 1., 1.], norm_type: none
    - Permute: 
    - PadGT: 
  batch_size: 16
  shuffle: true
  drop_last: true
  use_shared_memory: true
  collate_batch: true

EvalReader:
  sample_transforms:
    - Decode: 
    - Resize: target_size: *eval_size, keep_ratio: False, interp: 2
    - NormalizeImage: mean: [0., 0., 0.], std: [1., 1., 1.], norm_type: none
    - Permute: 
  batch_size: 16

TestReader:
  inputs_def:
    image_shape: [3, *eval_height, *eval_width]
  sample_transforms:
    - Decode: 
    - Resize: target_size: *eval_size, keep_ratio: False, interp: 2
    - NormalizeImage: mean: [0., 0., 0.], std: [1., 1., 1.], norm_type: none
    - Permute: 
  batch_size: 1 #最好是1,下文会说明

训练参数列表:(可通过–help查看)

FLAG支持脚本用途默认值备注
-cALL指定配置文件None必选,例如-c configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.yml
-oALL设置或更改配置文件里的参数内容None相较于-c设置的配置文件有更高优先级,例如:-o use_gpu=False
–evaltrain是否边训练边测试False如需指定,直接--eval即可
-r/–resume_checkpointtrain恢复训练加载的权重路径None例如:-r output/faster_rcnn_r50_1x_coco/10000
–slim_configALL模型压缩策略配置文件None例如--slim_config configs/slim/prune/yolov3_prune_l1_norm.yml
–use_vdltrain/infer是否使用VisualDL记录数据,进而在VisualDL面板中显示FalseVisualDL需Python>=3.5
–vdl_log_dirtrain/infer指定 VisualDL 记录数据的存储路径train:vdl_log_dir/scalar infer: vdl_log_dir/imageVisualDL需Python>=3.5
–output_evaleval评估阶段保存json路径None例如 --output_eval=eval_output, 默认为当前路径
–json_evaleval是否通过已存在的bbox.json或者mask.json进行评估False如需指定,直接--json_eval即可, json文件路径在--output_eval中设置
–classwiseeval是否评估单类AP和绘制单类PR曲线False如需指定,直接--classwise即可
–output_dirinfer/export_model预测后结果或导出模型保存路径./output例如--output_dir=output
–draw_thresholdinfer可视化时分数阈值0.5例如--draw_threshold=0.7
–infer_dirinfer用于预测的图片文件夹路径None--infer_img--infer_dir必须至少设置一个
–infer_imginfer用于预测的图片路径None--infer_img--infer_dir必须至少设置一个,infer_img具有更高优先级
–save_resultsinfer是否在文件夹下将图片的预测结果保存到文件中False可选

2.4 ppyoloe+s,mAP=77.6%

# lr=0.0002,epoch=40,time=2572s
%cd ~/work/PaddleDetection/
!python -u tools/train.py -c configs/ppyoloe/ppyoloe_plus_crn_s_80e_coco-Copy1.yml \\
            --use_vdl=true \\
            --vdl_log_dir=vdl_dir/scalar \\
            --eval \\
            --amp
[10/02 02:51:09] ppdet.engine INFO: Epoch: [45] [ 0/75] learning_rate: 0.000085 loss: 1.671754 loss_cls: 0.781011 loss_iou: 0.174941 loss_dfl: 0.880325 loss_l1: 0.378740 eta: 0:10:17 batch_cost: 0.5481 data_cost: 0.0049 ips: 29.1918 images/s
[10/02 02:51:58] ppdet.engine INFO: Epoch: [46] [ 0/75] learning_rate: 0.000080 loss: 1.672976 loss_cls: 0.782366 loss_iou: 0.173936 loss_dfl: 0.885129 loss_l1: 0.378303 eta: 0:09:36 batch_cost: 0.5459 data_cost: 0.0049 ips: 29.3068 images/s
[10/02 02:52:48] ppdet.engine INFO: Epoch: [47] [ 0/75] learning_rate: 0.000075 loss: 1.679924 loss_cls: 0.791866 loss_iou: 0.173251 loss_dfl: 0.892923 loss_l1: 0.371434 eta: 0:08:55 batch_cost: 0.5490 data_cost: 0.0049 ips: 29.1445 images/s
[10/02 02:53:37] ppdet.engine INFO: Epoch: [48] [ 0/75] learning_rate: 0.000069 loss: 1.669277 loss_cls: 0.785255 loss_iou: 0.173793 loss_dfl: 0.879943 loss_l1: 0.384001 eta: 0:08:14 batch_cost: 0.5546 data_cost: 0.0072 ips: 28.8511 images/s
[10/02 02:54:25] ppdet.engine INFO: Epoch: [49] [ 0/75] learning_rate: 0.000064 loss: 1.653534 loss_cls: 0.783021 loss_iou: 0.173808 loss_dfl: 0.865887 loss_l1: 0.377161 eta: 0:07:32 batch_cost: 0.5445 data_cost: 0.0080 ips: 29.3847 images/s
[10/02 02:55:18] ppdet.utils.checkpoint INFO: Save checkpoint: output/ppyoloe_plus_crn_l_80e_coco-Copy1
[10/02 02以上是关于paddle学习赛——钢铁目标检测(yolov5ppyoloe+,Faster-RCNN)的主要内容,如果未能解决你的问题,请参考以下文章

如何基于Flutter和Paddle Lite实现实时目标检测

水下机器人线上赛战火升级,目标检测通信赛项等你来战

Paddle入门实战系列:车牌检测与识别

Paddle OCR文字识别学习

Paddle入门实战系列:中文场景文字识别

Paddle入门实战系列:中文场景文字识别