PaddlePaddle2.0利用ResNet101预训练模型实现蝴蝶分类

该项目来自于AI Studio上的公开项目,这里记录我的学习笔记,把一些细节的地方具体说明一下,并且提供完整的程序代码和分步说明,供大家本地PaddlePaddle2.0环境或者AI Studio上面复现。
用到的数据集来自AI Studio中公开的数据集,但是不知道为什么找不到那个数据集项目了,所以就提供我下载好的数据集的网盘链接:
链接:https://pan.baidu.com/s/19Fqsg_rUAQi9nvf3vLhI9w
提取码:qdkx
数据中对蝴蝶种类的描述是这样的,将蝴蝶分为9个属,20个物种,也就是说在本数据集中有的属中包含几个物种的蝴蝶,有的属中就包含单一一种蝴蝶,图片命名例子如下:

一、数据集中图片显示

import matplotlib.pyplot as plt
import PIL.Image as Imagepath='/home/aistudio/data/Butterfly20/001.Atrophaneura_horishanus/006.jpg'
img = Image.open(path)
plt.imshow(img)          #根据数组绘制图像
plt.show()               #显示图像
print(img.size)

二、数据准备

分为两个阶段:
(1)建立训练集中图片和标签之间的对应关系。
(2)确立好对应关系之后对数据进行预处理,即归一化、数据增强等操作。
先看第一部分:
这一部分的功能为:训练集中的图片和species.txt中的标签对应,标签的形式为0-19,共20个数字。

#以下代码用于建立样本数据读取路径与样本标签之间的关系
import os
import randomdata_list = [] #用个列表保存每个样本的读取路径、标签#由于属种名称本身是字符串,而输入模型的是数字。需要构造一个字典,把某个数字代表该属种名称。键是属种名称,值是整数。
label_list=[]
with open("/home/aistudio/data/species.txt") as f:for line in f:a,b = line.strip("\n").split(" ")label_list.append([b, int(a)-1])
label_dic = dict(label_list)#获取Butterfly20目录下的所有子目录名称,保存进一个列表之中
class_list = os.listdir("/home/aistudio/data/Butterfly20")
class_list.remove('.DS_Store') #删掉列表中名为.DS_Store的元素,因为.DS_Store并没有样本。for each in class_list:for f in os.listdir("/home/aistudio/data/Butterfly20/"+each):data_list.append(["/home/aistudio/data/Butterfly20/"+each+'/'+f,label_dic[each]])#按文件顺序读取,可能造成很多属种图片存在序列相关,用random.shuffle方法把样本顺序彻底打乱。
random.shuffle(data_list)#打印前十个,可以看出data_list列表中的每个元素是[样本读取路径, 样本标签]。
print(data_list[0:10])#打印样本数量,一共有1866个样本。
print("样本数量是:{}".format(len(data_list)))


注意经过了标签乱序的操作,所以输出的10条信息并不是连续的,如果不经过乱序标签操作,结果为:

再看第二部分:
这一部分功能为:数据预处理,处理好后设置数据读取器,划分好训练集和测试集。

#以下代码用于构造读取器与数据预处理
#首先需要导入相关的模块
import paddle
from paddle.vision.transforms import Compose, ColorJitter, Resize,Transpose, Normalize
import cv2
import numpy as np
from PIL import Image
from paddle.io import Dataset#自定义的数据预处理函数,输入原始图像,输出处理后的图像,可以借用paddle.vision.transforms的数据处理功能
def preprocess(img):transform = Compose([Resize(size=(224, 224)), #把数据长宽像素调成224*224Normalize(mean=[127.5, 127.5, 127.5], std=[127.5, 127.5, 127.5], data_format='HWC'), #标准化Transpose(), #原始数据形状维度是HWC格式,经过Transpose,转换为CHW格式])img = transform(img).astype("float32")return img#自定义数据读取器
class Reader(Dataset):def __init__(self, data, is_val=False):super().__init__()#在初始化阶段,把数据集划分训练集和测试集。由于在读取前样本已经被打乱顺序,取20%的样本作为测试集,80%的样本作为训练集。self.samples = data[-int(len(data)*0.2):] if is_val else data[:-int(len(data)*0.2)]def __getitem__(self, idx):#处理图像img_path = self.samples[idx][0] #得到某样本的路径img = Image.open(img_path)if img.mode != 'RGB':img = img.convert('RGB')img = preprocess(img) #数据预处理--这里仅包括简单数据预处理,没有用到数据增强#处理标签label = self.samples[idx][1] #得到某样本的标签label = np.array([label], dtype="int64") #把标签数据类型转成int64return img, labeldef __len__(self):#返回每个Epoch中图片数量return len(self.samples)#生成训练数据集实例
train_dataset = Reader(data_list, is_val=False)#生成测试数据集实例
eval_dataset = Reader(data_list, is_val=True)#打印一个训练样本
print(len(train_dataset)) #1866*0.8=1492.8
#print(train_dataset[1136][0])
print(train_dataset[1136][0].shape)
print(train_dataset[1136][1])

三、建立模型

使用预训练模型。为了提升探索速度,建议首先选用比较成熟的基础模型,看看基础模型所能够达到的准确度。之后再试试模型融合,准确度是否有提升。最后可以试试自己独创模型。为简便,这里直接采用101层的残差网络ResNet,并且采用预训练模式。为什么要采用预训练模型呢?因为通常模型参数采用随机初始化,而预训练模型参数初始值是一个比较确定的值。这个参数初始值是经历了大量任务训练而得来的,比如用CIFAR图像识别任务来训练模型,得到的参数。虽然蝴蝶识别任务和CIFAR图像识别任务是不同的,但可能存在某些机器视觉上的共性。用预训练模型可能能够较快地得到比较好的准确度。
**注意:在PaddlePaddle2.0中,使用预训练模型只需要设定模型参数pretained=True。值得注意的是,预训练模型得出的结果类别是1000维度,要用个线性变换,把类别转化为20维度。**因为在我们的蝴蝶分类任务里面,一共有20个类别。

#定义模型
class MyNet(paddle.nn.Layer):def __init__(self):super(MyNet,self).__init__()self.layer=paddle.vision.models.resnet50(pretrained=True)self.fc = paddle.nn.Linear(1000, 20)#网络的前向计算过程def forward(self,x):x=self.layer(x)x=self.fc(x)return x

四、模型训练

训练的时候主要的步骤是:定义输入数据、模型封装、定义优化器、模型准备、开启训练。

#定义输入
input_define = paddle.static.InputSpec(shape=[-1,3,224,224], dtype="float32", name="img")
label_define = paddle.static.InputSpec(shape=[-1,1], dtype="int64", name="label")#实例化网络对象并定义优化器等训练逻辑
model = MyNet()
model = paddle.Model(model,inputs=input_define,labels=label_define) #用Paddle.Model()对模型进行封装
optimizer = paddle.optimizer.Adam(learning_rate=0.0001, parameters=model.parameters())
#上述优化器中的学习率(learning_rate)参数很重要。要是训练过程中得到的准确率呈震荡状态,忽大忽小,可以试试进一步把学习率调低。model.prepare(optimizer=optimizer, #指定优化器loss=paddle.nn.CrossEntropyLoss(), #指定损失函数metrics=paddle.metric.Accuracy()) #指定评估方法model.fit(train_data=train_dataset,     #训练数据集eval_data=eval_dataset,         #测试数据集batch_size=64,                  #一个批次的样本数量epochs=50,                      #迭代轮次save_dir="/home/aistudio/lup", #把模型参数、优化器参数保存至自定义的文件夹save_freq=20,                    #设定每隔多少个epoch保存模型参数及优化器参数log_freq=100                     #打印日志的频率
)

五、模型预测

模型预测主要步骤是:构建数据读取器(因为比赛时候官方提供的测试数据是没有标签的,因此读取数据的时候和训练的时候用到的数据读取器不一致,需要重新定义)、模型封装(这一步骤包含上一步定义好的数据读取器,所以要重新定义模型)、读取训练好的模型参数、模型准备、开始预测。

class InferDataset(Dataset):def __init__(self, img_path=None):"""数据读取Reader(推理):param img_path: 推理单张图片"""super().__init__()if img_path:self.img_paths = [img_path]else:raise Exception("请指定需要预测对应图片路径")def __getitem__(self, index):# 获取图像路径img_path = self.img_paths[index]# 使用Pillow来读取图像数据并转成Numpy格式img = Image.open(img_path)if img.mode != 'RGB': img = img.convert('RGB') img = preprocess(img) #数据预处理--这里仅包括简单数据预处理,没有用到数据增强return imgdef __len__(self):return len(self.img_paths)#实例化推理模型
model = paddle.Model(MyNet(),inputs=input_define)#读取刚刚训练好的参数
model.load('/home/aistudio/lup/final')#准备模型
model.prepare()#得到待预测数据集中每个图像的读取路径
infer_list=[]
with open("/home/aistudio/data/testpath.txt") as file_pred:for line in file_pred:infer_list.append("/home/aistudio/data/"+line.strip())#模型预测结果通常是个数,需要获得其对应的文字标签。这里需要建立一个字典。
def get_label_dict2():label_list2=[]with open("/home/aistudio/data/species.txt") as filess:for line in filess:a,b = line.strip("\n").split(" ")label_list2.append([int(a)-1, b])label_dic2 = dict(label_list2)return label_dic2label_dict2 = get_label_dict2()
#print(label_dict2)#利用训练好的模型进行预测
results=[]
for infer_path in infer_list:infer_data = InferDataset(infer_path)result = model.predict(test_data=infer_data)[0] #关键代码,实现预测功能result = paddle.to_tensor(result)result = np.argmax(result.numpy()) #获得最大值所在的序号results.append("{}".format(label_dict2[result])) #查找该序号所对应的标签名字#把结果保存起来
with open("work/result.txt", "w") as f:for r in results:f.write("{}\n".format(r))

注意:模型预测的时候不需要训练,只是根据训练好的网络提供测试集图片的的标签即可,因此类似于模型准备中,优化器的设置、损失函数定义等与训练有关的操作是不需要的。

六、查看网络结构

使用Paddle高级api查看网络的结构

model = paddle.Model(MyNet())
model.summary((1, 3, 224, 224))

PaddlePaddle2.0利用ResNet101预训练模型实现蝴蝶分类相关推荐

  1. 基于Mindspore2.0的GPT2预训练模型迁移教程

    摘要: 这篇文章主要目的是为了让大家能够清楚如何用MindSpore2.0来进行模型的迁移. 本文分享自华为云社区<MindNLP-基于Mindspore2.0的GPT2预训练模型迁移教程> ...

  2. Pytorch——BERT 预训练模型及文本分类(情感分类)

    BERT 预训练模型及文本分类 介绍 如果你关注自然语言处理技术的发展,那你一定听说过 BERT,它的诞生对自然语言处理领域具有着里程碑式的意义.本次试验将介绍 BERT 的模型结构,以及将其应用于文 ...

  3. MindNLP-基于Mindspore2.0的GPT2预训练模型迁移教程

    前言 动机 大家好,我是Super_WZB,最近MindSpore快要上线2.0版本了,由于之前主要是参与MindSpore的开发工作,一直想找机会多用一用.而自春节开始也是参与到了一项基于MindS ...

  4. 利用vgg预训练模型提取图像特征

    VGG卷积神经网络是牛津大学在2014年提出来的模型.当这个模型被提出时,由于它的简洁性和实用性,马上成为了当时最流行的卷积神经网络模型.它在图像分类和目标检测任务中都表现出非常好的结果.在2014年 ...

  5. BERT 预训练模型及文本分类(情感分类)

    https://www.cnblogs.com/wwj99/p/12283799.html

  6. PaddlePaddle2.0搭建VGG-16模型实现蝴蝶分类

    PaddlePaddle2.0利用VGG-16预训练模型实现蝴蝶分类 本项目是百度AI Studio上图像分类课程的一个内容,之前使用ResNet101网络完成,现在用VGG-16网络实现同样的任务. ...

  7. 大规模知识图谱预训练模型及电商应用

    点击上方蓝字关注我们 大规模知识图谱预训练模型及电商应用 陈华钧1,2, 张文3, 黄志文4, 叶橄强1, 文博1, 张伟2,4 1 浙江大学计算机科学与技术学院,浙江 杭州 310007 2 阿里巴 ...

  8. 预训练模型应用工具 PaddleHub情感分析、对话情绪识别文本相似度

    文章目录 1. 预训练模型的应用背景 1.1 多任务学习与迁移学习 1.2 自监督学习 2. 快速使用PaddleHub 2.1 通过Python代码调用方式 使用PaddleHub 2.1.1 CV ...

  9. PaddlePaddle模型资源之一:预训练模型应用工具 PaddleHub

    文章目录 1. 预训练模型的应用背景 1.1 多任务学习与迁移学习 1.2 自监督学习 2. 快速使用PaddleHub 2.1 通过Python代码调用方式 使用PaddleHub 2.1.1 CV ...

  10. 134个预训练模型、精度高达85.1%,百度视觉算法最强基石PaddleClas全新升级

    机器之心发布 机器之心编辑部 百度 PaddlePaddle 团队开发的 PaddleClas 是一个适用于业界和学界的图像分类任务工具集,可以帮助用户训练更好的计算机视觉模型并应用于真实场景中.近期 ...

最新文章

  1. 中国有神经网络计算机,新神经网络使计算机像人一样推理
  2. ajax提交到mysql_利用ajax的方式来提交数据到后台数据库及交互功能
  3. Package CJK Error: Invalid character code. 问题解决方法--xelatex和pdflatex编译的转换
  4. JavaScript深入理解对象方法——Object.assign()
  5. Mysql的锁机制之表锁
  6. [前端记录] --- vue axios 等调用完再执行后面的语句
  7. centos mysql rpm re_centos7和centos6.5环境rpm方式安装mysql5.7和mysql5.6详解
  8. 【华为云技术分享】华为云MySQL新增MDL锁视图特性,快速定位元数据锁问题
  9. mysql 什么时候用单列索引?什么使用用联合索引?
  10. MYSQL启动后报:ERROR! The server quit without updating PID file错误的问题解决
  11. SpringSecurity应用(二)
  12. python自学行吗-自学Python可以吗?怎样从入门到大师?我写这篇文章告诉你
  13. 难分伯仲,驱动人生驱动精灵巅峰评测?
  14. 工具 | Mac | 截图工具
  15. 【Shawn-LeetCode】Two Sum
  16. 阿弥陀佛么么哒 - 笔记
  17. 【渝粤题库】陕西师范大学210033 劳动法与社会保障法作业
  18. 眼见不为“实”,人们更信任人工智能合成的假脸
  19. 【多项式最小二乘拟合实验】
  20. *PAT_甲级_1072 Gas Station (30point(s)) (C++)【Dijkstra/字符串截取/与数字相互转换】

热门文章

  1. 百度网盘链接在线解析网站_最近很热闹啊,免登陆百度网盘高速链接转换工具...
  2. Matlab关于转置与共轭转置
  3. c语言的异步回调函数,C语言函数的回调函数
  4. 回调函数原理及应用实例
  5. J2EE是技术还是平台还是框架? 什么是J2EE
  6. dstat 命令详解
  7. 赖世雄英语学习三原则
  8. 【2021最新版】Kafka面试题总结(25道题含答案解析)
  9. Java性能调优指南pdf阅读0-100页
  10. 计算机有自带的拼音打字功能吗,搜狗拼音输入法 自带功能提升打字速度的技巧...