用PaddleX快速实现图像分类训练
比赛的链接:aistudio.baidu.com/aistudio/co…
PaddleX 1.3 版本文档:paddlex.readthedocs.io/zh_CN/relea…
直接使用paddle进行测试
验证飞桨安装
python -c "import paddle;paddle.utils.run_check()" 复制代码
获得下图,则安装成功
准备工作
用pip install安装paddlex
pip install paddlex==1.3.7 -i https://mirror.baidu.com/pypi/simple
复制代码
用pip install安装pycocotools
pip install pycocotools -i https://mirror.baidu.com/pypi/simple
复制代码
验证PaddleX安装
python -c "import paddlex as pdx;print(pdx.__version__)"
复制代码
获得下图,则安装成功
飞桨 – PaddleX
是一套更加简明易懂的API,并配套一键下载安装的图形化开发客户端。用PaddleX实现图像分类训练非常快速,代码量也小。
数据的处理
unzip cat_data_sets_models.zip
复制代码
解压完成
我们进入data_sets中查看下数据:
构造需要的数据
labels.txt (主要是类别标签的名称)
制造train_list.txt和val_list.txt
- 我们将原本的train_list.txt中的数据进行打乱并以70%作为训练文件,以30%作为验证图片集合
- 需要一个python脚本来进行分割
import random
rate = 0.7
with open("train_list_origin.txt","r") as f:
datas = f.readlines()
index = int(len(datas) * rate)
random.shuffle(datas)
train_list = datas[:index]
val_list = datas[index:]
with open("train_list.txt","w") as f:
for data in train_list:
f.write(data)
with open("val_list.txt","w") as f:
for data in val_list:
f.write(data)
复制代码
- train_list.txt (训练图片的路径和标签)
- val_list.txt (验证图片的路径和标签)
构造test_list.txt
- 需要一个python脚本,来完成
import os
files = os.listdir("cat_12_test")
f = open("test_list.txt","w")
for file in files:
f.write(os.path.join("cat_12_test",file) + "\n")
f.close()
复制代码
- test_list.txt
到此为止,数据已经全部处理完成
PaddleX完成图片分类
- 程序运行的主路径是
data_sets
,在此目录下新建一个output的目录
下面是程序的代码
from paddlex.cls import transforms
import paddlex as pdx
train_transforms = transforms.Compose([
transforms.RandomCrop(crop_size=224),
transforms.RandomHorizontalFlip(),
transforms.Normalize()
])
eval_transforms = transforms.Compose([
transforms.ResizeByShort(short_size=256),
transforms.CenterCrop(crop_size=224),
transforms.Normalize()
])
train_dataset = pdx.datasets.ImageNet(
data_dir='cat_12',
file_list='cat_12/train_list.txt',
label_list='cat_12/labels.txt',
transforms=train_transforms,
shuffle=True)
eval_dataset = pdx.datasets.ImageNet(
data_dir='cat_12',
file_list='cat_12/val_list.txt',
label_list='cat_12/labels.txt',
transforms=eval_transforms)
num_classes = len(train_dataset.labels)
model = pdx.cls.MobileNetV3_small_ssld(num_classes=num_classes)
model.train(num_epochs=30,
train_dataset=train_dataset,
train_batch_size=32,
eval_dataset=eval_dataset,
lr_decay_epochs=[4, 6, 8],
save_dir='output/mobilenetv3_small_ssld',
use_vdl=True)
复制代码
- 上面图片的三个注意的点
- 第一执行程序,程序正常运行
- 第二我们可以看到输出了epoch、loss、acc、lr的关键的数据
- 报错了,cv2读取图片出现错误
- 仔细读过发现,yGcJHV8Uuft6grFs7QWnK5CTAZvYzdDO.jpg图片有问题,在train_list.txt或者val_list.txt中去掉
经过仔细的分析之后,我们发现在训练和验证集中有5张图片有问题,在测试集中,有一张图片有问题
- 训练和验证集
- yGcJHV8Uuft6grFs7QWnK5CTAZvYzdDO.jpg
- tO6cKGH8uPEayzmeZJ51Fdr2Tx3fBYSn.jpg
- YfsxcFB9D3LvkdQyiXlqnNZ4STwope2r.jpg
- 5nKsehtjrXCZqbAcSW13gxB8E6z2Luy7.jpg
- 3yMZzWekKmuoGOF60ICQxldhBEc9Ra15.jpg
- 测试集
- Qt29gPjYZwv3B6RJh5yiTWXrVImue1FH.jpg
观察训练过程
第一个epoch
我们能看到的信息是这是30个epoch中的第一轮,训练完,在训练集上的正确率最低是77.24%,最高是98.9%,然后在要验证集上,的正确率是77.24%,当前轮次是最好参数轮次。
第十五个epoch
我们能看到的信息是这是30个epoch中的第15轮,训练完,在训练集上的正确率最低是87.92%,最高是99.26%,然后在要验证集上,的正确率是88.54%,第十二轮次是最好参数轮次。除此之外,我们还能看到我们的学习率变成了lr = 2.5e-05,这个和我们设置的学习率的衰减有关。
第三十个epoch
我们能看到的信息是这是30个epoch中的第30轮,训练完,在训练集上的正确率最低是88.54%,最高是99.07%,然后在要验证集上,的正确率是89.0%,第二十轮次是最好参数轮次。
在测试集进行验证
验证部分的代码如下:
import paddlex as pdx
import os
model = pdx.load_model('output/mobilenetv3_small_ssld/best_model')
cf = open("result.csv","w")
with open("./cat_12/test_list.txt","r") as f:
test_datas = f.readlines()
for t_data in test_datas:
result = model.predict(os.path.join("cat_12",t_data.strip()))
cf.write(t_data.strip().split("/")[1] + "," + str(result[0]["category_id"]) + "\n")
print("预测完成")
复制代码
提交result.csv
将刚才的result.csv从paddle中下载下来,然后上传让官方判定结果,根据提交的结果对自己的构建过程进行修正调整。
一会就能得到测试结果
此次的成绩是85.83%,可以作为一个简单的baseline.
改进方法
修改学习率的衰减方式
我们之前的代码中在第8个epoch的时候我们的lr就变成了2.5e-05,变得太小了,所以后面在进行梯度衰减的时候,几乎不能改变什么,所以进行调整
看下调整后的训练结果
在第12轮的时候,就比上次30轮训练的结果要好,我们看此时的lr是2.5e-04,证明有效果。
最后我们的训练在验证集上的准确率是92.57%,提交下,看下效果