一、LeNet-5

这个是n多年前就有的一个CNN的经典结构,主要是用于手写字体的识别,也是刚入门需要学习熟悉的一个网络。
原论文地址
输入:32*32的手写字体图片,这些手写字体包含0~9数字,也就是相当于10个类别的图片

输出:分类结果,0~9之间的一个数
因此我们可以知道,这是一个多分类问题,总共有十个类,因此神经网络的最后输出层必然是SoftMax问题,然后神经元的个数是10个。LeNet-5结构:

  • 输入层:32*32的图片,也就是相当于1024个神经元
  • C1层:paper作者,选择6个特征卷积核,然后卷积核大小选择55,这样我们可以得到6个特征图,然后每个特征图的大小为32-5+1=28,也就是神经元的个数为628*28=784。

参考公式

  • S2层:这就是下采样层,也就是使用最大池化进行下采样,池化的size,选择(2,2),也就是相当于对C1层2828的图片,进行分块,每个块的大小为22,这样我们可以得到1414个块,然后我们统计每个块中,最大的值作为下采样的新像素,因此我们可以得到S1结果为:1414大小的图片,共有6个这样的图片。

  • C3层:卷积层,这一层我们选择卷积核的大小依旧为55,据此我们可以得到新的图片大小为14-5+1=10,然后我们希望可以得到16张特征图。那么问题来了?这一层是最难理解的,我们知道S2包含:6张14 * 14大小的图片,我们希望这一层得到的结果是:16张1010的图片。这16张图片的每一张,是通过S2的6张图片进行加权组合得到的,具体是怎么组合的呢?问题如下图所示:
    为了解释这个问题,我们先从简单的开始,我现在假设输入6特征图的大小是55的,分别用6个55的卷积核进行卷积,得到6个卷积结果图片大小为11,如下图所示:
    为了简便起见,我这里先做一些标号的定义:我们假设输入第i个特征图的各个像素值为x1i,x2i……x25i,因为每个特征图有25个像素。因此第I个特征图经过5
    5的图片卷积后,得到的卷积结果图片的像素值Pi可以表示成:
    这个是卷积公式因此对于上面的P1 ~ P6的计算方法,这个就是直接根据公式。然后我们把P1~P6相加起来,也就是:

     P=P1+P2+……P6
    

把上面的Pi的计算公式,代入上式,那么我们可以得到:

 P=WX

其中X就是输入的那6张55特征图片的各个像素点值,而W就是我们需要学习的参数,也就相当于6个55的卷积核,当然它包含着6*(5*5)个参数。因此我们的输出特征图就是:

Out=f(P+b)

这个就是从S2到C3的计算方法,其中b表示偏置项,f为激活函数。

我们回归到原来的问题:有6张输入1414的特征图片,我们希望用55的卷积核,然后最后我们希望得到一张10*10的输出特征图片?

根据上面的过程,也就是其实我们用55的卷积核去卷积每一张输入的特征图,当然每张特征图的卷积核参数是不一样的,也就是不共享,因此我们就相当于需要6(55)个参数。对每一张输入特征图进行卷积后,我们得到6张1010,新图片,这个时候,我们把这6张图片相加在一起,然后加一个偏置项b,然后用激活函数进行映射,就可以得到一张10*10的输出特征图了。

总之,C3层每个图片是通过S2图片进行卷积后,然后相加,并且加上偏置b,最后在进行激活函数映射得到的结果。

  • S4层:下采样层,比较简单,也是知己对C3的16张1010的图片进行最大池化,池化块的大小为22。因此最后S4层为16张大小为55的图片。至此我们的神经元个数已经减少为:165*5=400。
  • C5层:我们继续用5*5的卷积核进行卷积,然后我们希望得到120个特征图。这样C5层图片的大小为5-5+1=1,也就是相当于1个神经元,120个特征图,因此最后只剩下120个神经元了。这个时候,神经元的个数已经够少的了,后面我们就可以直接利用全连接神经网络,进行这120个神经元的后续处理,

上面的结构,只是一种参考,在现实使用中,每一层特征图需要多少个,卷积核大小选择,还有池化的时候采样率要多少,等这些都是变化的,这就是所谓的CNN调参,我们需要学会灵活多变。

代码部分

采用pytorch官网的数据集

#model.pyimport torch.nn as nn
import torch.nn.functional as Fclass LeNet(nn.Module):def __init__(self):super(LeNet,self).__init__()self.covn1 = nn.Conv2d(3,16,5)self.pool1 = nn.MaxPool2d(2,2)self.conv2 = nn.Conv2d(16,32,5)self.pool2 = nn.MaxPool2d(2,2)self.fc1 = nn.Linear(32*5*5,120)self.fc2 = nn.Linear(120,84)self.fc3 = nn.Linear(84,10)def forward(self, x):x = F.relu(self.conv1(x))#input(3,32,32) output(16,28,28)x = self.pool1(x) #output(16,14,14)x = F.relu(self.conv2(x)) #output(32,10.10)x = self.pool2(x) #output(32,5,5)x = x.view(-1,32*5*5) #output(5*5*32)x = F.relu(self.fc1(x)) #output(120)x = F.relu(self.fc2(x)) #output(84)x = self.fc3(x) #output(10)return x# #model调试
# import torch# #定义shape
# input1 = torch.rand([32,3,32,32])
# model = LeNet()#实例化
# print(model)
# #输入网络中
# output = model(input1)

首先下载数据集

#train.pyimport torch
import torchvision
import torch.nn as nn
#from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms#预处理函数
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 50000张训练图片
train_set = torchvision.datasets.CIFAR10(root='./data', train=True,download=True, transform=transform))

或者在网盘下载
链接:https://pan.baidu.com/s/1NBHp0SxEOJ5EIyYUsDHm_g
提取码:qp3k

先小部分测试一下

#train.pyimport torch
import torchvision
import torch.nn as nn
from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms
from torchvision import transforms, datasets, utils
import matplotlib.pyplot as plt
import numpy as np#device : GPU or CPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 50000张训练图片
train_set = torchvision.datasets.CIFAR10(root='./data', train=True,download=False, transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=36,shuffle=False, num_workers=0)# 10000张验证图片
val_set = torchvision.datasets.CIFAR10(root='./data', train=False,download=False, transform=transform)
val_loader = torch.utils.data.DataLoader(val_set, batch_size=4,shuffle=False, num_workers=0)
val_data_iter = iter(val_loader)
val_image, val_label = val_data_iter.next()
print(val_image.size())
print(train_set.class_to_idx)
classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')#显示图像,之前需把validate_loader中batch_size改为4
aaa = train_set.class_to_idx
cla_dict = dict((val, key) for key, val in aaa.items())
def imshow(img):img = img / 2 + 0.5  # unnormalizenpimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()print(' '.join('%5s' % cla_dict[val_label[j].item()] for j in range(4)))
imshow(utils.make_grid(val_image))


正式测试

#train.pyimport torch
import torchvision
import torch.nn as nn
from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms
from torchvision import transforms, datasets, utils
import matplotlib.pyplot as plt
import numpy as np#device : GPU or CPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# 50000张训练图片
train_set = torchvision.datasets.CIFAR10(root='./data', train=True,download=False, transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=36,shuffle=False, num_workers=0)# 10000张验证图片
val_set = torchvision.datasets.CIFAR10(root='./data', train=False,download=False, transform=transform)
val_loader = torch.utils.data.DataLoader(val_set, batch_size=5000,shuffle=False, num_workers=0)
val_data_iter = iter(val_loader)
val_image, val_label = val_data_iter.next()
print(val_image.size())
# print(train_set.class_to_idx)
# classes = ('plane', 'car', 'bird', 'cat',
#           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
#
#
# #显示图像,之前需把validate_loader中batch_size改为4
# aaa = train_set.class_to_idx
# cla_dict = dict((val, key) for key, val in aaa.items())
# def imshow(img):
#     img = img / 2 + 0.5  # unnormalize
#     npimg = img.numpy()
#     plt.imshow(np.transpose(npimg, (1, 2, 0)))
#     plt.show()
#
# print(' '.join('%5s' % cla_dict[val_label[j].item()] for j in range(4)))
# imshow(utils.make_grid(val_image))net = LeNet()
net.to(device)loss_function = nn.CrossEntropyLoss()
#定义优化器
optimizer = optim.Adam(net.parameters(), lr=0.001)#训练过程
for epoch in range(10):  # loop over the dataset multiple timesrunning_loss = 0.0 #累加损失for step, data in enumerate(train_loader, start=0):# get the inputs; data is a list of [inputs, labels]inputs, labels = data#print(inputs.size(), labels.size())# zero the parameter gradientsoptimizer.zero_grad()#如果不清除历史梯度,就会对计算的历史梯度进行累加# forward + backward + optimizeoutputs = net(inputs.to(device))loss = loss_function(outputs, labels.to(device))loss.backward()optimizer.step()# print statisticsrunning_loss += loss.item()if step % 500 == 499:    # print every 500 mini-batcheswith torch.no_grad():#上下文管理器outputs = net(val_image.to(device))  # [batch, 10]predict_y = torch.max(outputs, dim=1)[1]accuracy = (predict_y == val_label.to(device)).sum().item() / val_label.size(0)print('[%d, %5d] train_loss: %.3f  test_accuracy: %.3f' %(epoch + 1, step + 1, running_loss / 500, accuracy))running_loss = 0.0print('Finished Training')save_path = './Lenet.pth'
torch.save(net.state_dict(), save_path)


进行预测

#predict.pyimport torch
import torchvision.transforms as transforms
from PIL import Image
from model import LeNet
import matplotlib.pyplot as plt
import numpy as np#预处理
transform = transforms.Compose([transforms.Resize((32, 32)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')net = LeNet()
net.load_state_dict(torch.load('Lenet.pth'))im = Image.open('飞机.jpg')      #测试飞机
#im = Image.open('猫.jpg')         #测试猫
#im = Image.open('轮船.jpg')       #测试狗
#im = Image.open('狗。jpg’)       #测试猫,可能出现错误
im1 = transform(im)  # [C, H, W]
im = torch.unsqueeze(im1, dim=0)  # [N, C, H, W]#显示图像
def imshow(img):img = img / 2 + 0.5  # unnormalizenpimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()
imshow(im1)with torch.no_grad():outputs = net(im)predict = torch.max(outputs, dim=1)[1].data.numpy()predict1 = torch.softmax(outputs, dim=1)print(predict1)print(classes[int(predict)])

参考自
Get achievement

LeNet-5——CNN经典网络模型详解(pytorch实现)相关推荐

  1. 【深度学习】ResNet——CNN经典网络模型详解(pytorch实现)

    建议大家可以实践下,代码都很详细,有不清楚的地方评论区见~ 1.前言 ResNet(Residual Neural Network)由微软研究院的Kaiming He等四名华人提出,通过使用ResNe ...

  2. DenseNet——CNN经典网络模型详解(pytorch实现)

    一.概述 论文:Densely Connected Convolutional Networks 论文链接:https://arxiv.org/pdf/1608.06993.pdf 代码的github ...

  3. GoogLeNet——CNN经典网络模型详解(pytorch实现)

    一.前言 论文地址:http://arxiv.org/abs/1602.07261 2014年,GoogLeNet和VGG是当年ImageNet挑战赛(ILSVRC14)的双雄,GoogLeNet获得 ...

  4. CNN经典网络模型详解LeNet(LeNet-1, LeNet-4, LeNet-5最详细, Boosted LeNet-4)发展和过程

    1.LeNet-5详细 2.回顾LeNet其他模型结构 3.补充 一.LeNet-5详细 LeNet-5是最受欢迎的LeNet-5,与LeNet-4相比只有细微差别,32x32的输入图像 – 6个28 ...

  5. MobileNet(v1、v2)——CNN经典网络模型详解(pytorch实现)

    在之前的文章中讲的AlexNet.VGG.GoogLeNet以及ResNet网络,它们都是传统卷积神经网络(都是使用的传统卷积层),缺点在于内存需求大.运算量大导致无法在移动设备以及嵌入式设备上运行. ...

  6. AlexNet--CNN经典网络模型详解(pytorch实现)

    二.AlexNet 在imagenet上的图像分类challenge上大神Alex提出的alexnet网络结构模型赢得了2012届的冠军,振奋人心,利用CNN实现了图片分类,别人用传统的机器学习算法调 ...

  7. 详解pytorch实现猫狗识别98%附代码

    详解pytorch实现猫狗识别98%附代码 前言 一.为什么选用pytorch这个框架? 二.实现效果 三.神经网络从头到尾 1.来源:仿照人为处理图片的流程,模拟人们的神经元处理信息的方式 2.总览 ...

  8. python中squeeze函数_详解pytorch中squeeze()和unsqueeze()函数介绍

    squeeze的用法主要就是对数据的维度进行压缩或者解压. 先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的 ...

  9. UNIX经典命令详解

    UNIX经典命令详解 第一章 目录及文件操作命令 1.1 ls [语法]: ls [-RadCxmlnogrtucpFbqisf1] [目录或文件......]  [说明]: ls 命令列出指定目录下 ...

最新文章

  1. 用CMake构建工程时 cmake -G“Unix Makefiles“ 的使用
  2. python哪一版好用-python IDE有哪些?哪个好用?
  3. Android OTA 升级之三:生成recovery.img
  4. Qt智能指针--QSharedPointer
  5. 阿里巴巴大规模应用Flink的踩坑经验:如何大幅降低 HDFS 压力?
  6. 设计模式之_Iterator_01
  7. 敏捷软件开发宣言–Manifesto for Agile Software Development
  8. 作者:詹晓娟(1978-),女,黑龙江工程学院讲师。
  9. andorid平台游戏内存修改器的开发思路
  10. Fix: Send-Mail: Warning: Inet_protocols: IPv6 Support Is Disabled
  11. Unity3D开发电脑选择
  12. 双主动桥隔离双向DC-DC变换器(七)设计建议及未来趋势、总结
  13. 使用小马激活工具激活Windows后,浏览器的首页被篡改,如何改回去?
  14. win 7旗舰版开机提示 :explorer.exe-无法找到入口
  15. 与浏览网站的访客直接进行QQ对话
  16. 原生webgl学习(六) WebGL写简单的汉字(一)
  17. 细说华为和荣耀的关系:潮流的荣耀和稳重的华为
  18. Unity Shaders and Effects Cookbook (7-2) Surface Shader 中实现 顶点动画
  19. 豆瓣评分高于8.8分的计算机书籍
  20. C语言之memset函数

热门文章

  1. 神奇的 SQL 之团结的力量 → JOIN
  2. vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多
  3. 【JAVA 第三章 流程控制语句】课后习题 输出正整数的顺序相反数
  4. 怎么不保存退出、保存退出vim、vi编辑
  5. 【C语言】一元二次方程(求实根和虚根)
  6. C#LeetCode刷题之#840-矩阵中的幻方(Magic Squares In Grid)
  7. ddt python_python-ddt实践
  8. 用Python盘点那些豆瓣评分低于3.0的奇葩电影
  9. Python回调函数的实现
  10. PTA-数组元素循环右移问题