深度学习|LeNet-5 详解+pytorch简洁实现

lenet 是Yann LeCun’s提出用于手写数字识别的简单卷积神经网络, 论文地址
网络结构如下:
深度学习|LeNet-5 详解+pytorch简洁实现
文章图片
深度学习|LeNet-5 详解+pytorch简洁实现
文章图片

LnNet共7层,不包括输入层,包括两个卷积层、两个池化层、三个全链接层,激活函数用sigmoid()。
参数详解如下 #1.input层-输入层

输入图像统一规划为32*32。

2.Convolutions-卷积层-C1层
输入h*w:32*32 in_channels:1 out_channels:6 kernel_size:5*5 padding : none 输出图片h/w:(32-5+1)= 28 神经元数量: 28*28*6 = 156 可训练参数:(5*5+1)*6 每个卷积核 5*5=25个unit参数和一个bias参数,一共六个核。 连接数:(5*5+1)*6*28*28 = 122304

详细说明: 对输入的13232的图像进行一次卷积运算,使用6个55的卷积核,得到6个2828的C1特征图,即输出通道数为6,总共有122304个链接,通过权值共享,我们只需要训练的参数为 (5*5+1)*6=156个参数。
3.Avgpool-平均池化层-S2层
输入h*w:28*28 in_channels:6 out_channels:6 kernel_size:2*2 stride : 2 padding:none 输出图片h/w:(28/2)= 14 神经元数量: 14*14*6 = 1176 可训练参数:2*6核的权和偏执(如果需要的话) 连接数:(2*2+1)*6*14*14 = 5880

【深度学习|LeNet-5 详解+pytorch简洁实现】说明:池化层的channels不变,只改变图片的h和w,使用pytorch的api时,无需指定channels,只需指定kernel_size和stride,padding.
4.Convolutions-卷积层-C3层
输入h*w:14*14 in_channels:6 out_channels:16 kernel_size:5*5 padding : none 输出图片h/w:(14-5+1)= 10 神经元数量: 10*10*16 = 1600 可训练参数:6*(3*5*5+1)+6*(4*5*5+1)+3*(4*5*5+1)+1*(6*5*5+1)=1516 连接数:(6*(3*5*5+1)+6*(4*5*5+1)+3*(4*5*5+1)+1*(6*5*5+1))*10*10=151600

详细说明: 第一次池化之后是第二次卷积,第二次卷积的输出是C3,16个10x10的特征图,卷积核大小是 55. 我们知道S2 有6个 1414 的特征图,怎么从6 个特征图得到 16个特征图了? 这里是通过对S2 的特征图特殊组合计算得到的16个特征图。具体如下:
深度学习|LeNet-5 详解+pytorch简洁实现
文章图片

层C3是具有16个5-5的卷积核的卷积层。前六个C3特征图的输入是S2中的三个特征图的每个连续子集(第一个红框),接下来的六个特征图的输入则来自四个连续子集的输入(第二个红框),接下来的三个特征图的输入来自不连续的四个子集(第三个红框)。最后一个特征图的输入来自S2所有特征图(第四个红矿)。C3层有1516个可训练参数和156 000个连接。卷积核大小依然为55,所以总共有6(355+1)+6*(455+1)+3*(455+1)+1*(655+1)=1516个参数。而图像大小为10*10,所以共有151600个连接。
C3与S2中前3个图相连的卷积结构如下图所示:
深度学习|LeNet-5 详解+pytorch简洁实现
文章图片

上图对应的参数为 3* 5* 5+1,一共进行6次卷积得到6个特征图,所以有6*(355+1)参数。 为什么采用上述这样的组合了?论文中说有两个原因:1)减少参数,2)这种不对称的组合连接的方式有利于提取多种组合特征。
5.Avgpool-平均池化层-S4层
输入h*w:10*10 in_channels:16 out_channels:16 kernel_size:2*2 stride : 2 padding:none 输出图片h/w:(10/2)= 5 神经元数量: 5*5*16 = 400 可训练参数:2*16核的权和偏执(如果需要的话) S4中每个特征图的大小是C3中特征图大小的1/4

详细说明:层S4是与S2类似,大小为22,输出为16个55的特征图。S4层有32个可训练参数和2000个连接。
6.把1655的数据打平成 400*1 7.Linear-全连接层
输入:400 输出:120

7.Linear-全连接层
输入:120 输出:84

7.Linear-全连接层-输出层
输入:84 输出:10

代码实现:
定义 改变输入维度的函数reshape
class Reshape(torch.nn.Module): def forward(self, x): return x.view(-1, 1, 28, 28)

定义网络:
net = torch.nn.Sequential( Reshape(), nn.Conv2d(1,6, kernel_size=5, padding=2), nn.Sigmoid(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(6,16, kernel_size=5), nn.Sigmoid(),nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),#打平,变成一维向量 第一维批量保持不变,其他的打平,nn.Linear(16*5*5, 120), nn.Sigmoid(),nn.Linear(120, 84), nn.Sigmoid(),nn.Linear(84, 10))

完整版:
LeNet-5 实现

    推荐阅读