安装其他依赖
cd PaddleDetection
pip install -r requirements.txt
编译安装paddledet
python setup.py install
picodet/data/
picodet/data/
"""
生成训练集和测试集txt文本
可随机选取
"""
import os
import random
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--dataset', type=str, required=True, help='dataset relative path')
parser.add_argument('-t', '--txt', type=str, required=True, help='txt relative path')
parser.add_argument('-r', '--ratio', type=float, default=1.0, help='Percentage of training sets 0<=ratio<=1')
args = parser.parse_args()
def create_txt(data_path, train_path, eval_path, ratio):
path_list = list()
i = 0
for home, dirs, files in os.walk(data_path):
for filename in files:
if filename.split('.')[-1] == 'jpg':
path_jpg = os.path.join(home, filename)
path_xml1 = os.path.join(home, 'outputs/' + filename.split('.')[0] + '.xml')
path_xml2 = os.path.join(home, filename.split('.')[0] + '.xml')
if os.path.exists(path_xml1):
i = i + 1
path_list.append((path_jpg, path_xml1))
elif os.path.exists(path_xml2):
i = i + 1
path_list.append((path_jpg, path_xml2))
else:
print("no such file:" + path_jpg + " xml.")
seed = 1
random.seed(seed)
# random.shuffle(path_list)
f_train = open(train_path, 'w')
f_eval = open(eval_path, 'w')
for e, content in enumerate(path_list):
img, xml = content
text = img + ' ' + xml + '\n'
if e < len(path_list) * ratio:
f_train.write(text)
else:
f_eval.write(text)
f_train.close()
f_eval.close()
print("Total has " + str(i) + " images.")
print("over")
data_path = "/home/sq/Desktop/picodet/data/" + args.dataset
train_path = "/home/sq/Desktop/picodet/PaddleDetection-release-2.4/dataset/" + args.txt + "/train_list.txt"
eval_path = "/home/sq/Desktop/picodet/PaddleDetection-release-2.4/dataset/" + args.txt + "eval_list.txt"
if args.ratio < 0 or args.ratio > 1:
print("Please enter ratio greater than 0 but less than 1")
else:
create_txt(data_path, train_path, eval_path, args.ratio)
调用方法
python get_txt.py -d fish -t s416_7/s416_7_220922 -r 1.0
生成文件 train_list.txt
/home/sq/Desktop/picodet/data/20220623/ahd_3_20210508_183507990/0732.jpg /home/sq/Desktop/picodet/data/20220623/ahd_3_20210508_183507990/outputs/0732.xml
/home/sq/Desktop/picodet/data/20220623/ahd_3_20210508_180102968/1020.jpg /home/sq/Desktop/picodet/data/20220623/ahd_3_20210508_180102968/outputs/1020.xml
/home/sq/Desktop/picodet/data/20220623/ahd_5_20210508_210941744/1016.jpg /home/sq/Desktop/picodet/data/20220623/ahd_5_20210508_210941744/outputs/1016.xml
picodet/PaddleDetection-release-2.4/dataset/s_416/
lable_list.txt
car
bus
pedestrian
tricycle
truck
special_vehicle
rider
picodet/PaddleDetection-release-2.4/configs/datasets/s416_7/
s416_7_220922.yml
s416_7_220922.yml 修改内容
metric: VOC
map_type: 11point
num_classes: 7 #修改类别数
TrainDataset:
!VOCDataSet
dataset_dir: /home/sq/Desktop/picodet/PaddleDetection-release-2.4/dataset/s416_7/s416_7_220922 #修改数据路径
anno_path: train_list.txt
label_list: label_list.txt
data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
EvalDataset:
!VOCDataSet
dataset_dir: /home/sq/Desktop/picodet/PaddleDetection-release-2.4/dataset/s416_7/s416_7_220922#修改数据路径
anno_path: eval_list.txt
label_list: label_list.txt
data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
TestDataset:
!ImageFolder
anno_path: /home/sq/Desktop/picodet/PaddleDetection-release-2.4/dataset/s416_7/s416_7_220922/label_list.txt
picodet/PaddleDetetion-release-2.4/configs/picodet
- picodet_s_416_coco_lcnet.yml
_BASE_: [
'../datasets/s416_7/s416_7_220922.yml#修改数据路径',
'../runtime.yml',
'_base_/picodet_v2.yml',
'_base_/optimizer_300e.yml',
'_base_/picodet_416_reader.yml',
]
pretrain_weights:
weights:
find_unused_parameters: True
use_ema: true
epoch: 301 #修改训练轮数
snapshot_epoch: 10 #修改多少轮保存一次参数
LCNet:
scale: 0.75
feature_maps: [3, 4, 5]
LCPAN:
out_channels: 96
PicoHeadV2:
conv_feat:
name: PicoFeat
feat_in: 96
feat_out: 96
num_convs: 2
num_fpn_stride: 4
norm_type: bn
share_cls_reg: True
use_se: True
feat_in_chan: 96
TrainReader:
batch_size: 16 #修改
LearningRate:
base_lr: 0.05
schedulers:
- !CosineDecay
max_epochs: 300
- !LinearWarmup
start_factor: 0.1
steps: 300
picodet/PaddleDetection-release-2.4/configs/
runtime.yml
use_gpu: true
use_xpu: false
log_iter: 100
save_dir: s416_7/s416_7_220922 #修改保存路径
snapshot_epoch: 10
print_flops: false
# Exporting the model
export:
post_process: False # Whether post-processing is included in the network when export model.
nms: False # Whether NMS is included in the network when export model.
benchmark: True # It is used to testing model performance, if set `True`, post-process and NMS will not be exported.
picodet/PaddleDetetion-release-2.4/configs/picodet/_base_/
- optimizer_300e.yml
epoch: 300 #修改epoch
LearningRate:
base_lr: 0.05
schedulers:
- !CosineDecay
max_epochs: 300 #修改
- !LinearWarmup
start_factor: 0.1
steps: 300
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.00004
type: L2
picodet/PaddleDetetion-release-2.4/configs/picodet/_base_/
- Picodet_416_reader.yml
worker_num: 6
eval_height: &eval_height 416
eval_width: &eval_width 416
eval_size: &eval_size [*eval_height, *eval_width]
TrainReader:
sample_transforms:
- Decode: {}
- RandomCrop: {}
- RandomFlip: {prob: 0.5}
- RandomDistort: {}
batch_transforms:
- BatchRandomResize: {target_size: [352, 384, 416, 448, 480], random_size: True, random_interp: True, keep_ratio: False}
- NormalizeImage: {is_scale: true, mean: [0.485,0.456,0.406], std: [0.229, 0.224,0.225]}
- Permute: {}
- PadGT: {}
batch_size: 16 #修改
shuffle: true
drop_last: true
EvalReader:
sample_transforms:
- Decode: {}
- Resize: {interp: 2, target_size: *eval_size, keep_ratio: False}
- NormalizeImage: {is_scale: true, mean: [0.485,0.456,0.406], std: [0.229, 0.224,0.225]}
- Permute: {}
batch_transforms:
- PadBatch: {pad_to_stride: 32}
batch_size: 8 #修改
shuffle: false
TestReader:
inputs_def:
image_shape: [1, 3, *eval_height, *eval_width]
sample_transforms:
- Decode: {}
- Resize: {interp: 2, target_size: *eval_size, keep_ratio: False}
- NormalizeImage: {is_scale: true, mean: [0.485,0.456,0.406], std: [0.229, 0.224,0.225]}
- Permute: {}
batch_size: 1
以s-416模型为例,只需修改epoch和snapshot_epoch参数,epoch表示训练轮数,snapshot_epoch表示每经过多少轮验证一次结果并保存此时的权重文件。
修改训练轮数时需要在optimizer_300e.yml中也修改epoch和max_epochs参数,若需要修改输出路径,进入runtime.yml中在对应的位置修改即可。
其中:
s416_7_220922.yml 主要说明了训练数据和验证数据的路径。
runtime.yml 主要说明了公共的运行参数,比如说是否使用GPU、每多少个epoch存储checkpoint等。
optimizer_300e.yml 主要说明了学习率和优化器的配置。
Picodet_v2.yml 主要说明模型、和主干网络的情况。
Picodet_416_reader.yml 主要说明数据读取器配置,如batch size,并发加载子进程数等,同时包含读取后预处理操作,如resize、数据增强等等。
在终端中输入下面的命令,即可开始训练:
单卡训练
# training on single-GPU
export CUDA_VISIBLE_DEVICES=0
python tools/train.py -c configs/picodet/picodet_s_320_coco_lcnet.yml --eval
多卡训练
# training on multi-GPU
export CUDA_VISIBLE_DEVICES=0,1,2,3
python -m paddle.distributed.launch --gpus 0,1,2,3 tools/train.py -c configs/picodet/picodet_s_320_coco_lcnet.yml --eval
若要边训练边评估,只需在最后加入–eval
python tools/train.py -c configs/picodet/picodet_s_320_coco_lcnet.yml--eval
若中途意外停止,可以从已保存的最后一次的权重(例如100)进行恢复训练:
python tools/train.py -c configs/picodet/picodet_s_320_coco_lcnet.yml \
-r output/picodet_s_320_coco_lcnet/100
python tools/eval.py -c configs/ picodet/picodet_s_320_coco_lcnet.yml \
-o weights=output/picodet_s_320_coco_lcnet/best_model.params
python tools/infer.py -c configs/picodet/picodet_s_320_coco_lcnet.yml \
--infer_img=demo/图片名称.png \
--output_dir=infer_output/ \
--draw_threshold=0.5 \
-o weights=output/picodet_s_320_coco_lcnet/best_model \
--use_vdl=True
其中–draw_threshold 是个可选参数. 根据 NMS 的计算,不同阈值会产生不同的结果 keep_top_k表示设置输出目标的最大数量,默认值为100,用户可以根据自己的实际情况进行设定。
在模型训练过程中保存的模型文件是包含前向预测和反向传播的过程,在实际的工业部署则不需要反向传播,因此需要将模型进行导成部署需要的模型格式。 在PaddleDetection中提供了 tools/export_model.py脚本来导出模型。
python tools/export_model.py -c configs/picodet/picodet_s_320_coco_lcnet.yml \
--output_dir=./inference_model \
- o weights=output/picodet_s_320_coco_lcnet/best_model
预测模型会导出到inference_model/ picodet_s_320_coco_lcnet目录下,分别为infer_cfg.yml, model.pdiparams, model.pdiparams.info,model.pdmodel
首先安装Paddle2ONNX(高于或等于0.6版本):
pip install paddle2onnx
再使用下面的命令进行转换:
paddle2onnx --model_dir inference_model/ picodet_s_320_coco_lcnet \
--model_filename model.pdmodel \
--params_filename model.pdiparams \
--opset_version 11 \
--save_file picodet-s-320.onnx
再使用onnxsim对其进行简化:
python -m onnxsim picodet-s-320.onnx picodet-s-320-sim.onnx