经典分类网络(传送门):目录索引、LeNet、AlexNet、VGG、ResNet、Inception、DenseNet、SeNet。
相关文章:AlexNet论文翻译
ImageNet Classification with Deep Convolutional Neural Networks
文章虽然发表在12年,但文章中提到的Relu、Dropput,momentum、数据增广方式、10 paths测试法以及作者认为深度是非常重要的,这些都是现在神经网络的基础。很值得仔细阅读和理解。
1、特性/贡献
发表于2012年,在ImageNet测试数据上,我们得到了top-1 37.5%, top-5 17.0%的错误率,赢得了冠军并且与第二名 top-5 26.2%的错误率相比,我们取得了top-5 15.3%的错误率。
贡献(到目前为止仍在被使用的技巧):
1、使用Relu激活函数.
Relu激活函数学习速率总是比饱和神经元网络快几倍。
2、引入Dropput,momentum(动量学习率)
权重衰减:正则项,减少训练误差。
3、整体结构:
input_shape = (224, 224, 3)
主要优势:网络加深(相比lenet),5个conv+3个Dense+1个softmax
4、两种数据增广方式(至今仍是经典)
改变图像位置:平移、翻转、随机剪裁;
改变图像像素值,不改变位置:随机颜色变换;
测试方式:10 paths测试法。
5、遵循启发式的方法(至今仍是经典)
所有的层使用相等的学习率,这个是在整个训练过程中我们手动调整得到的。当验证误差在当前的学习率下停止提供时,我们遵循启发式的方法将学习率除以10。学习率初始化为0.01,在训练停止之前降低三次。
6、作者实验发现,认为深度是非常重要的。
2、文章中的一些见解
1)与具有层次大小相似的标准前馈神经网络,CNNs有更少的连接和参数,因此它们更容易训练,而它们理论上的最佳性能可能仅比标准前馈神经网络差一点;
2)最终的网络包含5个卷积层和3个全连接层,深度似乎是非常重要的:我们发现移除任何卷积层(每个卷积层包含的参数不超过模型参数的1%)都会导致更差的性能;
3、数据处理
训练时,将图像进行下采样到固定的256×256分辨率。给定一个矩形图像,我们首先缩放图像短边长度为256,然后从结果图像中裁剪中心的256×256大小的图像块。在训练集上对像素减去像素平均值。
即:等比例缩放至256,中心剪裁获取256*256的图像。
数据增强:
剪裁式数据增广:第一种数据增强方式包括产生图像变换和水平翻转。我们从256×256图像上通过随机提取224 × 224的图像块实现了这种方式,然后在这些提取的图像块上进行训练。这通过一个2048因子增大了我们的训练集,尽管最终的训练样本是高度相关的。没有这个方案,我们的网络会有大量的过拟合,这会迫使我们使用更小的网络。在测试时,网络会提取5个224 × 224的图像块(四个角上的图像块和中心的图像块)和它们的水平翻转(因此总共10个图像块)进行预测,然后对网络在10个图像块上的softmax层进行平均。
第二种数据增强方式包括改变训练图像的RGB通道的强度。具体地,我们在整个ImageNet训练集上对RGB像素值集合执行PCA。对于每幅训练图像,我们加上多倍找到的主成分,大小成正比的对应特征值乘以一个随机变量,随机变量通过均值为0,标准差为0.1的高斯分布得到。因此对于每幅RGB图像像素$I_xy = [I^R_{xy} , I^G_{xy} , I^B_{xy} ]^T$,我们加上下面的数量:
$p_i$,$\lambda_i$分别是RGB像素值3 × 3协方差矩阵的第$i$个特征向量和特征值,$\alpha_i$是前面提到的随机变量。对于某个训练图像的所有像素,每个$\alpha_i$只获取一次,直到图像进行下一次训练时才重新获取。这个方案近似抓住了自然图像的一个重要特性,即光照的颜色和强度发生变化时,目标身份是不变的。这个方案减少了top 1错误率1%以上。
即:随机剪裁使网络一定程度的克服数据上的过拟合,随机调整RGB颜色通道强度,使得top 1错误率减少1%以上。
4、网络结构
4.1、Relu非线性激活函数
Relu激活函数学习速率总是比饱和神经元网络快几倍。虚线是tanh激活训练曲线,实线是Relu激活函数。在CIFAR-10上,relu要比tanh从0.75错误率下降到0.25的错误率快上好几倍。
4.2、重叠池化
CNN中的池化层归纳了同一核映射上相邻组神经元的输出。习惯上,相邻池化单元归纳的区域是不重叠的(例如[17, 11, 4])。更确切的说,池化层可看作由池化单元网格组成,网格间距为 s 个像素,每个网格归纳池化单元中心位置 z × z 大小的邻居。如果设置 s = z ,我们会得到通常在CNN中采用的传统局部池化。如果设置 s < z ,我们会得到重叠池化。这就是我们网络中使用的方法,设置 s = 2 ,z = 3 。这个方案分别降低了top-1 0.4%,top-5 0.3%的错误率,与非重叠方案s = 2,z = 2相比,输出的维度是相等的。我们在训练过程中通常观察采用重叠池化的模型,发现它更难过拟合。
即:kernel_size=3, stride=2。top-1 错误率降低0.4%,且更难过拟合。
4.3、隐层局部归一化,BN,Dropput,动量学习率
Dropput:
将许多不同模型的预测结合起来是降低测试误差[1, 3]的一个非常成功的方法,但对于需要花费几天来训练的大型神经网络来说,这似乎太昂贵了。然而,有一个非常有效的模型结合版本,它只花费两倍的训练成本。这种最近引入的技术,叫做“dropout”[10],它会以0.5的概率对每个隐层神经元的输出设为0。那些“失活的”的神经元不再进行前向传播并且不参与反向传播。因此每次输入时,神经网络会采样一个不同的架构,但所有架构共享权重。这个技术减少了复杂的神经元互适应,因为一个神经元不能依赖特定的其它神经元的存在。因此,神经元被强迫学习更鲁棒的特征,它在与许多不同的其它神经元的随机子集结合时是有用的。
在测试时,我们使用所有的神经元但它们的输出乘以0.5,对指数级的许多失活网络的预测分布进行几何平均,这是一种合理的近似。
我们在图2中的前两个全连接层使用失活。如果没有失活,我们的网络表现出大量的过拟合。dropout大致上使要求收敛的迭代次数翻了一倍,训练速度为1/Dropout。
学习细节:
我们使用随机梯度下降来训练我们的模型,样本的batch size为128,动量为0.9,权重衰减为0.0005。我们发现少量的权重衰减对于模型的学习是重要的。换句话说,权重衰减不仅仅是一个正则项:它减少了模型的训练误差。权重 w 的更新规则是:
i 是迭代索引,v 是动量变量,e是学习率,e*(al/aw|wi)*Di是目标函数对 w ,在 w_i上的第 i 批微分 D_i的平均。
我们使用均值为0,标准差为0.01的高斯分布对每一层的权重进行初始化。我们在第2,4,5卷积层和全连接隐层将神经元偏置初始化为常量1。这个初始化通过为ReLU提供正输入加速了学习的早期阶段。我们在剩下的层将神经元偏置初始化为0。
我们对所有的层使用相等的学习率,这个是在整个训练过程中我们手动调整得到的。当验证误差在当前的学习率下停止提供时,我们遵循启发式的方法将学习率除以10。学习率初始化为0.01,在训练停止之前降低三次。我们在120万图像的训练数据集上训练神经网络大约90个循环,在两个NVIDIA GTX 580 3GB GPU上花费了五到六天。
5、网络结构
AlexNet诞生于2012年,主要优势是网络加深(5个卷积层+3个全连接层+1个softmax层),也是在那年之后,更多的更深的神经网路被提出。
第一层(卷积+池化):
输入:224*224*3大小的彩色原图,预处理为227*227*3的大小;
Conv1:96个11*11的卷积核,步长4, 输出图为55*55*96 (2个并行的48) ;(227-11)/4+1=55 ;
relu1:激活函数定义为ReLU(x)=max(x,0);
pooling1:3*3 pool,步长2,输出图为27*27*96;
第二层:
输入:27*27*96大小的特征图;
Conv2:256个5*5*96的卷积核,加边padding=2,图大小不变,步长1, 输出图为 27*27*256 (2个128并行) ; (27-5+2*2)/1+1=27;
relu2:激活函数定义为ReLU(x)=max(x,0);
pooling2:3*3 pool,步长2,输出图为13*13*256;
第三层:
输入:13*13*256大小的特征图;
Conv3:384个3*3*256的卷积核,加边,图大小不变,步长1, 输出图为13*13*384 (2个192并行) ;(13-3+2*1)/1+1=13
第四层:
输入:13*13*384大小的特征图;
Conv4:384个3*3*384的卷积核,加边,图大小不变,步长1, 输出图为13*13*384 (2个192并行) ; (13-3+2*1)/1+1=13
第五层:
输入:13*13*384大小的特征图;
Conv5:256个3*3*384的卷积核,步长2, 输出图为8*8*256 (2个128并行) ; (13-3+2*2)/2+1=8;
pooling5:2*2 pool,步长2,输出图为4*4*256;
全连接层:
输入:4*4*256的特征图,将4*4*256的特征图拉成一个4096的向量,即4096个节点;
隐层:同输入层节点数,即4096个节点 ;
输出:1000,表示有1000个类别;
特点:
卷积核大小:11*11->5*5->3*3->3*3->3*3,大小由大至小
隐层单元深度:96->256->256->384->256,从小至大再至小
特征图大小:224->55->27->13->13->8,倍数递减,至不变
6、实现
训练速度为1/Dropout,可进一步减少过拟合,BN在卷积激活层后添加。局部响应归一化(A-LRN网络)在没有任何归一化层的情况下,对模型VGG的A模型没有改善(VGG论文翻译)。在一些版本的实现用BN替代,这里示例代码不做填加。
import torch as t
import torch.nn as nn
class AlexNet(nn.Module):
def __init__(self, num_classes):
super(AlexNet, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(3, 96, 11, 4, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.layer2 = nn.Sequential(
nn.Conv2d(96, 256, 5, 1, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
self.layer3 = nn.Sequential(
nn.Conv2d(256, 384, 3, 1, padding=1),
nn.ReLU(inplace=True),
)
self.layer4 = nn.Sequential(
nn.Conv2d(384, 384, 3, 1, padding=1),
nn.ReLU(inplace=True),
)
self.layer5 = nn.Sequential(
nn.Conv2d(384, 256, 3, 2, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.classifier = nn.Sequential(
nn.Dropout(0.5),
nn.Linear(256 * 4 * 4, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.layer5(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
if __name__ == '__main__':
x = t.randn(1, 3, 224, 224)
model = AlexNet(1000)
y = model(x)
print("model:", model)
print("y:", y.shape)
pass
完整代码实现:https://github.com/alexzhang19/pytorch-classify/blob/master/models/alexnet.py
上一篇:AlexNet论文翻译,下一篇:VGG论文翻译,传送门:分类网络目录索引。