先说一个小知识,助于理解代码中各个层之间维度是怎么变换的。

卷积函数:一般只用来改变输入数据的维度,例如3维到16维。

Conv2d()

Conv2d(in_channels:int,out_channels:int,kernel_size:Union[int,tuple],stride=1,padding=o):
"""
:param in_channels: 输入的维度
:param out_channels: 通过卷积核之后,要输出的维度
:param kernel_size: 卷积核大小
:param stride: 移动步长
:param padding: 四周添多少个零
"""

一个小例子:

import torch
import torch.nn
# 定义一个16张照片,每个照片3个通道,大小是28*28
x= torch.randn(16,3,32,32)
# 改变照片的维度,从3维升到16维,卷积核大小是5
conv= torch.nn.Conv2d(3,16,kernel_size=5,stride=1,padding=0)
res=conv(x) print(res.shape)
# torch.Size([16, 16, 28, 28])
# 维度升到16维,因为卷积核大小是5,步长是1,所以照片的大小缩小了,变成28

卷积神经网络实战之Lenet5:

下面放一个示例图,代码中的过程就是根据示例图进行的

  • 1.经过一个卷积层,从刚开始的[b,3,32,32]-->[b,6,28,28]
  • 2.经过一个池化层,从[b,6,28,28]-->[b,6,14,14]
  • 3.再经过一个卷积层,从[b,6,14,14]-->[b,16,10,10]
  • 4.再经过一个池化层,从[b,16,10,10]-->[b,16,5,5]
  • 5.经过三个个全连接层,将数据[b,16,5,5]-->[b,120]-->[b,84]-->[b,10]

Lenet5的构造如下:

Lenet5(
(conv_unit): Sequential(
(0): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(fc_unit): Sequential(
(0): Linear(in_features=400, out_features=120, bias=True)
(1): ReLU()
(2): Linear(in_features=120, out_features=84, bias=True)
(3): ReLU()
(4): Linear(in_features=84, out_features=10, bias=True)
)
)

程序运行前,先启动visdom,如果没有配置好visdom环境的,先百度安装好visdom环境

  • 1.使用快捷键win+r,在输入框输出cmd,然后在命令行窗口里输入python -m visdom.server,启动visdom

代码实战

定义一个名为lenet5.py的文件,代码如下

import torch
from torch import nn
import torch.optim
import torch.nn
from torch.nn import functional as F class Lenet5(nn.Module):
# for cifar10 dataset.
def __init__(self):
super(Lenet5, self).__init__() # 卷积层 Convolutional
self.conv_unit = nn.Sequential(
# x:[b,3,32,32]==>[b,6,28,28]
nn.Conv2d(3, 6, kernel_size=5, stride=1, padding=0),
# x:[b,6,28,28]==>[b,6,14,14]
nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
#[b,6,14,14]==>[b,16,10,10]
nn.Conv2d(6,16,kernel_size=5,stride=1,padding=0),
# x:[b,16,10,10]==>[b,16,5,5]
nn.MaxPool2d(kernel_size=2,stride=2,padding=0), ) # 全连接层fully connected
self.fc_unit=nn.Sequential(
nn.Linear(16*5*5,120),
nn.ReLU(),
nn.Linear(120,84),
nn.ReLU(),
nn.Linear(84,10)
) def forward(self,x):
"""
:param x:[b,3,32,32]
:return:
"""
batchsz=x.size(0)
# 卷积层池化层运算 [b,3,32,32]==>[b,16,5,5]
x=self.conv_unit(x) # 对数据进行打平,方便后边全连接层进行运算[b,16,5,5]==>[b,16*5*5]
x=x.view(batchsz,16*5*5) # 全连接层[b,16*5*5]==>[b,10]
logits=self.fc_unit(x) return logits
# loss=self.criteon(logits,y) def main():
net=Lenet5()
# [b,3,32,32]
temp = torch.randn(2, 3, 32, 32)
out = net(temp)
# [b,16,5,5]
print("lenet_out:", out.shape) if __name__ == '__main__':
main()

定义一个名为main.py的文件,代码如下

import torch
from torchvision import datasets
from torchvision import transforms
from torch.utils.data import DataLoader
from torch import nn,optim
from visdom import Visdom
from lenet5 import Lenet5 def main():
batch_siz=32
cifar_train = datasets.CIFAR10('cifar',True,transform=transforms.Compose([
transforms.Resize((32,32)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
]),download=True)
cifar_train=DataLoader(cifar_train,batch_size=batch_siz,shuffle=True) cifar_test = datasets.CIFAR10('cifar',False,transform=transforms.Compose([
transforms.Resize((32,32)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
]),download=True)
cifar_test=DataLoader(cifar_test,batch_size=batch_siz,shuffle=True) x,label = iter(cifar_train).next()
print('x:',x.shape,'label:',label.shape) # 指定运行到cpu //GPU
device=torch.device('cpu')
model = Lenet5().to(device) # 调用损失函数use Cross Entropy loss交叉熵
# 分类问题使用CrossEntropyLoss比MSELoss更合适
criteon = nn.CrossEntropyLoss().to(device)
# 定义一个优化器
optimizer=optim.Adam(model.parameters(),lr=1e-3)
print(model) viz=Visdom()
viz.line([0.],[0.],win="loss",opts=dict(title='Lenet5 Loss'))
viz.line([0.],[0.],win="acc",opts=dict(title='Lenet5 Acc')) # 训练train
for epoch in range(1000):
# 变成train模式
model.train()
# barchidx:下标,x:[b,3,32,32],label:[b]
for barchidx,(x,label) in enumerate(cifar_train):
# 将x,label放在gpu上
x,label=x.to(device),label.to(device)
# logits:[b,10]
# label:[b]
logits = model(x)
loss = criteon(logits,label) # viz.line([loss.item()],[barchidx],win='loss',update='append')
# backprop
optimizer.zero_grad()
loss.backward()
optimizer.step()
viz.line([loss.item()],[epoch],win='loss',update='append')
print(epoch,'loss:',loss.item()) # 变成测试模式
model.eval()
with torch.no_grad():
# 测试test
# 正确的数目
total_correct=0
total_num=0
for x,label in cifar_test:
# 将x,label放在gpu上
x,label=x.to(device),label.to(device)
# [b,10]
logits=model(x)
# [b]
pred=logits.argmax(dim=1)
# [b] = [b'] 统计相等个数
total_correct+=pred.eq(label).float().sum().item()
total_num+=x.size(0)
acc=total_correct/total_num
print(epoch,'acc:',acc) viz.line([acc],[epoch],win='acc',update='append')
# viz.images(x.view(-1, 3, 32, 32), win='x') if __name__ == '__main__':
main()

测试结果

准确率刚开始是有一定的上升的,最高可达64%,后来准确率就慢慢的下降。

Pytorch-卷积神经网络CNN之lenet5的Pytorch代码实现的更多相关文章

  1. 写给程序员的机器学习入门 (八) - 卷积神经网络 (CNN) - 图片分类和验证码识别

    这一篇将会介绍卷积神经网络 (CNN),CNN 模型非常适合用来进行图片相关的学习,例如图片分类和验证码识别,也可以配合其他模型实现 OCR. 使用 Python 处理图片 在具体介绍 CNN 之前, ...

  2. 卷积神经网络CNN总结

    从神经网络到卷积神经网络(CNN)我们知道神经网络的结构是这样的: 那卷积神经网络跟它是什么关系呢?其实卷积神经网络依旧是层级网络,只是层的功能和形式做了变化,可以说是传统神经网络的一个改进.比如下图 ...

  3. 卷积神经网络(CNN)学习笔记1:基础入门

    卷积神经网络(CNN)学习笔记1:基础入门 Posted on 2016-03-01   |   In Machine Learning  |   9 Comments  |   14935  Vie ...

  4. 深度学习之卷积神经网络CNN

    转自:https://blog.csdn.net/cxmscb/article/details/71023576 一.CNN的引入 在人工的全连接神经网络中,每相邻两层之间的每个神经元之间都是有边相连 ...

  5. 深度学习之卷积神经网络CNN及tensorflow代码实例

    深度学习之卷积神经网络CNN及tensorflow代码实例 什么是卷积? 卷积的定义 从数学上讲,卷积就是一种运算,是我们学习高等数学之后,新接触的一种运算,因为涉及到积分.级数,所以看起来觉得很复杂 ...

  6. 深度学习之卷积神经网络CNN及tensorflow代码实现示例

    深度学习之卷积神经网络CNN及tensorflow代码实现示例 2017年05月01日 13:28:21 cxmscb 阅读数 151413更多 分类专栏: 机器学习 深度学习 机器学习   版权声明 ...

  7. 卷积神经网络(CNN)前向传播算法

    在卷积神经网络(CNN)模型结构中,我们对CNN的模型结构做了总结,这里我们就在CNN的模型基础上,看看CNN的前向传播算法是什么样子的.重点会和传统的DNN比较讨论. 1. 回顾CNN的结构 在上一 ...

  8. 卷积神经网络(CNN)反向传播算法

    在卷积神经网络(CNN)前向传播算法中,我们对CNN的前向传播算法做了总结,基于CNN前向传播算法的基础,我们下面就对CNN的反向传播算法做一个总结.在阅读本文前,建议先研究DNN的反向传播算法:深度 ...

  9. 【深度学习系列】手写数字识别卷积神经--卷积神经网络CNN原理详解(一)

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

  10. 深度学习之卷积神经网络(CNN)详解与代码实现(二)

    用Tensorflow实现卷积神经网络(CNN) 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/10737065. ...

随机推荐

  1. 学习ASP.NET Core Razor 编程系列文章目录

    学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二--添加一个实体 学习ASP.NET Core Razor 编程系列三--创建数据表及创建项目 ...

  2. Spring5课堂笔记

    Spring5 1..Spring 1.1.简介 Spring --> 春天,为开源软件带来了春天 2002,首次推出了Spring框架的雏形:interface21框架! Spring框架以i ...

  3. linux 三剑客命令

    Linux 命令集合 目录 Linux 命令集合 基础概念 1 软连接和硬链接 1.1 基础概念 1.2 如何创建软链接 零.正则 01 区别 02 通配符 03 基础正则 04 扩展正则 一 awk ...

  4. autohotkey 设置快捷键 设置光标位置 (ctrl + alt + Numpad0)

    autohotkey 设置快捷键 设置光标位置 (ctrl + alt + Numpad0) 原因 3个屏幕,所以鼠标设置的灵敏度非常高,经常就找不到鼠标在哪了. 设置个快捷键,让鼠标每次都初始化一个 ...

  5. [VueJsDev] 基础知识 - AutoNumber VsCode 插件开发

    [VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html AutoNumber VsCode插件开发 ::: deta ...

  6. Spring Boot获取配置参数最简单常用的两种方式

    一.自定义属性及常量 在开发过程中,我们常常用到的多环境配置文件,常用的有:dev,test,prod,在不同环境下,我们用到的一样的配置参数,例如:redis,mq,回调接口的url配置.这个情况, ...

  7. RabbitMQ集群运维实践

    一.RabbitMQ的集群模式 主要有两种:普通集群模式和镜像队列模式.下面分别介绍这两种模式的原理: 1.普通集群模式: 在普通集群模式下,RabbitMQ的集群节点之间主要同步元数据,而不同步存储 ...

  8. Android之Window和弹窗问题

    目录介绍 10.0.0.1 Window是什么?如何通过WindowManager添加Window(代码实现)?WindowManager的主要功能是什么? 10.0.0.2 Window概念解析?W ...

  9. 记录--vue3+setup+ts 知识总结

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 vue3 于 2020 年 09 月 18 日正式发布,2022 年 2 月 7 日 vue3 成为新的默认版本 距离 vue3 正式发布 ...

  10. 开发必会系列:《深入理解JVM(第二版)》读书笔记

    一  开始前 HotSpot:http://xiaomogui.iteye.com/blog/857821 http://blog.csdn.net/u011521890/article/detail ...