基于PaddleClas实现猫的十二分类
项目背景介绍
飞桨PaddlePaddle大赛:猫的十二种分类问题。
本场比赛要求参赛选手对十二种猫进行分类,属于CV方向经典的图像分类任务。图像分类任务作为其他图像任务的基石,可以让大家更快上手计算机视觉。
结合深度学习框架Pytorch和AI平台Paddle,使用分类模型,对这十二种猫进行分类。从第二次实验课开始,全部实验课用来完成这个比赛。
环境准备
编程平台:根据要求适用飞桨Paddle提供的平台BML Codelab
深度学习框架:paddlepaddle-gpu
与paddleclas
Python版本:3.7.4
介绍paddleclas
飞桨图像识别套件PaddleClas是飞桨为工业界和学术界所准备的一个图像识别和图像分类任务的工具集,助力使用者训练出更好的视觉模型和应用落地。
PaddleClas支持多种前沿图像分类、识别相关算法,发布产业级特色骨干网络PP-HGNet、PP-LCNetv2、 PP-LCNet和SSLD半监督知识蒸馏方案等模型,在此基础上打造PULC超轻量图像分类方案和PP-ShiTu图像识别系统。
关于paddleclas的模型训练可以参考一下以下
数据集准备
直接选用官方提供的数据集:猫脸识别-12种猫分类数据集
/home/aistudio/data/data10954/train_list.txt
/home/aistudio/data/data10954/cat_12_test.zip
/home/aistudio/data/data10954/cat_12_train.zip
解压数据集与复制训练list
!unzip -q data/data10954/cat_12_test.zip -d /home/aistudio/
!unzip -q data/data10954/cat_12_train.zip -d /home/aistudio/
!cp data/data10954/train_list.txt /home/aistudio/
数据预处理
图片格式应当为RGB三通道,提供的数据集有几张需要进行修改,不然使用paddleclas会报错。
import os
from PIL import Image
for img_path in os.listdir('/home/aistudio/cat_12_train'):
src = os.path.join('/home/aistudio/cat_12_train',img_path)
img = Image.open(src)
if img.mode != 'RGB':
img = img.convert('RGB')
# print("train"+src)
img.save(src)
for img_path in os.listdir('/home/aistudio/cat_12_test'):
src = os.path.join('/home/aistudio/cat_12_test',img_path)
img = Image.open(src)
if img.mode != 'RGB':
img = img.convert('RGB')
# print(src)
img.save(src)
划分数据集并生成标签
#划分数据集
import random
def randrow(file_path, rnd_path):
out = open(rnd_path, 'w')
lines=[]
with open(file_path, 'r') as infile:
for line in infile:
lines.append(line)
for i in range(6):
random.shuffle(lines)
for line in lines:
out.write(line)
print('已打乱数据')
rnd_path = 'train_list_rnd.txt'
randrow('train_list.txt', rnd_path) # 打乱数据
# 按比例随机切割数据集
train = open('train.txt','w')
val = open('val.txt','w')
with open('train_list_rnd.txt','r') as f:
lines = f.readlines()
for (lid, line) in enumerate(lines, start=1):
img, label = line.split('\t')
new_data = img + ' ' + label
if lid % 10 == 0:
val.write(new_data)
else:
train.write(new_data)
train.close()
val.close()
os.remove('train_list_rnd.txt')
print('已生成新的数据集合')
# 生成标签
with open('label.txt','w') as f:
for i in range(12):
f.write(str(i) + '\n')
print('已生成标签')
配置yaml文件
打开PaddleClas/ppcls/configs/quick_start/ResNet50_vd.yaml文件
修改epochs
训练迭代次数为80
修改device
设备为gpu
修改class_num
分类数目为12
修改训练与验证类的image_root
与cls_label_path
修改预测的topk
为1和class_id_map_file
模型训练
# 切换目录到PaddleClas下
%cd /home/aistudio/PaddleClas-2.2.1
# 开始训练
!python tools/train.py -c ./ppcls/configs/quick_start/ResNet50_vd.yaml -o Arch.pretrained=True
部分结果如下所示:
[2023/04/13 22:32:23] root INFO: Already save model in ./output/ResNet50_vd/epoch_4
[2023/04/13 22:32:23] root INFO: Already save model in ./output/ResNet50_vd/latest
[2023/04/13 22:32:24] root INFO: [Train][Epoch 5/80][Iter: 0/61]lr: 0.01004, CELoss: 0.77114, loss: 0.77114, top1: 0.65625, top5: 1.00000, batch_cost: 0.13495s, reader_cost: 0.04580, ips: 237.12732 images/sec, eta: 0:10:25
[2023/04/13 22:32:25] root INFO: [Train][Epoch 5/80][Iter: 10/61]lr: 0.01045, CELoss: 0.78542, loss: 0.78542, top1: 0.74716, top5: 0.96875, batch_cost: 0.08887s, reader_cost: 0.00022, ips: 360.08646 images/sec, eta: 0:06:51
[2023/04/13 22:32:26] root INFO: [Train][Epoch 5/80][Iter: 20/61]lr: 0.01086, CELoss: 0.79159, loss: 0.79159, top1: 0.75000, top5: 0.96577, batch_cost: 0.08849s, reader_cost: 0.00014, ips: 361.61824 images/sec, eta: 0:06:48
[2023/04/13 22:32:27] root INFO: [Train][Epoch 5/80][Iter: 30/61]lr: 0.01127, CELoss: 0.86264, loss: 0.86264, top1: 0.73690, top5: 0.96169, batch_cost: 0.08836s, reader_cost: 0.00018, ips: 362.14592 images/sec,
....
模型预测
打开PaddleClas/ppcls/engine/engine.py文件 并在infer下加入一行代码 logger.info(result)
#预测
!python3 tools/infer.py -c ./ppcls/configs/quick_start/ResNet50_vd.yaml -o Global.pretrained_model=./output/ResNet50_vd/latest -o Infer.infer_imgs=../cat_12_test/
保存结果
手动删除多余内容,保存有用数据
!cp output/ResNet50_vd/infer.log ../infer.txt
处理保存的结果
%cd /home/aistudio/
import json
import os
result = {}
summary_scores=[]
f = open("infer.txt","r")
lines = f.readlines() #读取全部内容 ,并以列表方式返回
count = 0
for line in lines:
# 先把前面的时间都干掉,然后将单引号换成双引号,就变成了json格式的文本了
#print(line)
txt = line.split(" root INFO: ")[1]
# print(txt)
jsontxt = txt.replace("\'","\"")
# print(jsontxt)
list_txt = json.loads(jsontxt)
# print(list_txt)
for i in range(len(list_txt)):
print(list_txt[i])
name, ids,score = list_txt[i]['file_name'],list_txt[i]['class_ids'],list_txt[i]['scores']
onefilepath = name.split("/")[2]
summary_scores.append(score)
# print(onefilepath)
result[onefilepath] = ids[0]
count += 1
cvs=[]
for k in result.keys() :
csv=k , result[k]
res_data=[]
res_data.append(csv[0])
res_data.append(csv[1])
cvs.append(res_data)
#print(len(cvs))
#print(cvs)
with open('result.csv','w') as f_result:
for i in range(len(cvs)):
f_result.write(cvs[i][0] + ',' + str(cvs[i][1]) + '\n')
部分结果如下所示
/home/aistudio
{'class_ids': [9], 'scores': [0.9876], 'file_name': '../cat_12_test/06yUTYIeaRsE782Ou5dh1NPzm9XpkBoL.jpg', 'label_names': ['']}
{'class_ids': [0], 'scores': [1.0], 'file_name': '../cat_12_test/0inVXMEgaBO4Fcrhdj9bkLvHzN71yTuI.jpg', 'label_names': ['']}
{'class_ids': [4], 'scores': [1.0], 'file_name': '../cat_12_test/0l8jL4ROZqzBYXeGH3fFyxPCJEs2togc.jpg', 'label_names': ['']}
{'class_ids': [10], 'scores': [0.99931], 'file_name': '../cat_12_test/0vqnOQ8N7JfRxYLuHWG5BKiwb3ltMkg1.jpg', 'label_names': ['']}
{'class_ids': [11], 'scores': [1.0], 'file_name': '../cat_12_test/1nvK0pif9zLc74MCeYrOyqx6ZVQ3EGNH.jpg', 'label_names': ['']}
{'class_ids': [3], 'scores': [1.0], 'file_name': '../cat_12_test/1oCwQeU3KzI2bESWZVDvacAxHhg4O0p5.jpg', 'label_names': ['']}
{'class_ids': [9], 'scores': [1.0], 'file_name': '../cat_12_test/1pMk2hNyv4WXfEVlOxd0I7wbUL6ur9cP.jpg', 'label_names': ['']}
{'class_ids': [2], 'scores': [0.98152], 'file_name': '../cat_12_test/1ry0uScsWatxqJ8zAnkVD9j3QRUiZC7h.jpg', 'label_names': ['']}
{'class_ids': [1], 'scores': [0.86432], 'file_name': '../cat_12_test/2Gz5sW0vnPYapF1btMZK6qUQJcA8xyIB.jpg', 'label_names': ['']}
{'class_ids': [5], 'scores': [0.90268], 'file_name': '../cat_12_test/2JpNeS5GmtdOV3B9I8TZRAxUEvPc7i1w.jpg', 'label_names': ['']}
{'class_ids': [7], 'scores': [0.99997], 'file_name': '../cat_12_test/2NbvoGleSIPmdiXLjVwgM40CBZWr7qU9.jpg', 'label_names': ['']}
{'class_ids': [4], 'scores': [0.99991], 'file_name': '../cat_12_test/3ZlItXUDgHEJLPr0bSAzisp8YfvxuGBW.jpg', 'label_names': ['']}
求平均分数
import numpy as np
average_score = np.mean(summary_scores)
print(average_score)
结语
因为作者没有特别多的神经网络和深度学习的内容,只能做调包侠了。
如果对用pytroch建立restnet50网络实现分类感兴趣的话,可以看看这位同学的笔记
CJH’s blog - CJH’s blog (cjh0220.github.io)