使用PyTorch实现CNN

文章目录

  • 使用PyTorch实现CNN
    • 1. 导入所需包:
    • 2. 获取数据集
      • 2.1 获取数据集,并对数据集进行预处理
      • 2.2 获取迭代数据:`data.DataLoader()`
    • 3. 定义网络结构
    • 4. 定义损失和优化器
    • `model.parmaters()`含义:
    • 5. 训练网络
    • 损失图:
      • 如果使用MSELoss:平方差损失
    • 7. 测试网络:精确度:0.98
    • 8. 其他实验:
      • 8.1 全连接第一层增加ReLU激活函数:提高了0.02
      • 8.2 去掉批量归一化:降低了0.01
      • 8.3 使用LeakyReLU激活函数:降低0.01
      • 8.4 使用PReLU激活函数:提升0.01
    • 卷积方法的使用:`torch.nn.Conv2d()`
    • 反卷积方法的使用:`torch.nn.ConvTranspose2d()`

1. 导入所需包:

import torch
from torch.utils import data # 获取迭代数据
from torch.autograd import Variable # 获取变量
import torchvision
from torchvision.datasets import mnist # 获取数据集
import matplotlib.pyplot as plt

2. 获取数据集

2.1 获取数据集,并对数据集进行预处理

(1)对原有数据转成Tensor类型

(2)用平均值和标准偏差归一化张量图像

# 数据集的预处理
data_tf = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize([0.5],[0.5])]
)data_path = r'C:\Users\liev\Desktop\myproject\yin_test\MNIST_DATA_PyTorch'
# 获取数据集
train_data = mnist.MNIST(data_path,train=True,transform=data_tf,download=False)
test_data = mnist.MNIST(data_path,train=False,transform=data_tf,download=False)

第一次下载的输出:

Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Processing...
Done!

注意:

  1. 对数据的预处理还有很多。
  2. 第一次获取数据集时,参数download=True,会下载MNIST数据集所有文件,包括训练集和测试集
  3. 获取MNIST数据集的步骤:
  • 如果本地没有数据集:

    • train_data = mnist.MNIST(data_path,train=True,transform=data_tf,download=True)
      
    • 等待下载,直到下载完成

    • train_data = mnist.MNIST(data_path,train=True,transform=data_tf,download=False)
      test_data = mnist.MNIST(data_path,train=False,transform=data_tf,download=False)
      
    • 获取测试集和训练集

  • 如果本地有数据集

    • train_data = mnist.MNIST(data_path,train=True,transform=data_tf,download=False)
      test_data = mnist.MNIST(data_path,train=False,transform=data_tf,download=False)
      

2.2 获取迭代数据:data.DataLoader()

train_loader = data.DataLoader(train_data,batch_size=128,shuffle=True)
test_loader = data.DataLoader(test_data,batch_size=100,shuffle=True)

注意:

  1. DataLoader返回的是所有的数据,只是分成了每批次为参数batch_size的数据
  2. DataLoader的shuffle参数,True 决定了是否能多次取出batch_size,False,则表明只能取出数据集大小的数据。

3. 定义网络结构

CNN网络结构 输入shape 卷积核 激活函数 输出图像
conv1 [128,1,28,28] [3,3,1,16] ReLU [128, 16, 14, 14]
conv2 [128, 16, 14, 14] [3,3,16,32] ReLU [128, 32, 7, 7]
conv3 [128, 32, 7, 7] [3,3,32,64] ReLU [128, 64, 4, 4]
conv4 [128, 64, 4, 4] [3,3,64,64] ReLU [128, 64, 2, 2]

代码实现:

# 定义网络结构
class CNNnet(torch.nn.Module):def __init__(self):super(CNNnet,self).__init__()self.conv1 = torch.nn.Sequential(torch.nn.Conv2d(in_channels=1,out_channels=16,kernel_size=3,stride=2,padding=1),torch.nn.BatchNorm2d(16),torch.nn.ReLU())self.conv2 = torch.nn.Sequential(torch.nn.Conv2d(16,32,3,2,1),torch.nn.BatchNorm2d(32),torch.nn.ReLU())self.conv3 = torch.nn.Sequential(torch.nn.Conv2d(32,64,3,2,1),torch.nn.BatchNorm2d(64),torch.nn.ReLU())self.conv4 = torch.nn.Sequential(torch.nn.Conv2d(64,64,2,2,0),torch.nn.BatchNorm2d(64),torch.nn.ReLU())self.mlp1 = torch.nn.Linear(2*2*64,100)self.mlp2 = torch.nn.Linear(100,10)def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = self.conv4(x)x = self.mlp1(x.view(x.size(0),-1))x = self.mlp2(x)return x
model = CNNnet()
print(model)

输出:

CNNnet((conv1): Sequential((0): Conv2d(1, 16, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU())(conv2): Sequential((0): Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU())(conv3): Sequential((0): Conv2d(32, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU())(conv4): Sequential((0): Conv2d(64, 64, kernel_size=(2, 2), stride=(2, 2))(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU())(mlp1): Linear(in_features=256, out_features=100, bias=True)(mlp2): Linear(in_features=100, out_features=10, bias=True)
)

4. 定义损失和优化器

(1)使用交叉熵损失

(2)使用Adam优化器

loss_func = torch.nn.CrossEntropyLoss()
opt = torch.optim.Adam(model.parameters(),lr=0.001)
  1. model.parmaters()含义:

  2. 使用损失和优化器的步骤:

    • 获取损失:loss = loss_func(out,batch_y)
    • 清空上一步残余更新参数:opt.zero_grad()
    • 误差反向传播:loss.backward()
    • 将参数更新值施加到netparmeters上:opt.step()

5. 训练网络

loss_count = []
for epoch in range(2):for i,(x,y) in enumerate(train_loader):batch_x = Variable(x) # torch.Size([128, 1, 28, 28])batch_y = Variable(y) # torch.Size([128])# 获取最后输出out = model(batch_x) # torch.Size([128,10])# 获取损失loss = loss_func(out,batch_y)# 使用优化器优化损失opt.zero_grad()  # 清空上一步残余更新参数值loss.backward() # 误差反向传播,计算参数更新值opt.step() # 将参数更新值施加到net的parmeters上if i%20 == 0:loss_count.append(loss)print('{}:\t'.format(i), loss.item())torch.save(model,r'C:\Users\liev\Desktop\myproject\yin_test\log_CNN')if i % 100 == 0:for a,b in test_loader:test_x = Variable(a)test_y = Variable(b)out = model(test_x)# print('test_out:\t',torch.max(out,1)[1])# print('test_y:\t',test_y)accuracy = torch.max(out,1)[1].numpy() == test_y.numpy()print('accuracy:\t',accuracy.mean())break
plt.figure('PyTorch_CNN_Loss')
plt.plot(loss_count,label='Loss')
plt.legend()
plt.show()

输出:

0:    2.313704252243042
accuracy:    0.11
20:  1.1835652589797974
40:  0.5378416776657104
60:  0.41440480947494507
80:  0.18270650506019592
100:     0.18721994757652283
accuracy:    0.92
......
380:     0.032591354101896286
400:     0.024792633950710297
accuracy:    1.0
420:     0.03427279368042946
440:     0.04764523729681969
460:     0.01753203198313713

损失图:

如果使用MSELoss:平方差损失

将真实值转为one-hot形式

def one_hot(data):hot = np.zeros([10])hot[data] = 1return hot
# 并且在计算损失前,加入下面一行代码,将真实值转为one-hot形式
y = [one_hot(i) for i in y]

7. 测试网络:精确度:0.98

注意点:

  1. 获取accuracy时的问题:

    • 获取的预测值shape:【128,10】
    • 真实值shape:【128】,无one-hot编码
    • 转换预测值:使用torch.max() 获取最后输出的每张图片预测值的最大值
# 测试网络
model = torch.load(r'C:\Users\liev\Desktop\myproject\yin_test\log_CNN')
accuracy_sum = []
for i,(test_x,test_y) in enumerate(test_loader):test_x = Variable(test_x)test_y = Variable(test_y)out = model(test_x)# print('test_out:\t',torch.max(out,1)[1])# print('test_y:\t',test_y)accuracy = torch.max(out,1)[1].numpy() == test_y.numpy()accuracy_sum.append(accuracy.mean())print('accuracy:\t',accuracy.mean())print('总准确率:\t',sum(accuracy_sum)/len(accuracy_sum))
# 精确率图
print('总准确率:\t',sum(accuracy_sum)/len(accuracy_sum))
plt.figure('Accuracy')
plt.plot(accuracy_sum,'o',label='accuracy')
plt.title('Pytorch_CNN_Accuracy')
plt.legend()
plt.show()

输出:

accuracy:     0.98
accuracy:    1.0
accuracy:    1.0
accuracy:    1.
总准确率:     0.9850999999999999

8. 其他实验:

8.1 全连接第一层增加ReLU激活函数:提高了0.02

测试输出:

accuracy:     0.98
accuracy:    0.99
accuracy:    0.98
accuracy:    0.99
总准确率:     0.9872999999999992

8.2 去掉批量归一化:降低了0.01

accuracy:     0.97
accuracy:    0.97
accuracy:    0.92
总准确率:     0.9746999999999996

8.3 使用LeakyReLU激活函数:降低0.01

accuracy:     0.97
accuracy:    0.98
accuracy:    1.0
总准确率:     0.9848999999999997

8.4 使用PReLU激活函数:提升0.01

accuracy:     0.97
accuracy:    1.0
accuracy:    1.0
accuracy:    0.97
总准确率:     0.9867999999999998

卷积方法的使用:torch.nn.Conv2d()

在由多个输入平面组成的输入信号上应用2D卷积。

在最简单的情况下,具有输入大小的图层的输出值
(N,Cin,H,W)(N,Cin,H,W)(N,C_{in},H,W)(N,Cin,H,W) (N,Cin​,H,W)(N,Cin,H,W)
和输出
(N,Cout,Hout,Wout)(N,Cout,Hout,Wout)(N,Cout,Hout,Wout)(N,Cout,Hout,Wout) (N,Cout,Hout,Wout)(N,Cout,Hout,Wout)
可以精确地描述为:

out(Ni,Coutj)=bias(Coutj)+∑k=0Cin−1weight(Coutj,k)⋆input(Ni,k)\text{out}(N_i,C_{out_j})=\text{bias}(C_{out_j}) + \sum_{k = 0}^{C_{in}-1}\text{weight}(C_{out_j}, k) \star\text{input}(N_i, k) out(Ni​,Coutj​​)=bias(Coutj​​)+k=0∑Cin​−1​weight(Coutj​​,k)⋆input(Ni​,k)

⋆是有效的2D 互相关运算符, N 是一个批量大小, C 表示多个频道, H 是输入平面的高度,以像素为单位 W 是像素的宽度。

参数说明:

参数 说明
in_channels 输入图像中的通道数:int
out_channels 卷积产生的通道数
kernel_size 卷积内核的大小
stride 卷积的步幅。默认值:1
padding 将零填充添加到输入的两侧。默认值:0
dilation 内核元素之间的间距。默认值:1
groups 从输入通道到输出通道的阻塞连接数。默认值:1
bias 如果True,在输出中增加了可学习的偏差。默认:True

计算输出图片shape:

  • 输入shape格式:

(N,Cin,Hin,Win)(N,C_{in},H_{in},W_{in}) (N,Cin​,Hin​,Win​)

  • 输出shape格式:

(N,Cout,Hout,Wout)(N,C_{out},H_{out},W_{out}) (N,Cout​,Hout​,Wout​)

输出图片shape的计算公式:

Hout=⌊Hin+2×padding[0]−dilation[0]×(kernel_size[0]−1)−1stride[0]+1⌋Wout=⌊Win+2×padding[1]−dilation[1]×(kernel_size[1]−1)−1stride[1]+1⌋H_{out} = \bigg\lfloor\frac{\mathbf{H}_{\mathbf{in}}+2\times \mathbf{padding[0]}-\mathbf{dilation[0]}\times (\mathbf{kernel}\_\mathbf{size[0]}-1)-1 }{\mathbf{stride[0]}}+1 \bigg\rfloor \\ W_{out} = \bigg\lfloor\frac{\mathbf{W}_{\mathbf{in}}+2\times \mathbf{padding[1]}-\mathbf{dilation[1]}\times (\mathbf{kernel}\_\mathbf{size[1]}-1)-1 }{\mathbf{stride[1]}}+1 \bigg\rfloor Hout​=⌊stride[0]Hin​+2×padding[0]−dilation[0]×(kernel_size[0]−1)−1​+1⌋Wout​=⌊stride[1]Win​+2×padding[1]−dilation[1]×(kernel_size[1]−1)−1​+1⌋

变量:

  • weight(Tensor) - 形状模块的可学习权重(out_channels,in_channels,kernel_size [0],kernel_size [1])
  • 偏见(Tensor) - 形状模块的可学习偏差(out_channels)

实例代码:

import torchconv = torch.nn.Conv2d(1,3,2,1,0)print('conv.weight.size():\t',conv.weight.size())
print('conv.bias.size():\t',conv.bias.size())
print('conv初始化的weight数据:\n',conv.weight)
print('conv初始化的bias数据:\n',conv.bias)

输出:

conv.weight.size():   torch.Size([3, 1, 2, 2])
conv.bias.size():    torch.Size([3])
conv初始化的weight数据:Parameter containing:
tensor([[[[ 0.2753, -0.1573],[-0.4197,  0.1795]]],[[[ 0.1529,  0.3869],[ 0.0219, -0.2829]]],[[[ 0.3727, -0.1673],[ 0.4687,  0.3792]]]], requires_grad=True)
conv初始化的bias数据:Parameter containing:
tensor([ 0.2909, -0.0980,  0.0066], requires_grad=True)

反卷积方法的使用:torch.nn.ConvTranspose2d()

在由多个输入平面组成的输入图像上应用2D转置卷积运算符。

该模块可以看作Conv2d相对于其输入的梯度。它也被称为分数跨度卷积或反卷积(尽管它不是实际的去卷积操作)。

参数说明:

参数 说明
in_channels 输入图像中的通道数
out_channels 卷积产生的通道数
kernel_size 卷积内核的大小
stride 卷积的步幅。默认值:1
padding 零填充将添加到输入中每个维度的两侧。默认值:0kernel_size - 1 - padding
output_padding 在输出形状中添加到每个维度的一侧的附加大小。默认值:0
groups 从输入通道到输出通道的阻塞连接数。默认值:1
bias 如果True,在输出中增加了可学习的偏差。默认:True
dilation 内核元素之间的间距。默认值:1

计算输出图片shape:

  • 输入:

(N,Cin,Hin,Win)(N,C_{in},H_{in},W_{in}) (N,Cin​,Hin​,Win​)

  • 输出:

(N,Cout,Hout,Wout)(N,C_{out},H_{out},W_{out}) (N,Cout​,Hout​,Wout​)

输出图片shape的计算公式:
Hout=(Hin−1)×stride[0]−2×padding[0]+kernel_size[0]+output_padding[0]Wout=(Win−1)×stride[1]−2×padding[1]+kernel_size[1]+output_padding[1]\mathbf{H_{out}} = \mathbf{(H_{in}-1)}\times \mathbf{stride[0]} - 2\times \mathbf{padding[0] }+\mathbf{kernel}\_\mathbf{size[0]}+\mathbf{output}\_\mathbf{padding[0]} \\ \mathbf{W_{out}} = \mathbf{(W_{in}-1)}\times \mathbf{stride[1]} - 2\times \mathbf{padding[1] }+\mathbf{kernel}\_\mathbf{size[1]}+\mathbf{output}\_\mathbf{padding[1]} Hout​=(Hin​−1)×stride[0]−2×padding[0]+kernel_size[0]+output_padding[0]Wout​=(Win​−1)×stride[1]−2×padding[1]+kernel_size[1]+output_padding[1]

变量:

  • weight(Tensor) - 形状模块的可学习权重(out_channels,in_channels,kernel_size [0],kernel_size [1])
  • 偏见(Tensor) - 形状模块的可学习偏差(out_channels)

使用PyTorch实现CNN相关推荐

  1. Pytorch和CNN图像分类

    Pytorch和CNN图像分类 PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序.它主要由Facebookd的人工智能小组开发,不仅能够实现强大的GPU加速, ...

  2. Pytorch之CNN:基于Pytorch框架实现经典卷积神经网络的算法(LeNet、AlexNet、VGG、NIN、GoogleNet、ResNet)——从代码认知CNN经典架构

    Pytorch之CNN:基于Pytorch框架实现经典卷积神经网络的算法(LeNet.AlexNet.VGG.NIN.GoogleNet.ResNet)--从代码认知CNN经典架构 目录 CNN经典算 ...

  3. 卷积神经网络、比较MLPS和CNNS、滤波器、CNN各层的作用、在Pytorch可视化CNN

    1.33.卷积神经网络 1.33.1.卷积 和 神经网络 1.33.1.1.比较MLPS和CNNS 1.33.1.2.计算机如何看图像? 1.33.1.3.建立自己的滤波器 1.33.2.完整的卷积神 ...

  4. MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网络训练实现及比较(三)...

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 在前两篇文章MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网 ...

  5. 基于PyTorch搭建CNN实现视频动作分类任务代码详解

    数据及具体讲解来源: 基于PyTorch搭建CNN实现视频动作分类任务 import torch import torch.nn as nn import torchvision.transforms ...

  6. Pytorch中CNN入门思想及实现

    CNN卷积神经网络 基础概念: 以卷积操作为基础的网络结构,每个卷积核可以看成一个特征提取器. 思想: 每次观察数据的一部分,如图,在整个矩阵中只观察黄色部分3×3的矩阵,将这[3×3]矩阵·(点乘) ...

  7. 03.PyTorch与CNN(4-1 机器学习和神经网络的基本概念(1))

    03.PyTorch与CNN(4-1 机器学习和神经网络的基本概念(1)) 一, 4-1 机器学习和神经网络的基本概念(1) 来自慕课网 一, 4-1 机器学习和神经网络的基本概念(1)

  8. 【深度学习基础】SENet——PyTorch实现CNN的SE结构改造

    [深度学习基础][深度学习基础]SENet--PyTorch实现CNN的SE结构改造 1 论文关键信息 1.1 SE block 1.1.1 squeeze 1.1.2 Exitation 2 pyt ...

  9. 使用PyTorch搭建CNN神经网络

    使用pytorch搭建CNN神经网络 卷积运算的基本原理 单层卷积运算 valid convolution same convolution CNN的基本结构 数据输入层 卷积层 池化层 全连接层 数 ...

  10. 基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络

    基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络 所用工具 文件结构: 数据: 代码: 结果: 改进思路 拓展 本文是一个基于pytorch使用CNN在生物信息学上进行位 ...

最新文章

  1. 10 年 bloger 教你如何优雅玩转博客!
  2. 免费素材下载:Box Of Bundles Number 2
  3. Android实现支持缩放平移图片
  4. li连接mysql代码_php连接mysql基本代码-测试代码
  5. riskv的linux模拟环境,开启你RISC-V的开发之旅-RISC-V的linux模拟环境搭建整理和总结-EDA365电子论坛通信数码-人工智能-计算机-半导体-手机家电消费电子硬件门户网站...
  6. 远程下载pdf文件 java代码
  7. 正确的加密存储密码防止被拖库(脱裤)保护用户登录安全
  8. JavaScript将HTML元素导出PDF及World
  9. 大一学生《web课程设计》用DIV+CSS技术设计的个人网页(网页制作课作业)
  10. 抖音APP终极瘦身方案
  11. 笔记............................
  12. 搭建Discuz论坛网站-最新版Discuz3.4
  13. Cloudflare免费CDN加速及防护
  14. 嵌入式Linux C笔试题积累
  15. 上海python周末培训班_上海python周末班
  16. L3-031 千手观音 - java
  17. 苹果手机闹钟声音大小怎么调_电脑上什么便签备忘录软件可以像闹钟那样按时提醒我们做事?...
  18. ceres Analytic Derivatives
  19. 关于Spring的两三事:万物之始—BeanDefinition
  20. 使用可信科技的人脸识别活体认证遇到的问题

热门文章

  1. MD4 算法代码实现
  2. 2019最新高级JAVA架构师之路(价值3万元的教程-年薪百万计划)
  3. 使用Python解二元一次方程组
  4. oracle报03113,一条SQL查询,报ora-03113的错误,请高手分析
  5. c语言的按位取反运算符
  6. 全流程基于最新导则下的生态环境影响评价技术方法及图件制作
  7. unity3d 台球源码_基于Unity3d的桌球游戏的设计与实现
  8. Arcgis中按照cass标准分幅图框进行批量正射影像DOM分幅裁剪并命名
  9. oracle中文转全拼音,(转)oracle下,把中文转为拼音函数编写
  10. python opencv导入pbtxt文件出现错误Failed to parse GraphDef file