学校自然语言处理的第一次大作业,之前没有过python基础,更不会pytorch,花了些功夫算是勉强完成了作业,用这篇博客记录一下。代码不够好,模型准确率也不够高,算是提供一个小白视角吧~

0.作业描述

实验目的

1.掌握卷积神经网络、循环神经网络等深度学习的各项基本技术。

2.加强对pytorch、tensorflow等深度学习框架的使用能力。

实验要求

任选一个深度学习框架,实现在给定数据集上的基于DNN、CNN、RNN的图片分类模型(给出模型准确率)。

非常重要的一些说明:

本次作业的核心代码参考了这篇博客(十分惭愧,面向CSDN深度学习了)

CNN入门+猫狗大战(Dogs vs. Cats)+PyTorch入门_l1076604169的博客-CSDN博客

在这篇博客中,作者对猫狗大战的数据集,以及CNN的各种知识点做了详细的说明,博主的代码和注释也写得非常漂亮!!!是非常好的CNN的入门资料。

不过,博主只实现了CNN,并且对测试数据集只做了图片显式并没有计算出识别准确率,因此我的作业在此基础上做了以下完善:

1.补充DNN,RNN的实现

2.训练过程绘制损失图像

3.计算测试过程准确率

1.程序概况

代码:自然语言处理第一次作业-DNNRNNCNN实现猫狗分类-深度学习文档类资源-CSDN文库

程序目录

CNN,RNN,DNN三个文件夹中分别存储三个文件:_network.py描述模型结构,_train.py描述模型训练,_test.py描述模型测试,实际上这三份测试代码以及训练代码只有路径不同,但是为了节约调试时间,在这个程序中并没有将三份代码合并起来。

data文件夹中保存了训练图片和测试图片,训练图片共4000张(为了加强模型效果将2000张图片扩充到了4000),测试图片共500张。训练图片与测试图片互斥。

model文件夹中保存了已经训练好的模型

getedata.py用来对图片进行预处理

运行步骤

1.运行_train.py文件训练模型,并将训练好的模型保存在model文件夹中

2.运行_test.py文件测试模型

目前model文件夹中的模型已经训练完成,只需要运行_test.py文件既可以看到模型准确率:CNN:0.704,RNN:0.506,DNN:0.502。

2.数据准备

数据预处理流程图:

在原始的数据集中,图片大小不整齐,因此需要对数据进行缩放和裁剪,统一为相同尺寸,这里取了一个相对平均的尺寸200X200,同时也需要将图片格式转化为pytorch的Tensor格式。

dataTransform = transforms.Compose([transforms.Resize(IMAGE_SIZE),                  # 比例缩放至合适尺寸transforms.CenterCrop((IMAGE_SIZE, IMAGE_SIZE)),# 裁剪合适大小的图像transforms.ToTensor()                           # 转换成Tensor形式

在data文件夹中有train和test两个子文件夹,分别存储训练图片以及测试图片。观察图片可以看到其命名方式是cat.x.jpg,第一个字符串即为图片的便签,因此可以将图片名称以‘.’划分为三段,name[0]为‘cat’时,在标签中存入0,name[0]=‘dog’时,在标签中存入1。需要注意的是,在训练阶段和测试阶段都需要读取到图片标签,前者用于计算训练过程中的损失,后者用于计算测试过程中的精确度。

3.网络搭建

CNN

卷积神经网络适用于处理图片,因此它也是这三个模型中表现最佳的一个。它由若干卷积池化层以及若干全连接层构成。

网络结构

本模型采用两层卷积池化,并叠加三层全连接层

输入层:200X200X3

在数据预处理阶段,我们将图片调整为了200X200的尺寸,由于是彩色图片,有RGB三个通道(每一个通道对应一个feature map)所以输入应该为一个200X200X3的矩阵。

卷积层1:卷积核3X3X3X16,卷积输出200X200X16

在卷积层由卷积核对输入层图像进行卷积操作提取特征。每一个卷积核会生成一个feature map,卷积核的尺寸为(SxSxCxN),C表示卷积核的深度,N表示卷积核的个数。第一层卷积层的尺寸为3X3,深度为3,卷积核的深度必须与输入层的通道数量一致,卷积核数量为16。 经过该卷积层后,会输出16个卷积图像,尺寸大小为200X200。

卷积层不影响图片尺寸,只影响通道数目

最大池化层1:池化核2X2,池化输出100X100X16  

池化层是对图片进行采样,降低图片的分辨率,最常用的池化方法是最大池化max pooling,它会将池化核内最大的数作为输出。第一层池化核的大小为2X2,它将200X200的图片尺寸转化为100X100的尺寸。

池化层不影响通道数目,只影响图片尺寸

卷积层2:卷积核3X3X16X16,卷积输出100X100X16

卷积核大小为3X3,深度为16,一共16个卷积核,经过卷积计算之后输出16个100X100的卷积图像。

最大池化层2:池化核2X2,池化输出50X50X16

经过第二个池化层,图像尺寸进一步缩小,变为50X50,共输出16个特征图像。

全连接层1

第一个全连接层接收最后一个池化层的输出,输入结点数目为50X50X16=40000,输出结点个数为128

全连接层2

输入结点数目为128,输出结点数为64

全连接层3

输入结点数目为64,输出节点数为2(本实验为二分类问题,因此输出结点为2)

激活函数:

在每一个卷积层以及全连接层后都叠加一层ReLu()激活函数

代码:

class Net(nn.Module): def __init__(self):                                super(Net, self).__init__()                    self.conv1 = torch.nn.Conv2d(3, 16, 3, padding=1)   # 第一个卷积层,输入通道数3,输出通道数16,卷积核大小3×3,padding大小1,其他参数默认self.conv2 = torch.nn.Conv2d(16, 16, 3, padding=1)  # 第二个卷积层,输入通道数16,输出通道数16,卷积核大小3×3,padding大小1,其他参数默认self.fc1 = nn.Linear(50*50*16, 128)                 # 第一个全连层,线性连接,输入节点数50×50×16,输出节点数128self.fc2 = nn.Linear(128, 64)                       # 第二个全连层,线性连接,输入节点数128,输出节点数64self.fc3 = nn.Linear(64, 2)                         # 第三个全连层,线性连接,输入节点数64,输出节点数2def forward(self, x):                   # 重写父类forward方法,即前向计算,通过该方法获取网络输入数据后的输出值x = self.conv1(x)                   # 第一次卷积x = F.relu(x)                       # 第一次卷积结果经过ReLU激活函数处理x = F.max_pool2d(x, 2)              # 第一次池化,池化大小2×2,方式Max poolingx = self.conv2(x)                   # 第二次卷积x = F.relu(x)                       # 第二次卷积结果经过ReLU激活函数处理x = F.max_pool2d(x, 2)              # 第二次池化,池化大小2×2,方式Max poolingx = x.view(x.size()[0], -1)         # 由于全连层输入的是一维张量,因此需要对输入的[50×50×16]格式数据排列成[40000×1]形式,-1表示不确定的数x = F.relu(self.fc1(x))             # 第一次全连,ReLU激活x = F.relu(self.fc2(x))             # 第二次全连,ReLU激活y = self.fc3(x)                     # 第三次激活,ReLU激活return y

模型损失

优化记录

将训练集数量从2000(猫1000,狗1000)扩为4000(猫2000,狗2000),准确率从0.6提升到0.7。

DNN

神经网络是基于感知机的扩展,DNN是有很多隐藏层的神经网络。从DNN按不同层的位置划分,DNN内部的神经网络层可以分为三类,输入层,隐藏层和输出层,一般来说第一层是输入层,最后一层是输出层,而中间的层数都是隐藏层。

网络结构

class myNet(nn.Module):def __init__(self):super().__init__()self.layers = nn.Sequential(nn.Linear(200*200*3,512),nn.ReLU(),nn.Linear(512, 128),nn.ReLU(),nn.Linear(128, 2),nn.Softmax(dim=1),)

本实验的DNN模型由3个全连接层组成

全连接层一:输入200X200X3个结点,输出512个结点

全连接层二:输入512个结点,输出128个结点

全连接层三:输入128个结点,输出2个结点

nn.linear()是用来设置网络中的全连接层,第一个参数为输入的特征数目,第二个参数为输出的特征数。

模型损失

优化记录

1.增加一个线性层:

将三层全连接层模型修改为四层以及五层模型,得到准确率都在0.5左右,没有明显提升。

2.增加epoch

将epoch次数从10改为20,准确率无提升。

3.扩充训练数据集

将训练集数量从2000(猫1000,狗1000)扩为4000(猫2000,狗2000),但是准确率没有提升。

RNN

本实验采用LSTM模型。LSTM是一种特殊的RNN,相比于原始的RNN的隐层(hidden state), LSTM增加了一个细胞状态(cell state),可以解决RNN无法处理长距离的依赖的问题,一般用于处理序列数据,LSTM能够在更长的序列中有更好的表现。所以在猫狗分类问题中,该模型并没有很优秀的表现。

网络结构

class Net(nn.Module):def __init__(self):  super(Net, self).__init__()self.rnn = nn.LSTM(  input_size=120000,            # 等于3*200*200hidden_size=64,               # 隐藏层神经元的个数num_layers=1,                 # RNN层数batch_first=True,)self.out = nn.Linear(64, 2)def forward(self, x):x = x.view(len(x), 1, -1)   r_out, (h_n, h_c) = self.rnn(x, None)out = self.out(r_out[:, -1, :])

nn.LSTM()参数描述:

  1. input_size: 输入特征维数,图片尺寸为200X200像素,通道为3,因此输入为200X200X3
  2. hidden_size: 隐藏层状态的维数,即隐藏层节点的个数,这个维数值是自定义的,和输入的维度没有关系。如果要修改hidden_size则需要同时全连接层的输入,两者应该保持一致。
  3. num_layers: LSTM 堆叠的层数,默认值是1层,如果设置为2,第二个LSTM接收第一个LSTM的计算结果。
  4. bias: 默认为true,带bias(偏置值)。
  5. 5. batch_first: 设置为true,由于输入数据是二维数据,应该将batch_first 设置为True;
  6. bidirectional:是否是双向RNN,默认为:false,若为 true,则:num_directions=2,否则为1。

模型损失

优化记录

  1. 将训练集数量从2000(猫1000,狗1000)扩为4000(猫2000,狗2000) 得到的准确率仍为0.5左右
  2. 将隐藏层神经元的个数从64升为100,此时线性层的输入也要进行相应的更改,下图为得到的新的损失图像,但是准确率没有提升

4.训练网络

模型训练流程:

首先需要将训练数据集中的图片一张一张加载到模型中,得到模型的预测结果,将预测结果与图片标签传入 CrossEntropyLoss()计算损失,也就是网络输出值和实际label的差异,差异越小说明网络拟合效果越好。误差经过backward() 函数进行反向传播,采用求导的方式,计算网络中每个节点参数的梯度,梯度越大说明参数设置不合理,需要调整。接下来采用adam方法对网络中的各个参数进行调整,最后通过zero_grad()清除优化器中的梯度以便下一次计算,因为优化器默认会保留,不清除的话,每次计算梯度都会累加。

相关参数说明:

workers=8:设置pytorch并行读取数据的线程数量为8,这是有本机电脑配置决定的

batch_size = 16:设置一批次处理的图像数量为16

lr = 0.0001:设置学习率为0.0001,它会作为Adam()函数中对参数进行优化。

nepoch = 10:综合考虑训练数据集的数量以及训练时间,将nepoch设置为10,代表所有的数据要经过模型处理10次

相关函数说明:

backward():自动求导函数。在猫狗分类问题中,模型的输出是一个标量,此时backward函数不需要输入任何参数。

adam():这种优化算法结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点,对内存需求较小,为不同的参数计算不同的自适应学习率。

CrossEntropyLoss():指交叉熵损失函数, 该损失函数结合了nn.LogSoftmax()和nn.NLLLoss()两个函数。

5.测试网络

模型测试流程:

首先将测试数据集中图片一张一张送入模型处理,得到一个预测值out,这个预测值需要经过softmax函数处理,得到两个和为1的概率[p猫,p狗],哪一个概率大就将该样本分为哪一类。获取了分类结果之后,将其与图片的标签进行比较,如果匹配,count值加1,最后将模型的准确率定义为acc=count/N,其中N为测试图片的总数500。

准确率结果:

CNN:0.704

RNN:0.506

DNN:0.502

6.思考与学习:

1.pytorch安装及环境配置

PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili

2.epoch, batch, iteration怎么区分?

例如:训练样本10000条,batchsize设置为20,将所有的训练样本在同一个模型中训练5遍,则epoch=5,batchsize=20, iteration=10000/20=500

3.如何理解Tensor张量?

从张量到自动微分:PyTorch入门教程 (qq.com)

标量是零阶张量,向量是一阶张量,矩阵是二阶张量。可以把张量想象成一桶数字张量和多维数组是不同类型的对象。前者是一种函数,后者是适宜在坐标系统中表示张量的一种数据结构态创建的计算图自动计算所有参数上的梯度。总的来说,这一步进行的是梯度下降和反向传播。

4.线性层是越多越好吗?如何确定层数?

参考:如何确定神经网络的层数和隐藏层神经元数量 - 知乎 (zhihu.com)

没有隐藏层:仅能够表示线性可分函数或决策

隐藏层数=1:可以拟合任何“包含从一个有限空间到另一个有限空间的连续映射”的函数

隐藏层数=2:搭配适当的激活函数可以表示任意精度的任意决策边界,并且可以拟合任何精度的任何平滑映射

隐藏层数>2:多出来的隐藏层可以学习复杂的描述(某种自动特征工程)

层数越深,理论上拟合函数的能力增强,效果按理说会更好,但是实际上更深的层数可能会带来过拟合的问题,同时也会增加训练难度,使模型难以收敛。因此一般的经验是,在使用BP神经网络时,可以参照已有的表现优异的模型,如果实在没有,则可以,从一两层开始尝试,尽量不要使用太多的层数。

5.双向RNN的效果会比单向RNN更好吗?

双向RNN时bidirectional设置为true

一般的按序列顺序过来的RNN会记录、保存来自前面序列的信息,这些历史信息对当前的输出是很有帮助的。但是有些问题,序列当前位置历史信息和这个位置未来的信息会共同对计算当前位置的输出有帮助,例如在NLP里面的人名识别里面, 如果我们很确信下一个字符是人名的开始,那么当前位置再是人名的开始的概率就会相当的低。

猫狗分类问题首先并不是序列问题,且未来的信息并不会对当前的预测结果产生任何影响,因此在猫狗分类问题中,不应该设置双向RNN

参考:BiLSTM+CRF (一)双向RNN 浅谈_jmhIcoding-CSDN博客

【一起入门NLP】中科院自然语言处理作业一:RNN,DNN,CNN 进行猫狗分类(pytorch入门)【代码+报告】相关推荐

  1. Hugging Face实战(NLP实战/Transformer实战/预训练模型/分词器/模型微调/模型自动选择/PyTorch版本/代码逐行解析)下篇之模型训练

    模型训练的流程代码是不是特别特别多啊?有的童鞋看过Bert那个源码写的特别特别详细,参数贼多,运行一个模型百八十个参数的. Transformer对NLP的理解是一个大道至简的感觉,Hugging F ...

  2. 使用NeMo快速入门NLP、实现机器翻译任务,英伟达专家实战讲解,内附代码

    对话式AI是当前AI领域最火热的细分领域之一,其中自然语言处理(NLP)是最为困难的问题之一. 那么,零基础.对会话式AI感兴趣的小伙伴们如何快速入门 NLP领域? 近日,英伟达x量子位发起的NLP公 ...

  3. 机器学习-猫狗识别(入门案例)

    案例分析:下载猫狗图片,进行分类.对数据进行分类,训练集和测试集. 训练集和测试集都进行命名规范,把猫标记为1,狗标记为0. 处理流程: 数据处理,把数据处理为64X64大小的格式,参数初始化分被初试 ...

  4. 【一起入门NLP】中科院自然语言处理作业五:BiLSTM+Attention实现SemEval-2010 Task 8上的关系抽取(Pytorch)【代码+报告】

    这里是国科大自然语言处理的第五次作业(终于是最后一次作业了,冲!),本篇博客是记录对论文:Attention-Based Bidirectional Long Short-Term Memory Ne ...

  5. 【一起入门NLP】中科院自然语言处理作业四:RNN+Attention实现Seq2Seq中英文机器翻译(Pytorch)【代码+报告】

    这里是国科大自然语言处理的第四次作业,同样也是从小白的视角解读程序和代码,现在我们开始吧(今天也是花里胡哨的一天呢

  6. 自然语言处理(二)基于CNN的新闻文本分类

    自然语言处理(二) 1.Task1 数据集探索 1.1下载数据集 1.2数据集的描述 1.3 数据的预处理 1.4 CNN卷积神经网络 1.5 训练与验证 2.IMDB 2.1下载 IMDB 数据集 ...

  7. 吴恩达作业1:逻辑回归实现猫的分类

    思路:输入样本X与随机初始权重W相乘,利用sigmoid激活函数输出值,对于二分类问题,用交叉熵损失函数来计算损失值,通过交叉熵损失函数利用链式法则求出W和b的偏导,梯度下降更新W和b即可,(梯度下降 ...

  8. lenet5卷积神经网络_tensorflow图像识别入门实战:使用LeNet5模型实现猫狗分类

    LeNet5介绍 LeNet-5是一种高效的卷积神经网络,在论文<Gradient-Based Learning Applied to Document Recognition>中 有详细 ...

  9. 【新手入门】课程6-卷积神经网络实践-猫狗分类

    图像分类是根据图像的语义信息将不同类别图像区分开来,是计算机视觉中重要的基本问题 猫狗分类属于图像分类中的粗粒度分类问题 实践总体过程和步骤如下图 首先导入必要的包 paddle.fluid---&g ...

  10. TensorFlow(keras)入门课程--06 CNN用于猫狗数据集

    目录 1 简介 在本节中,我们将学习如何使用卷积神经网络,并使用更大的数据集,这有助于避免过度拟合的问题! 2 使用更大的数据集进行训练-猫和狗 在之前的实验中,训练了一个马与人类数据的分类器.尽管在 ...

最新文章

  1. CSS实现鼠标移入图片边框有小三角
  2. 【转载】如何去除C#Strings中的空格?
  3. 处理图片(updated)
  4. MySql的优化步骤
  5. 负载均衡会话保持技术、原理、产品(以F5为例)
  6. WebUtils-网络请求工具类
  7. Linux下JDK和Tomcat安装
  8. 最经典的大数据案例解析(附代码)
  9. 【数字逻辑设计】电路原理图
  10. 通用技术标模板,技术方案书
  11. 七层网络协议详细解释
  12. python中怎么压缩文件_使用Python实现文件压缩和解压
  13. 客户贷款逾期预测[2]-svm和决策树模型
  14. ::-moz-focus-inner
  15. 开关电源-半桥LLC控制
  16. Word图片显示不全解决
  17. 【动画消消乐 】HTML+CSS 吃豆豆动画 073
  18. 启动hadoop组件时报错:(Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password))
  19. Base Filtering Engine (BFE)服务无法启动
  20. 基于java的在线商城项目(1)

热门文章

  1. Python-Locust接口压力测试
  2. 宇宙简史——星光中有什么秘密?
  3. No5.String类的常用方法
  4. 肯德基中国门店将限时发售植物肉汉堡
  5. 评副高考计算机英语能加分吗,19类人员评副高以下职称时不用再考外语
  6. thinkphp 分页样式
  7. Golang 信息采集
  8. Linux与Windows命令行杀死端口命令
  9. python--pandas长宽数据转换
  10. 神棍节移动电商显头角