本程序采用百度 paddlepaddle 深度学习框架,并在百度 AI Studio 平台上运行

目录

1 实验内容

2 原始模型 CNN

2.1 原始 CNN 网络结构

2.2 原始 CNN 的定义

2.3 原始 CNN 模型的测试结果

3 VGG 模型

3.1 VGG 的介绍

3.2 VGG 的网络结构

3.3 VGG-16 网络的定义

3.4 数据增强

3.5 训练曲线与测试结果

3.6模型评价

4 总结

5 完整源程序


1 实验内容

本次实验采用简单的 CNN 模型与 VGG 模型对海洋生物进行识别,下面是数据集的介绍

2 原始模型 CNN

2.1 原始 CNN 网络结构

2.2 原始 CNN 的定义

下面是对 CNN 模型的定义代码

#定义CNN网络
import paddle
import paddle.nn.functional as Fclass CNN(paddle.nn.Layer):def __init__(self):super(CNN,self).__init__()self.conv1 = Conv2D(in_channels=3, out_channels=20, kernel_size=5,stride=1)        self.pool1 = MaxPool2D(kernel_size=2, stride=2)self.conv2 = Conv2D(in_channels=20, out_channels=50, kernel_size=5,stride=1)self.pool2 = MaxPool2D(kernel_size=2, stride=2)self.conv3 = Conv2D(in_channels=50, out_channels=50, kernel_size=5,stride=1)self.pool3 = MaxPool2D(kernel_size=2, stride=2)self.linear1 = Linear(in_features=200, out_features=23)def forward(self, input):x = self.conv1(input)x = F.relu(x)x = self.pool1(x)x = self.conv2(x)x = F.relu(x)x = self.pool2(x)x = self.conv3(x)x = F.relu(x)x = self.pool3(x)x = paddle.flatten(x, start_axis=1,stop_axis=-1)  x = self.linear1(x)x=F.softmax(x)return x

2.3 原始 CNN 模型的测试结果

经过简单的调参,下面是性能较好的超参数设置

学习率 损失函数 优化函数 batch_size epoch_num
0.001 cross-entropy Adam 128 9

下面是训练过程

在设置时可以将 epoch 适当变大,观察训练曲线或准确率离散值变化,可以在准确率变化不大时中断训练,既可以节省时间,又可以防止产生过拟合。最终的测试结果如下

最终在测试集上的准确率达到了91.55%,可见模型出现了轻微的过拟合,于是调整 epoch=9,无论在之后进行怎样的调参,准确率均变化不大,因此说明此模型的表达能力已经到了极限,需要调整网络结构,于是我采用 VGG 模型进行测试。

3 VGG 模型

3.1 VGG 的介绍

Oxford Visual Geometry Group 就是 VGG 模型的缩写,VGG模型是2014年ILSVRC竞赛的第二名。但是VGG模型在多个迁移学习任务中的表现要优于googLeNet。而且从图像中提取CNN特征,VGG模型是首选算法。但它的缺陷在于参数过多,网络结构很臃肿,计算量大,训练费时。

3.2 VGG 的网络结构

3.3 VGG-16 网络的定义

下面是代码

class ConvPool(paddle.nn.Layer):'''卷积+池化'''def __init__(self,in_channels,out_channels,filter_size,pool_size,pool_stride,groups,conv_stride=1,conv_padding=1,pool_type='max'):super(ConvPool, self).__init__()  self._conv2d_list = []for i in range(groups):conv2d = self.add_sublayer(   #返回一个由所有子层组成的列表。'bb_%d' % i,paddle.nn.Conv2D(in_channels=in_channels,out_channels=out_channels,kernel_size=filter_size,padding=conv_padding))in_channels = out_channelsself._conv2d_list.append(conv2d)if pool_type == 'avg':self._pool2d = paddle.nn.AvgPool2D(kernel_size=pool_size,           #池化核大小stride=pool_stride        #池化步长)elif pool_type == 'max':self._pool2d = paddle.nn.MaxPool2D(kernel_size=pool_size,           #池化核大小stride=pool_stride        #池化步长)def forward(self, inputs):x = inputsfor conv in self._conv2d_list:x = conv(x)x = F.relu(x)x = self._pool2d(x)return xclass VGGNet(paddle.nn.Layer):'''VGG网络'''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,23)def forward(self, inputs):# print('input shape is {}'.format(inputs.shape)) #[8, 3, 224, 224]"""前向计算"""out = self.convpool01(inputs)# print('after convpool01')# print(out.shape)           #[8, 64, 112, 112]out = self.convpool02(out)# print(out.shape)           #[8, 128, 56, 56]out = self.convpool03(out)# print(out.shape)           #[8, 256, 28, 28]out = self.convpool04(out)# print(out.shape)           #[8, 512, 14, 14]out = self.convpool05(out)# print(out.shape)           #[8, 512, 7, 7]         out = paddle.reshape(out, shape=[-1, 512*7*7])out = self.fc01(out)out = F.relu(out)out = self.fc02(out)out = F.relu(out)out = self.fc03(out)out = F.softmax(out)return out

3.4 数据增强

通过随机裁剪大小,变换方向,使得模型能够学到关于图像的更本质的特征,减少过拟合。代码如下

if mode == 'train':self.transforms = T.Compose([T.Resize((224,224)),    # 随机裁剪大小T.RandomHorizontalFlip(0.5),        # 随机水平翻转T.ToTensor(),                       # 数据的格式转换和标准化、 HWC => CHW T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 图像归一化])else:self.transforms = T.Compose([T.Resize((224,224)),                 # 图像大小修改T.ToTensor(),                  # 数据的格式转换和标准化 HWC => CHWT.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])   # 图像归一化])

3.5 训练曲线与测试结果

最终测试集的准确率达到了97.15%,可见 VGG 模型泛化能力之强。

3.6模型评价

VGG 的优点:

(1)VGG采用了同样大小的卷积核(3*3)与池化尺寸(2*2),结构十分简洁

(2)VGG采用了理论上可以的最小卷积核,至少 3*3 的尺寸才能保证能够对周围一圈的环境进行感知,采用了最小的卷积核就能够减少增加网络层数,深层的神经网络性能更好

(3)VGG 所有卷积核的步长设为1,避免了信息丢失,通过 padding=1(填充1)能够使输入输出的特征图保持尺寸一致

(4)两个3*3的卷积核的感受野与一个5*5的卷积核的感受野一样,相同的感受野但是网络更深同时参数量更少,于是性能上由于Alexnet 模型

VGG的缺点:

(1)VGG 由于全连接层神经元多,因此参数量大,计算量大,训练耗时

(2)由于参数多,占用内存大

4 总结

首先我采用了较原始的 CNN 模型,由于对海洋生物的识别对人来说有点困难,也就意味着神经网络的结构也必须更复杂,网络结构的复杂度必须与图像识别任务的难度相匹配才能取得较好的效果,因此,采用VGG 模型比较合理,最后通过简单的调参获得了较高的准确率,但是复杂的网络模型又需要丰富、复杂 、庞大的数据集去支撑,于是数据增强显得非常重要。

5 完整源程序

完整 VGG-16 海洋生物识别的源程序如下,参数自行调整,数据集自行获取,路径自行修改

#导入必要的包
import zipfile
import os
import random
import paddle
import paddle.nn.functional as F
import matplotlib.pyplot as plt
from paddle.nn import MaxPool2D,Conv2D,BatchNorm
from paddle.nn import Linear
import sys
import numpy as np
from PIL import Image
from PIL import ImageEnhance
import paddle
from multiprocessing import cpu_count
import matplotlib.pyplot as plt
import json #解压原始数据集,将fish_image.zip解压至data目录下
src_path="/home/aistudio/data/data14492/fish_image23.zip"
target_path="/home/aistudio/data/fish_image"
if(not os.path.isdir(target_path)):z = zipfile.ZipFile(src_path, 'r')z.extractall(path=target_path)z.close()#存放所有类别的信息
class_detail = []
#获取所有类别保存的文件夹名称
class_dirs = os.listdir(target_path+"/fish_image")data_list_path="/home/aistudio/data/"TRAIN_LIST_PATH=data_list_path + "train.txt"
EVAL_LIST_PATH=data_list_path + "eval.txt"#每次执行代码,首先清空train.txt和eval.txt
with open(TRAIN_LIST_PATH, 'w') as f: pass
with open(EVAL_LIST_PATH, 'w') as f: pass#总的图像数量
all_class_images = 0
#存放类别标签
class_label=0
# 设置要生成文件的路径
data_root_path="/home/aistudio/data/fish_image/fish_image"
#存储要写进test.txt和train.txt中的内容
trainer_list=[]
eval_list=[]
#读取每个类别,['fish_01', 'fish_02', 'fish_03']
for class_dir in class_dirs:   #每个类别的信息class_detail_list = {}eval_sum = 0trainer_sum = 0#统计每个类别有多少张图片class_sum = 0#获取类别路径 path = data_root_path + "/" + class_dir# 获取所有图片img_paths = os.listdir(path)for img_path in img_paths:                                  # 遍历文件夹下的每个图片name_path = path + '/' + img_path                       # 每张图片的路径if class_sum % 10 == 0:                                 # 每10张图片取一个做验证数据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                                   #所有类图片的数目class_label += 1  # 说明的json文件的class_detail数据class_detail_list['class_name'] = class_dir             #类别名称,如jiangwenclass_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)         random.shuffle(eval_list)
with open(data_list_path + "eval.txt", 'a') as f:for eval_image in eval_list:f.write(eval_image) random.shuffle(trainer_list)
with open(data_list_path + "train.txt", 'a') as f2:for train_image in trainer_list:f2.write(train_image) # 说明的json文件信息
readjson = {}
readjson['all_class_name'] = data_root_path                  #文件父目录
readjson['all_class_sum'] = class_sum
readjson['all_class_images'] = all_class_images
readjson['class_detail'] = class_detail
jsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))
with open(data_list_path + "readme.json",'w') as f:f.write(jsons)
print ('生成数据列表完成!')import paddle
import paddle.vision.transforms as T
import numpy as np
from PIL import Imageclass FishDataset(paddle.io.Dataset):"""23种鱼数据集类的定义"""def __init__(self, mode='train'):"""初始化函数"""assert mode in ['train', 'eval'], 'mode is one of train, eval.'self.data = []with open('data/{}.txt'.format(mode)) as f:for line in f.readlines():info = line.strip().split('\t')if len(info) > 0:self.data.append([info[0].strip(), info[1].strip()])if mode == 'train':self.transforms = T.Compose([T.Resize((224,224)),    # 随机裁剪大小T.RandomHorizontalFlip(0.5),        # 随机水平翻转T.ToTensor(),                       # 数据的格式转换和标准化、 HWC => CHW T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 图像归一化])else:self.transforms = T.Compose([T.Resize((224,224)),                 # 图像大小修改T.ToTensor(),                  # 数据的格式转换和标准化 HWC => CHWT.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])   # 图像归一化])def __getitem__(self, index):"""根据索引获取单个样本"""image_file, label = self.data[index]image = Image.open(image_file)if image.mode != 'RGB':image = image.convert('RGB')image = self.transforms(image)return image, np.array(label, dtype='int64')def __len__(self):"""获取样本总数"""return len(self.data)train_dataset=FishDataset(mode='train')
eval_dataset=FishDataset(mode='eval')class ConvPool(paddle.nn.Layer):'''卷积+池化'''def __init__(self,in_channels,out_channels,filter_size,pool_size,pool_stride,groups,conv_stride=1,conv_padding=1,pool_type='max'):super(ConvPool, self).__init__()  self._conv2d_list = []for i in range(groups):conv2d = self.add_sublayer(   #返回一个由所有子层组成的列表。'bb_%d' % i,paddle.nn.Conv2D(in_channels=in_channels,out_channels=out_channels,kernel_size=filter_size,padding=conv_padding))in_channels = out_channelsself._conv2d_list.append(conv2d)if pool_type == 'avg':self._pool2d = paddle.nn.AvgPool2D(kernel_size=pool_size,           #池化核大小stride=pool_stride        #池化步长)elif pool_type == 'max':self._pool2d = paddle.nn.MaxPool2D(kernel_size=pool_size,           #池化核大小stride=pool_stride        #池化步长)def forward(self, inputs):x = inputsfor conv in self._conv2d_list:x = conv(x)x = F.relu(x)x = self._pool2d(x)return xclass VGGNet(paddle.nn.Layer):'''VGG网络'''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,23)def forward(self, inputs):# print('input shape is {}'.format(inputs.shape)) #[8, 3, 224, 224]"""前向计算"""out = self.convpool01(inputs)# print('after convpool01')# print(out.shape)           #[8, 64, 112, 112]out = self.convpool02(out)# print(out.shape)           #[8, 128, 56, 56]out = self.convpool03(out)# print(out.shape)           #[8, 256, 28, 28]out = self.convpool04(out)# print(out.shape)           #[8, 512, 14, 14]out = self.convpool05(out)# print(out.shape)           #[8, 512, 7, 7]         out = paddle.reshape(out, shape=[-1, 512*7*7])out = self.fc01(out)out = F.relu(out)out = self.fc02(out)out = F.relu(out)out = self.fc03(out)out = F.softmax(out)return outimport paddle
from paddle import Modelmodel= Model(VGGNet())# 配置模型
model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()), paddle.nn.CrossEntropyLoss(), paddle.metric.Accuracy())model.evaluate(eval_dataset, batch_size=64,verbose=1)# 进行预测操作
predict_result = model.predict(eval_dataset)
import pandas as pd
data=pd.read_csv('./data/eval.txt',header=None,sep='\t')
# 定义画图方法
from PIL import Imagedef show_img(img, predict):plt.figure()plt.title(predict)plt.imshow(img, cmap=plt.cm.binary)plt.show()# 抽样展示
for i in range(10):img_path=data[0][i]real_class=data[1][i]predict_class= np.argmax(predict_result[0][i])img=Image.open(img_path)title=str(i) +'   '+ 'real_class: ' +str(real_class)+'  '+ 'predict_class: ' + str(predict_class)show_img(img, title)
model.save('inference_model', training=False)  # save for inference

深度学习(VGG模型)相关推荐

  1. 干货丨深度学习VGG模型核心拆解

    如今深度学习发展火热,但很多优秀的文章都是基于经典文章,经典文章中的一句一词都值得推敲和分析.此外,深度学习虽然一直被人诟病缺乏足够令人信服的理论,但不代表我们不能感性分析理解,下面我们将对2014年 ...

  2. 深度学习VGG模型核心拆解

    如今深度学习发展火热,但很多优秀的文章都是基于经典文章,经典文章中的一句一词都值得推敲和分析.此外,深度学习虽然一直被人诟病缺乏足够令人信服的理论,但不代表我们不能感性分析理解,下面我们将对2014年 ...

  3. 【深度学习】深度学习中模型计算量(FLOPs)和参数量(Params)等的理解以及四种在python应用的计算方法总结

    接下来要分别概述以下内容: 1 首先什么是参数量,什么是计算量 2 如何计算 参数量,如何统计 计算量 3 换算参数量,把他换算成我们常用的单位,比如:mb 4 对于各个经典网络,论述他们是计算量大还 ...

  4. 深度学习实战——模型推理优化(模型压缩与加速)

    忆如完整项目/代码详见github:https://github.com/yiru1225(转载标明出处 勿白嫖 star for projects thanks) 目录 系列文章目录 一.实验思路综 ...

  5. NVIDIA GPUs上深度学习推荐模型的优化

    NVIDIA GPUs上深度学习推荐模型的优化 Optimizing the Deep Learning Recommendation Model on NVIDIA GPUs 推荐系统帮助人在成倍增 ...

  6. 谷歌、阿里们的杀手锏:三大领域,十大深度学习CTR模型演化图谱

    作者 | 王喆 来源 | 转载自知乎专栏王喆的机器学习笔记 今天我们一起回顾一下近3年来的所有主流深度学习CTR模型,也是我工作之余的知识总结,希望能帮大家梳理推荐系统.计算广告领域在深度学习方面的前 ...

  7. 谷歌、阿里们的杀手锏:3大领域,10大深度学习CTR模型演化图谱(附论文)

    来源:知乎 作者:王喆 本文约4000字,建议阅读8分钟. 本文为你介绍近3年来的所有主流深度学习CTR模型. 今天我们一起回顾一下近3年来的所有主流深度学习CTR模型,也是我工作之余的知识总结,希望 ...

  8. 【深度学习】模型训练过程可视化思路(可视化工具TensorBoard)

    [深度学习]模型训练过程可视化思路(可视化工具TensorBoard) 文章目录 1 TensorBoard的工作原理 2 TensorFlow中生成log文件 3 启动TensorBoard,读取l ...

  9. DL之模型调参:深度学习算法模型优化参数之对LSTM算法进行超参数调优

    DL之模型调参:深度学习算法模型优化参数之对LSTM算法进行超参数调优 目录 基于keras对LSTM算法进行超参数调优 1.可视化LSTM模型的loss和acc曲线

  10. DL之模型调参:深度学习算法模型优化参数之对深度学习模型的超参数采用网格搜索进行模型调优(建议收藏)

    DL之模型调参:深度学习算法模型优化参数之对深度学习模型的超参数采用网格搜索进行模型调优(建议收藏) 目录 神经网络的参数调优 1.神经网络的通病-各种参数随机性 2.评估模型学习能力

最新文章

  1. 当AI黑科技撞上大数据日:清华大学第四届大数据日成功举办
  2. SQL Server 2005无法输入中文的解决方案
  3. administrator自动登录桌面
  4. 不同串口通信速率超时时间_串口知识详解 串口功能及电路介绍
  5. 量化指标公式源码_通达信指标公式源码线上阴线指标公式
  6. 【CodeForces - 266B 】Queue at the School (模拟)
  7. 计算机师范类算师范教育类吗,师范教育类专业和计算机类专业,两者相比,哪个更适合自考生报读...
  8. axis1 c# 接口 调用_java axis 调用C# webService的例子
  9. ELK日志分析系统部署
  10. php usort的用法,PHP usort()用法及代码示例
  11. iOS解决融云的 attempt to delete row 0 from section 0 which only contains 0 rows before the update 问题
  12. 关于QQ表情数据库的复制
  13. 使用计算机模拟抛硬币实验动画课件,《模拟掷硬币实验》课件.ppt
  14. 中文输入纠错任务整理
  15. lazarus 中文教程_Lazarus中文版下载|Pascal编译器Lazarus下载 v1.6.0中文版(附使用教程)_星星软件园...
  16. Fake Location(安卓)
  17. RuntimeError: Tensor for ‘out‘ is on CPU, Tensor for argument #1 ‘self‘ is on CPU, but expected them
  18. 计算机技术在我国的发展,计算机技术在我国热处理工业领域的应用和发展_阎承沛.pdf...
  19. seq2seq 解释
  20. 处理器后面的字母含义_科普向,笔记本cpu结尾字母的含义

热门文章

  1. 外贸在谷歌搜索客户,为什么搜索出来的都是同行?
  2. 【持续更新】机器学习特征工程实用技巧大全
  3. PMP有没有必要续证?
  4. (转)美国金融科技监管框架
  5. 如何在Linux上部署web程序
  6. “被裁员后,我领悟到的8个残酷真相”
  7. No converter found for return value of type错误解决以及消息转化器简单分析
  8. 财务管理----记账凭证的输入格式设计与数据库设计
  9. python的idle怎么运行_python中的idle是如何运行的
  10. 【x86架构】x86上的那些不明觉厉的功能