论文:GradientBased Learning Applied to Do cument Recognition
前言
LetNet-5被设计用于手写数字识别,成为了卷积神经网络(Convolutional Neural Network,简称CNN)的开山之作,此后,基于CNN的深度学习方法层出不穷,大放异彩。
模型介绍
LetNet-5的结构的简洁明了,但已经完整展现了CNN的三大核心结构:
- 卷积层(Convolution Layer):提取图像特征;
- 池化层(Pooling Layer):筛选特征;
- 全连接(Fully Connected Layer):进行分类。
如下:
Input:大小为 32×32 的 image;
Layer C1:使用 6 个大小为 5×5 的卷积核进行卷积(convolutions),stride=1,padding=0,得到 6 张 28×28 feature maps;
Layer S2:使用 6 个大小为 2×2 的卷积核进行下采样(subsampling),stride=2,padding=0,得到 6 张 14×14 feature maps;
Layer C3:使用 16 个大小为 5×5 的卷积核进行卷积,stride=1,padding=0,得到 16 张 10×10 feature maps。在论文中,作者对卷积的方法做了如下要求:
横坐标表示S2中的feature maps(6张),纵坐标表示C3中的feature maps(16张),第1列“0”表示C3的第一张feature map由S2中的前三张feature map参与卷积得到,后面依次类推。
为什么不将每个S2特征映射连接到每个C3特征映射呢? 作者认为原因是双重的。首先,非完整连接方案将连接数量保持在合理范围内。更重要的是,它迫使网络中的对称性被打破。不同的特征映射被迫提取不同的(希望是互补的)特征,因为它们得到不同的输入集。
(在实际写代码时,并不会这样去单个的手动设计卷积范围)
Layer S4:使用 16 个大小为 2×2 的卷积核进行下采样,stride=2,padding=0,得到 16 张 5×5 feature maps;
Layer C5:使用 120 个大小为 5×5 的卷积核进行卷积,stride=1, padding=0,得到 120 张 1×1 feature maps;
Layer F6:线性变换,输入120(上一层的输出维度),输出84;
Output:线性变换,输入84,输出10(类别数,手写数字类别为10)。
上述,Layer C表示卷积层,Layer S是池化层(池化操作往往会减小图像的维度,又可称之为下采样),Layer F是全连接层。
LeNet-5代码
用Pytoch对LeNet-5进行实现,如下:
import torch
import torch.nn as nn
import torch.nn.functional as F
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
self.conv3 = nn.Conv2d(16, 120, 5)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(120, 84)
self.fc2 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = F.relu(self.conv3(x))
x = torch.flatten(x, 1)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
if __name__ == "__main__":
net = LeNet()
print(net)