CNN(卷积神经网络)借助卷积层保留了输入形状,使图像在宽和高两个方向上的相关性均可能被有效识别,另一方面卷积层通过滑动窗口将同一卷积核与不同位置的输入重复计算,从而避免了参数尺寸过大。有效集解决了临近像素点的特征提取和模型参数过大的问题。 卷积神经网络就是包含卷积层的网络,这个名字最早来源于Lenet论文的第一作者Yann LeCun。Lenet展示了通过梯度下降训练卷积神经网络可以达到手写数字识别在当时最先进的成果。
Lenet
LeNet模型分为卷积层块和全连接层块。
卷积层块里的基本单位是卷积层后接最大池化层(Maxpool),卷积层用来识别图像里的空间模式,如线条和物体局部,之后的最大池化层则用来降低卷积层对位置的敏感性。卷积层块由两个这样的基本单位重复堆叠而成,每个卷积层都使用5x5的kernel,并在输出上使用sigmoid激活函数。最大池化层的kernel形状均为2x2,且步幅为2。
卷积层块的输出传入全连接层时,将输出的形状变为二维,其中第一维是小批量中的样本,第二维是每个样本的向量表示,向量长度为CxHxW。全连接层块包含三个全联接层,他们的输出个数分别是120、84、10。其中10位输出的类别个数。
Pytorch代码实现:
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 6, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2),
nn.Conv2d(6, 16, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2)
)
self.fc = nn.Sequential(
nn.Linear(16*4*4, 120),
nn.Sigmoid(),
nn.Linear(120, 84),
nn.Sigmoid(),
nn.Linear(84, 10)
)
def forward(self, img):
feature_map = self.conv(img)
output = self.fc(feature_map.view(img.shape[0], -1))
return output
AlexNet
在LeNet提出的近20年间,神经网络一度被其他机器学习方法取代,虽然LeNet在小数据集上取得了不错的成绩,但是在更大的真实数据集上的表现却不尽如人意。一方面受硬件水平限制,算力无法满足计算需求,另一方面,当年的研究者没有深入研究参数初始化和非凸优化算法等诸多领域,导致复杂的神经网络训练通常较为困难。
从LeNet可以看到,神经网络可以基于图像的原始像素进行分类。这种端到端的方法节省了很多中间步骤。然而,在很长一段时间里更流行的是研究者设计并生成手工的特征。这类图像分类研究的主要流程是:
- 获取图像数据集;
- 使用已有的特征提取函数提取图像特征;
- 使用机器学习模型对提取的特征进行分类。
当时认为的机器学习部分仅限于最后一步,然而另一部分人认为特征本身也应该由学习得来,并且,为了表征足够复杂的输入,特征本身应该分级表示,多层神经网络可以学习到数据的多级表征,并逐级表示越来越抽象的概念。在很长一段时间里,这部分人的理念并未实现,原因有二。 其一为数据集的限制,包含许多特征的深度模型需要大量的有标签数据集才能表现的比其他经典方法更好。这一状况在2010年前后兴起的大数据浪潮中得以改善,特别是2009年诞生的ImageNet数据集,包含1000类物体,每类多达数千张不同图像。ImageNet数据集同时推动计算机视觉和机器学习研究进入了新阶段。 其二为硬件资源限制,早期的硬件计算能力有限,使得训练较为复杂的神经网络非常困难,这一格局直到通用GPU的出现才得以改善。
2012年AlexNet使用8层卷积神经网络赢得了ImageNet 2012图像识别挑战赛,首次证明了学习到的特征可以超越手工设计的特征。
AlexNet的研究理念与LeNet非常相似,但也有显著的区别:
- 模型结构变化
AlexNet使用5层卷积和3层全连接,其中第一层卷积Kernel为11x11,这样做的目的是扩大感受野来捕获较大输入图像的特征。第二层的卷积kernel形状减小到5x5
|