序言
paddleclas里集成了很多优秀的分类模型,使用paddleclas对数据集进行分类训练,记录训练过程,供以后翻阅。
一、准备数据集
默认paddle环境安装好了,按照要求准备imageNet1k格式的数据,格式如下:
├── train
│ ├── n01440764
│ │ ├── n01440764_10026.JPEG
│ │ ├── n01440764_10027.JPEG
├── train.txt
...
├── val
│ ├── ILSVRC2012_val_00000001.JPEG
│ ├── ILSVRC2012_val_00000002.JPEG
├── val.txt
PaddleClas 使用 txt 格式文件指定训练集和测试集,以 ImageNet1k 数据集为例,其中 train_list.txt 和 val_list.txt 的格式形如:
# 每一行采用"空格"分隔图像路径与标注
# 下面是 train_list.txt 中的格式样例
train/n01440764/n01440764_10026.JPEG 0
...
# 下面是 val_list.txt 中的格式样例
val/ILSVRC2012_val_00000001.JPEG 65
train.txt和val.txt脚本生成准备:
import os
import cv2
classname = ["cat","dog","brid"]
img_path = ["/data/train_data/train/","/data/train_data/test/"]
file_train = open("train.txt","w")
file_test = open("val.txt","w")
for i,images_path in enumerate(img_path):
for indx ,clsname in enumerate(classname):
for name in os.listdir(os.path.join(images_path,clsname)):
if i ==0:
file_train.write("train/"+clsname+"/"+name+" "+str(indx))
file_train.write("\n")
else:
file_test.write("test/" + clsname + "/" + name + " " + str(indx))
file_test.write("\n")
file_train.close()
file_test.close()
二、配置修改
因为是训练imageNet1k格式数据,所以修改ppcls/configs/ImageNet里的配置文件,想训练哪个就修改哪个,这里我使用PPLCNet/PPLCNetV2_base.yaml,重点内容修改对象:
- 预训练模型地址
- 训练轮次
- 训练图片大小
- 分类网络类别数
- 学习率
- 数据集地址
- 训练批次
- 数据增强
示例修改如下:
# global configs
Global:
checkpoints: null
pretrained_model: ./models/PPLCNetV2_base_pretrained # 预训练模型地址
output_dir: ./output/ # 输出地址
device: gpu
save_interval: 1
eval_during_train: True
eval_interval: 1
epochs: 100 # 训练轮次
print_batch_step: 10
use_visualdl: False
# used for static mode and model export
image_shape: [3, 768, 768] # 训练图片大小
save_inference_dir: ./inference
# model architecture
Arch:
name: PPLCNetV2_base
class_num: 4 # 类别数
# loss function config for traing/eval process
Loss:
Train:
- CELoss:
weight: 1.0
epsilon: 0.1
Eval:
- CELoss:
weight: 1.0
Optimizer:
name: Momentum
momentum: 0.9
lr:
name: Cosine
learning_rate: 0.1 # 学习率
warmup_epoch: 3 # 预热轮次
regularizer:
name: 'L2'
coeff: 0.00004
# data loader for train and eval
DataLoader:
Train:
dataset:
name: ImageNetDataset # 数据集类型
image_root: /home/cai/data/train_data/ # 图片root地址
cls_label_path: /home/cai/data/train_data/train.txt # txt地址
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- RandCropImage:
size: 736
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
sampler:
name: DistributedBatchSampler
batch_size: 8 # 训练批次
drop_last: False
shuffle: True
loader:
num_workers: 4
use_shared_memory: True
Eval:
dataset:
name: ImageNetDataset
image_root: /home/cai/data/train_data/
cls_label_path: /home/cai/data/train_data/val.txt
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
resize_short: 768
- CropImage:
size: 736
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
sampler:
name: DistributedBatchSampler
batch_size: 8
drop_last: False
shuffle: False
loader:
num_workers: 4
use_shared_memory: True
Infer:
infer_imgs: docs/images/inference_deployment/whl_demo.jpg
batch_size: 10
transforms:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
resize_short: 768
- CropImage:
size: 736
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- ToCHWImage:
PostProcess:
name: Topk
topk: 3 # 如果类别数小于5的话
class_id_map_file: ppcls/utils/label_list.txt # 类别标签
Metric:
Train:
- TopkAcc:
topk: [1, 3]
Eval:
- TopkAcc:
topk: [1, 3]
三、模型训练
命令行运行:
python tools/train.py -c ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml
当前精度最佳的模型会保存在 output/PPLCNetV2_base/best_model.pdparams
四、模型评估
python3 tools/eval.py -c ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml -o Global.pretrained_model=output/PPLCNetV2_base/best_model
-o Global.pretrained_model=“output/PPLCNetV2_base/best_model” 指定了当前最佳权重所在的路径,如果指定其他权重,只需替换对应的路径即可。
五、模型预测
python3 tools/infer.py \
-c ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml \
-o Global.pretrained_model=output/PPLCNetV2_base/best_model \
-o Infer.infer_imgs=./images/0001.jpg
这里-o Global.pretrained_model=“output/PPLCNetV2_base/best_model” 指定了当前最佳权重所在的路径,如果指定其他权重,只需替换对应的路径即可。
默认输出的是 Top-5 的值,如果希望输出 Top-k 的值,可以指定-o Infer.PostProcess.topk=k,其中,k 为您指定的值。
六、基于训练得到的权重导出 inference 模型
python tools/export_model.py \
-c ppcls/configs/ImageNet/PPLCNetV2/PPLCNetV2_base.yaml \
-o Global.pretrained_model=output/PPLCNetV2_base/best_model \
-o Global.save_inference_dir=deploy/models/PPLCNetV2_base_infer
执行完该脚本后会在 deploy/models/ 下生成 PPLCNet_x1_0_infer 文件夹,models 文件夹下应有如下文件结构:
├── PPLCNet_x1_0_infer
│ ├── inference.pdiparams
│ ├── inference.pdiparams.info
│ └── inference.pdmodel
使用inference模型预测。cd到deploy目录中:
# 使用下面的命令使用 GPU 进行预测
python3 python/predict_cls.py -c configs/inference_cls.yaml -o Global.inference_model_dir=models/PPLCNet_x1_0_infer -o Infer.infer_imgs=./images/0001.jpg
# 使用下面的命令使用 CPU 进行预测
python3 python/predict_cls.py -c configs/inference_cls.yaml -o Global.inference_model_dir=models/PPLCNet_x1_0_infer -o Global.use_gpu=False -o Infer.infer_imgs=./images/0001.jpg
基于文件夹的批量预测:
# 使用下面的命令使用 GPU 进行预测,如果希望使用 CPU 预测,可以在命令后面添加 -o Global.use_gpu=False
python3 python/predict_cls.py -c configs/inference_cls.yaml -o Global.inference_model_dir=models/PPLCNetV2_base_infer -o Global.infer_imgs=images/ImageNet/
七、paddle2onnx
paddle2onnx --model_dir ./ --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file ./det_shv2.onnx --opset_version 11 --enable_onnx_checker True