paddlex使用自定义数据集训练语义分割模型步骤:
1.数据准备
(1)使用labelme标注工具,对图片进行标注;
(2)数据集按照如下方式进行组织,原图均放在同一目录,如JPEGImages
,标注的同名json文件均放在同一目录,如Annotations
;
MyDataset/ # 语义分割数据集根目录
|--JPEGImages/ # 原图文件所在目录
| |--1.jpg
| |--2.jpg
| |--...
| |--...
|
|--Annotations/ # 标注文件所在目录
| |--1.json
| |--2.json
| |--...
| |--...
(3)标注数据格式转换
进入MyDataset/文件夹,在终端输入下列语句,随后会在converted_dataset_dir/Annotations/文件夹中生成json对应的png图片;
paddlex --data_conversion --source labelme --to SEG --pics ./JPEGImages --annotations ./Annotations --save_dir ./converted_dataset_dir
参数 | 说明 |
---|---|
–source | 表示数据标注来源,支持labelme 、jingling (分别表示数据来源于LabelMe,精灵标注助手) |
–to | 表示数据需要转换成为的格式,支持ImageNet (图像分类)、PascalVOC (目标检测),MSCOCO (实例分割,也可用于目标检测)和SEG (语义分割) |
–pics | 指定原图所在的目录路径 |
–annotations | 指定标注文件所在的目录路径 |
(4)划分数据集
使用paddlex命令即可将数据集随机划分成70%训练集,20%验证集和10%测试集,将上述的converted_dataset_dir/文件夹拷贝到上一级目录,与MyDataset/同级,输入下列语句进行数据集划分;
paddlex --split_dataset --format SEG --dataset_dir converted_dataset_dir --val_value 0.2 --test_value 0.1
执行上面命令行,会在converted_dataset_dir/下生成train_list.txt
, val_list.txt
, test_list.txt
,分别存储训练样本信息,验证样本信息,测试样本信息;
2.模型训练
首先利用以下脚本计算样本图片的均值和方差:
import numpy as np
from tqdm import tqdm
from glob import glob
import cv2
import random
import os
means = [0, 0, 0]
stdevs = [0, 0, 0]
index = 1
num_imgs = 0
imgslist = glob(r'C:\Users\*\Desktop\converted_dataset_dir\JPEGImages\\*.jpg')
for imgpath in tqdm(imgslist):
num_imgs += 1
img = cv2.imread(imgpath)
img = np.asarray(img)
img = img.astype(np.float32) / 255.
for i in range(3):
means[i] += img[:, :, i].mean()
stdevs[i] += img[:, :, i].std()
means = np.asarray(means) / num_imgs
stdevs = np.asarray(stdevs) / num_imgs
print('normMean = {} normStd = {}'.format(means, stdevs))
计算得到的结果:
n
o
r
m
M
e
a
n
=
[
0.382315840.377324210.38105058
]
n
o
r
m
S
t
d
=
[
0.235456770.24525060.24322171
]
normMean = [0.38231584 0.37732421 0.38105058] normStd = [0.23545677 0.2452506 0.24322171]
normMean=[0.382315840.377324210.38105058]normStd=[0.235456770.24525060.24322171]
训练脚本:
# -*- coding:utf-8 -*-
import paddlex as pdx
from paddlex import transforms as T
# from paddlex.seg import transforms
train_transforms = T.Compose([
T.RandomHorizontalFlip(),
T.Resize(target_size=640),
T.MixupImage(alpha=1.5, beta=1.5, mixup_epoch=-1),
T.RandomDistort(),
T.RandomBlur(),
T.Normalize(mean=[0.38231584,0.37732421,0.38105058], std=[0.23545677,0.2452506,0.24322171])
])
eval_transforms = T.Compose([
T.Resize(target_size=640),
T.Normalize(mean=[0.38231584,0.37732421,0.38105058], std=[0.23545677,0.2452506,0.24322171])
])
train_dataset = pdx.datasets.SegDataset(
data_dir='converted_dataset_dir',
file_list='converted_dataset_dir/train_list.txt',
label_list='converted_dataset_dir/labels.txt',
transforms=train_transforms,
shuffle=True)
eval_dataset = pdx.datasets.SegDataset(
data_dir='converted_dataset_dir',
file_list='converted_dataset_dir/val_list.txt',
label_list='converted_dataset_dir/labels.txt',
transforms=eval_transforms)
num_classes = len(train_dataset.labels)
model = pdx.seg.DeepLabV3P(num_classes=num_classes)
model.train(
num_epochs=40,
optimizer=None,
train_dataset=train_dataset,
train_batch_size=1,
eval_dataset=eval_dataset,
learning_rate=0.01,
save_interval_epochs=10,
# pretrain_weights='output/deeplab4/best_model',
save_dir='out/deeplab',
early_stop=True,
early_stop_patience=5,
)
将上述结果放入T.Normalize:
T.Normalize(mean=[0.38231584,0.37732421,0.38105058], std=[0.23545677,0.2452506,0.24322171])
调整一下相关参数,即可开始训练…
3.模型导出:
paddlex --export_inference --model_dir=./best_model/ --save_dir=./inference
4.可视化:
visualdl --logdir=./vdl_log