CNN到VGG

  • 任务描述
  • 一、数据准备
    • (1)解压原始数据集
    • (2)(3)按照比例划分训练集与验证集&乱序,生成数据列表
    • (4)定义数据读取器
  • 二、模型配置
  • 三、模型训练
  • 四、模型评估
  • 五、模型预测

任务描述

如何根据据图像的视觉内容为图像赋予一个语义类别(例如,教室、街道等)是图像场景分类的目标,也是图像检索、图像内容分析和目标识别等问题的基础。但由于图片的尺度、角度、光照等多样性以及场景定义的复杂性,场景分类一直是计算机视觉中的一个挑战性问题。



import os
import zipfile
import random
import json
import paddle
import sys
import numpy as np
from PIL import Image
from PIL import ImageEnhance
import paddle
from paddle import fluid
import matplotlib.pyplot as plt
import paddle.vision.transforms as T
import paddle.nn as nn
import paddle.nn.functional as F
'''
参数配置
'''
train_parameters = {"input_size": [3, 224, 224],                              #输入图片的shape"class_dim": -1,                                          #分类数未知"src_path":"/home/aistudio/data/data55190/Chinese Medicine.zip",    #原始数据集路径"target_path":"/home/aistudio/data/",                     #要解压的路径"train_list_path": "/home/aistudio/data/train.txt",       #train.txt路径"eval_list_path": "/home/aistudio/data/eval.txt",         #eval.txt路径"readme_path": "/home/aistudio/data/readme.json",         #readme.json路径"label_dict":{},                                          #标签字典"num_epochs": 1,                                         #训练轮数"train_batch_size": 8,                                    #训练时每个批次的大小"skip_steps": 10,"save_steps": 30, "learning_strategy": {                                    #优化函数相关的配置"lr": 0.0001                                          #超参数学习率},"checkpoints": "/home/aistudio/work/checkpoints"          #保存的路径}

一、数据准备

(1)解压原始数据集

def unzip_data(src_path,target_path):'''解压原始数据集,将src_path路径下的zip包解压至target_path目录下'''if(not os.path.isdir(target_path + "Chinese Medicine")):     z = zipfile.ZipFile(src_path, 'r')z.extractall(path=target_path)z.close()
'''
参数初始化
'''
src_path=train_parameters['src_path']
target_path=train_parameters['target_path']
train_list_path=train_parameters['train_list_path']
eval_list_path=train_parameters['eval_list_path']'''
解压原始数据到指定路径
'''
unzip_data(src_path,target_path)

(2)(3)按照比例划分训练集与验证集&乱序,生成数据列表

def get_data_list(target_path,train_list_path,eval_list_path):'''生成数据列表'''#存放所有类别的信息class_detail = []#获取所有类别保存的文件夹名称data_list_path=target_path+"Chinese Medicine/"class_dirs = os.listdir(data_list_path)  #总的图像数量all_class_images = 0#存放类别标签class_label=0#存放类别数目class_dim = 0#存储要写进eval.txt和train.txt中的内容trainer_list=[]eval_list=[]#读取每个类别,['river', 'lawn','church','ice','desert']for class_dir in class_dirs:if class_dir != ".DS_Store":class_dim += 1#每个类别的信息class_detail_list = {}eval_sum = 0trainer_sum = 0#统计每个类别有多少张图片class_sum = 0#获取类别路径 path = data_list_path  + class_dir# 获取所有图片img_paths = os.listdir(path)for img_path in img_paths:                                  # 遍历文件夹下的每个图片name_path = path + '/' + img_path                       # 每张图片的路径if class_sum % 8 == 0:                                  # 每8张图片取一个做验证数据eval_sum += 1                                       # test_sum为测试数据的数目eval_list.append(name_path + "\t%d" % class_label + "\n")else:trainer_sum += 1 trainer_list.append(name_path + "\t%d" % class_label + "\n")#trainer_sum测试数据的数目class_sum += 1                                          #每类图片的数目all_class_images += 1                                   #所有类图片的数目# 说明的json文件的class_detail数据class_detail_list['class_name'] = class_dir             #类别名称class_detail_list['class_label'] = class_label          #类别标签class_detail_list['class_eval_images'] = eval_sum       #该类数据的测试集数目class_detail_list['class_trainer_images'] = trainer_sum #该类数据的训练集数目class_detail.append(class_detail_list)  #初始化标签列表train_parameters['label_dict'][str(class_label)] = class_dirclass_label += 1 #初始化分类数train_parameters['class_dim'] = class_dim#乱序  random.shuffle(eval_list)with open(eval_list_path, 'a') as f:for eval_image in eval_list:f.write(eval_image) random.shuffle(trainer_list)with open(train_list_path, 'a') as f2:for train_image in trainer_list:f2.write(train_image) # 说明的json文件信息readjson = {}readjson['all_class_name'] = data_list_path                  #文件父目录readjson['all_class_images'] = all_class_imagesreadjson['class_detail'] = class_detailjsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))with open(train_parameters['readme_path'],'w') as f:f.write(jsons)print ('生成数据列表完成!')
'''
划分训练集与验证集,乱序,生成数据列表
'''
#每次生成数据列表前,首先清空train.txt和eval.txt
with open(train_list_path, 'w') as f: f.seek(0)f.truncate()
with open(eval_list_path, 'w') as f: f.seek(0)f.truncate()
#生成数据列表
get_data_list(target_path,train_list_path,eval_list_path)
#训练数据加载
train_dataset = dataset('/home/aistudio/data',mode='train')
train_loader = paddle.io.DataLoader(train_dataset, batch_size=16, shuffle=True)
#测试数据加载
eval_dataset = dataset('/home/aistudio/data',mode='eval')
eval_loader = paddle.io.DataLoader(eval_dataset, batch_size = 8, shuffle=False)

(4)定义数据读取器

class dataset(Dataset):def __init__(self, data_path, mode='train'):"""数据读取器:param data_path: 数据集所在路径:param mode: train or eval"""super().__init__()self.data_path = data_pathself.img_paths = []self.labels = []if mode == 'train':with open(os.path.join(self.data_path, "train.txt"), "r", encoding="utf-8") as f:self.info = f.readlines()for img_info in self.info:img_path, label = img_info.strip().split('\t')self.img_paths.append(img_path)self.labels.append(int(label))else:with open(os.path.join(self.data_path, "eval.txt"), "r", encoding="utf-8") as f:self.info = f.readlines()for img_info in self.info:img_path, label = img_info.strip().split('\t')self.img_paths.append(img_path)self.labels.append(int(label))def __getitem__(self, index):"""获取一组数据:param index: 文件索引号:return:"""# 第一步打开图像文件并获取label值img_path = self.img_paths[index]img = Image.open(img_path)if img.mode != 'RGB':img = img.convert('RGB') img = img.resize((224, 224), Image.BILINEAR)img = np.array(img).astype('float32')img = img.transpose((2, 0, 1)) / 255label = self.labels[index]label = np.array([label], dtype="int64")return img, labeldef print_sample(self, index: int = 0):print("文件名", self.img_paths[index], "\t标签值", self.labels[index])def __len__(self):return len(self.img_paths)
train_dataset.print_sample(200)
print(train_dataset.__len__())
eval_dataset.print_sample(0)
print(eval_dataset.__len__())
print(eval_dataset.__getitem__(10)[0].shape)
print(eval_dataset.__getitem__(10)[1].shape)

二、模型配置

VGG的核心是五组卷积操作,每两组之间做Max-Pooling空间降维。同一组内采用多次连续的3X3卷积,卷积核的数目由较浅组的64增多到最深组的512,同一组内的卷积核数目是一样的。卷积之后接两层全连 接层,之后是分类层。由于每组内卷积层的不同,有11、13、16、19层这几种模型,上图展示一个16层的网络结构。

class ConvPool(paddle.nn.Layer):'''卷积+池化'''def __init__(self,num_channels,num_filters, filter_size,pool_size,pool_stride,groups,conv_stride=1, conv_padding=1,):super(ConvPool, self).__init__()  for i in range(groups):self.add_sublayer(   #添加子层实例'bb_%d' % i,paddle.nn.Conv2D(         # layerin_channels=num_channels, #通道数out_channels=num_filters,   #卷积核个数kernel_size=filter_size,   #卷积核大小stride=conv_stride,        #步长padding = conv_padding,    #padding))self.add_sublayer('relu%d' % i,paddle.nn.ReLU())num_channels = num_filtersself.add_sublayer('Maxpool',paddle.nn.MaxPool2D(kernel_size=pool_size,           #池化核大小stride=pool_stride               #池化步长))def forward(self, inputs):x = inputsfor prefix, sub_layer in self.named_children():# print(prefix,sub_layer)x = sub_layer(x)return x
class VGGNet(paddle.nn.Layer):def __init__(self):super(VGGNet, self).__init__()       self.convpool01 = ConvPool(3, 64, 3, 2, 2, 2)  #3:通道数,64:卷积核个数,3:卷积核大小,2:池化核大小,2:池化步长,2:连续卷积个数self.convpool02 = ConvPool(64, 128, 3, 2, 2, 2)self.convpool03 = ConvPool(128, 256, 3, 2, 2, 3) self.convpool04 = ConvPool(256, 512, 3, 2, 2, 3)self.convpool05 = ConvPool(512, 512, 3, 2, 2, 3)       self.pool_5_shape = 512 * 7* 7self.fc01 = paddle.nn.Linear(self.pool_5_shape, 4096)self.fc02 = paddle.nn.Linear(4096, 4096)self.fc03 = paddle.nn.Linear(4096, train_parameters['class_dim'])def forward(self, inputs, label=None):# print('input_shape:', inputs.shape) #[8, 3, 224, 224]"""前向计算"""out = self.convpool01(inputs) out = self.convpool02(out) out = self.convpool03(out) out = self.convpool04(out) out = self.convpool05(out)      out = paddle.reshape(out, shape=[-1, 512*7*7])out = self.fc01(out)out = self.fc02(out)out = self.fc03(out)if label is not None:acc = paddle.metric.accuracy(input=out, label=label)return out, accelse:return out

三、模型训练

def draw_process(title,color,iters,data,label):plt.title(title, fontsize=24)plt.xlabel("iter", fontsize=20)plt.ylabel(label, fontsize=20)plt.plot(iters, data,color=color,label=label) plt.legend()plt.grid()plt.show()
print(train_parameters['class_dim'])
print(train_parameters['label_dict'])

5
{‘0’: ‘huaihua’, ‘1’: ‘jinyinhua’, ‘2’: ‘gouqi’, ‘3’: ‘dangshen’, ‘4’: ‘baihe’}

model = VGGNet()
model.train()
cross_entropy = paddle.nn.CrossEntropyLoss()
optimizer = paddle.optimizer.Adam(learning_rate=train_parameters['learning_strategy']['lr'],parameters=model.parameters()) steps = 0
Iters, total_loss, total_acc = [], [], []for epo in range(train_parameters['num_epochs']):for _, data in enumerate(train_loader()):steps += 1x_data = data[0]y_data = data[1]predicts, acc = model(x_data, y_data)loss = cross_entropy(predicts, y_data)loss.backward()optimizer.step()optimizer.clear_grad()if steps % train_parameters["skip_steps"] == 0:Iters.append(steps)total_loss.append(loss.numpy()[0])total_acc.append(acc.numpy()[0])#打印中间过程print('epo: {}, step: {}, loss is: {}, acc is: {}'\.format(epo, steps, loss.numpy(), acc.numpy()))#保存模型参数if steps % train_parameters["save_steps"] == 0:save_path = train_parameters["checkpoints"]+"/"+"save_dir_" + str(steps) + '.pdparams'print('save model to: ' + save_path)paddle.save(model.state_dict(),save_path)
paddle.save(model.state_dict(),train_parameters["checkpoints"]+"/"+"save_dir_final.pdparams")
draw_process("trainning loss","red",Iters,total_loss,"trainning loss")
draw_process("trainning acc","green",Iters,total_acc,"trainning acc")

epo: 0, step: 10, loss is: [1.9345232], acc is: [0.1875]
epo: 0, step: 20, loss is: [1.3878424], acc is: [0.3125]
epo: 0, step: 30, loss is: [1.6113882], acc is: [0.25]
save model to: /home/aistudio/work/checkpoints/save_dir_30.pdparams
epo: 0, step: 40, loss is: [1.69562], acc is: [0.3125]
epo: 0, step: 50, loss is: [1.2417341], acc is: [0.33333334]
不要用基础版,会变得不幸

四、模型评估

'''
模型评估
'''
model__state_dict = paddle.load('work/checkpoints/save_dir_final.pdparams')
model_eval = VGGNet()
model_eval.set_state_dict(model__state_dict)
model_eval.eval()
accs = []for _, data in enumerate(eval_loader()):x_data = data[0]y_data = data[1]predicts = model_eval(x_data)acc = paddle.metric.accuracy(predicts, y_data)accs.append(acc.numpy()[0])
print('模型在验证集上的准确率为:',np.mean(accs))

模型在验证集上的准确率为: 0.6666667

五、模型预测

def unzip_infer_data(src_path,target_path):'''解压预测数据集'''if(not os.path.isdir(target_path + "Chinese Medicine Infer")):     z = zipfile.ZipFile(src_path, 'r')z.extractall(path=target_path)z.close()def load_image(img_path):'''预测图片预处理'''img = Image.open(img_path) if img.mode != 'RGB': img = img.convert('RGB') img = img.resize((224, 224), Image.BILINEAR)img = np.array(img).astype('float32') img = img.transpose((2, 0, 1)) / 255 # HWC to CHW 及归一化return imginfer_src_path = '/home/aistudio/data/data55194/Chinese Medicine Infer.zip'
infer_dst_path = '/home/aistudio/data/'
unzip_infer_data(infer_src_path,infer_dst_path)label_dic = train_parameters['label_dict']
model__state_dict = paddle.load('work/checkpoints/save_dir_final.pdparams')
model_predict = VGGNet()
model_predict.set_state_dict(model__state_dict)
model_predict.eval()
infer_imgs_path = os.listdir(infer_dst_path+"Chinese Medicine Infer")
print(infer_imgs_path)
for infer_img_path in infer_imgs_path:infer_img = load_image(infer_dst_path+"Chinese Medicine Infer/"+infer_img_path)infer_img = infer_img[np.newaxis,:, : ,:]  #reshape(-1,3,224,224)infer_img = paddle.to_tensor(infer_img)result = model_predict(infer_img)lab = np.argmax(result.numpy())print("样本: {},被预测为:{}".format(infer_img_path,label_dic[str(lab)]))

[‘dangshen01.jpg’, ‘gouqi01.jpg’, ‘baihe01.jpg’, ‘jinyinhua01.jpg’, ‘jinyinhua02.jpg’, ‘huaihua01.jpg’, ‘huaihua02.jpg’, ‘dangshen02.jpg’, ‘gouqi02.jpg’, ‘baihe02.jpg’]
样本: dangshen01.jpg,被预测为:baihe
样本: gouqi01.jpg,被预测为:gouqi
样本: baihe01.jpg,被预测为:baihe
样本: jinyinhua01.jpg,被预测为:jinyinhua
样本: jinyinhua02.jpg,被预测为:dangshen
样本: huaihua01.jpg,被预测为:huaihua
样本: huaihua02.jpg,被预测为:huaihua
样本: dangshen02.jpg,被预测为:baihe
样本: gouqi02.jpg,被预测为:gouqi
样本: baihe02.jpg,被预测为:baihe

实践 | 基于VGG-16实现中草药分类相关推荐

  1. 【paddle初体验】基于GoogLeNet实现中草药分类

    零 最近突发奇想打算完整的从零开始做一个完整的深度学习任务,于是从飞桨实践库里随便找了一个简单的VGG网络实现中草药分类的问题. 一.介绍(数据集,paddle,GoogLeNet,流程) 1.数据集 ...

  2. 基于改进AlexNet的植物中草药分类系统(源码&教程)

    1.研究背景 传统的中草药图像识别往往需要人工采集大量的原始样本,再进行人工分析和研究,需要研究者具有相当丰富的中医药知识储备和经验,整个过程耗时耗力且识别率难以得到保证.随着信息技术的飞速发展,人工 ...

  3. 机器学习算法(九): 基于线性判别LDA模型的分类(基于LDA手写数字分类实践)

    机器学习算法(九): 基于线性判别模型的分类 1.前言:LDA算法简介和应用 1.1.算法简介 线性判别模型(LDA)在模式识别领域(比如人脸识别等图形图像识别领域)中有非常广泛的应用.LDA是一种监 ...

  4. 【Computer Vision】基于VGG-16实现中草药分类

    [Computer Vision]基于VGG-16实现中草药分类 活动地址:[CSDN21天学习挑战赛](https://marketing.csdn.net/p/bdabfb52c5d5653213 ...

  5. 【项目实战课】NLP入门第1课,人人免费可学,基于TextCNN的新闻文本分类实战...

    欢迎大家来到我们的项目实战课,本期内容是<基于TextCNN的新闻文本分类实战>. 所谓项目课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实战讲解,可以 ...

  6. 机器学习实践—基于Scikit-Learn、Keras和TensorFlow2第二版—第9章 无监督学习技术(Chapter9_Unsupervised_Learning_Techniques)

    机器学习实践-基于Scikit-Learn.Keras和TensorFlow2第二版-第9章 无监督学习技术(Chapter9_Unsupervised_Learning_Techniques) 虽然 ...

  7. 基于VGG的猫狗识别

    由于猫和狗的数据在这里,所以就做了一下分类的神经网络 1.首先进行图像处理: import csv import glob import os import randomos.environ['TF_ ...

  8. 综述:基于深度学习的文本分类 --《Deep Learning Based Text Classification: A Comprehensive Review》总结(一)

    文章目录 综述:基于深度学习的文本分类 <Deep Learning Based Text Classification: A Comprehensive Review>论文总结(一) 总 ...

  9. 声音识别入门经典模型实践-基于大数据训练CNN14网络实现食物咀嚼声音识别

    声音识别入门经典模型实践-基于大数据训练CNN14网络实现食物咀嚼声音识别 项目简介 声音分类是指可以定制识别出当前音频是哪种声音,或者是什么状态/场景的声音.通过声音,人的大脑会获取到大量的信息,其 ...

  10. 猿创征文|深度学习基于前馈神经网络完成鸢尾花分类

    大家我是猿童学!这次给大家带来的是基于前馈神经网络完成鸢尾花分类! 在本实验中,我们使用的损失函数为交叉熵损失:优化器为随机梯度下降法:评价指标为准确率. 一.小批量梯度下降法 在梯度下降法中,目标函 ...

最新文章

  1. SSD情何以堪!微软:扔掉你的旧PC换台新的
  2. Windows 10版星巴克应用现身官网
  3. Cacti(一)之“better-cacti-templates”
  4. Python 字符串与列表去重
  5. C#实现网页加载后将页面截取成长图片 | Playwright版
  6. 怎么去除idea中代码的波浪线(黄色警告线)
  7. 如何打造高质量的SSP广告引擎(内部干货分享)
  8. IBM Lotus Domino Designer 下载安装记录
  9. 解决黑苹果(bigsur)ALC255声卡声音发虚问题
  10. adobe ae cs6中文版汉化(11.02)win版汉化安装教程
  11. 飞凌ok6410一键烧写linux文件,飞凌OK6410-B Linux学习之一刷机过程
  12. 所属学院mid函数计算机学院,EXCEL答案公式==
  13. 虚幻引擎学习笔记——Month1 Week1
  14. 弘泰俱乐部杨乐、车彦娇团队:凝聚慈善力量,关爱孤困儿童
  15. uvm 糖果爱好者 subscriber调用parent方法解读
  16. 绎维软件F-One获得B轮融资,华创资本领投,齐银基金跟投
  17. pip设置代理 豆瓣源
  18. Jenkins 通过SSH将文件发送到远程服务器
  19. VR全景开发学习链接Three.js
  20. 地方门户运营 最全思路10条

热门文章

  1. 2021年全球软磁铁氧体磁芯收入大约1826.4百万美元,预计2028年达到1965.3百万美元
  2. 泰禾集团收深交所关注函:要求说明债务重组及重大诉讼具体进展等
  3. 让视频丝滑流畅——N/A通用补帧傻瓜解决方案
  4. 多元函数中的泰勒公式的表达
  5. 【pygame】Python 制作 XP 经典扫雷游戏
  6. word空格不能出现下划线的解决办法
  7. 美食杰项目(四)美食详情页
  8. 设置电脑在多久后自动关机
  9. r及rstudio安装ggvegan问题
  10. Android项目:基于Android图书馆借阅系统app毕业设计(计算机毕业设计)