AlexNet
AlexNET
一、预备知识
1.网络可视化
1 | pip install torchsummary |
输入:为模型、输入尺寸、批数量、设备
输出:模型的参数信息
1 | from torchsummary import summary |
测试:
1 | import torch |
输出:
2.数据集
百度网盘下载地址:
1 | 链接: https://pan.baidu.com/s/1Uro6RuEbRGGCQ8iXvF2SAQ 密码: hl31 |
ImageNet
数据集太大了1000类别,而且达到100多G的大小,因此换成Mini-ImageNet
测试网络
Mini-ImageNet
数据集大约3G左右,100个类别,每一个类别均有600张图片左右,共60000张图片,而且图片都是可变分辨率的(图片大小尺寸不固定)
数据集的结构:
1 | ├── mini-imagenet: 数据集根目录 |
Mini-Imagenet
数据集中包含了train.csv
、val.csv
以及test.csv
三个文件,但是提供的标签文件并不是从每个类别中进行采样的,因此无法直接用于训练分类,
1 | train.csv 包含38400张图片,共64个类别 |
按照上述链接下载文件之后,对images进行解压,在使用panads
对数据集进行分割,需要自己构建一个新的new_train.csv
与new_val.csv
以new_test.val
,代码中imagenet_class_index.json
的下载地址为:json
1 | """ |
一般训练集、验证集、测试集按照6:2:2
的比例进行分割,分割后得到的csv
文件如下
1 | new_train.csv 包含36000张图片,共100个类别 |
根据创建的csv文件划分为原始如下形式:
1 | Mini-imageNet |
代码如下:
1 | """ |
划分的数据集图片:
二、论文细节
1.ReLu
与Tanh
收敛速度的比较
在论文的3.1节中提到ReLu相较于Tanh收敛速度更快,且ReLu无需对输入数据进行归一化防止饱和,在不对数据进行归一化的情况下,比较如下:
(1)代码
1 | """ |
(2)结果
对上面的结果进行比较可以得到,ReLu
的收敛速度在17轮之前确实是优于tanh
2.LRN
论文的3.3接提到的局部响应标准化(LRN
)有助于AlexNet泛化能力的提升,受真实的神经元侧抑制启发
**侧抑制:**细胞分化变为不同时,会对周围细胞产生抑制信号,组织他们像相同的方向分化,最终表现为细胞命运的不同
- a 表示卷积层(包括卷积操作和激活操作)后的输出结果。这个输出的结果是一个四维数组 [batch,height,width,channel]。这个输出结构中的一个位置 [a,b,c,d],可以理解成在某一张特征图中的某一个通道下的某个高度和某个宽度位置的点,即第 a 张特征图的第 d 个通道下的高度为 b 宽度为 c 的点。
表示第 i 个通道的特征图在位置(x,y)运用激活函数 ReLU 后的输出。n 是同一位置上临近的 feature map 的数目,N 是特征图的总数。
即公式中的分母,若此处的分母越大即表示对该处的像素值抑制程度越大。若周围的deepth_radius范围存在较大的像素值,那么对于
的输出存在较大的抑制
论文中提到使用LRN
分别减少了top-1
和top-5
的1.4%与1.2%的错误率
(1)Pyotrch中LRN的实现
1 | torch.nn.LocalResponseNorm(size, alpha=0.0001, beta=0.75, k=1.0) |
在2014年的《Very Deep Convolutional Networks for Large-Scale Image Recognition》
提到LRN
技术实际用处不大
3. Overall architecture
- 首先输入的是一张
224x224x3
(因为是彩色`RGB三通道的图) - 第一层用的卷积核的大小是
11∗11∗3
,卷积核的个数是48+48=96
,从这一层开始两个GPU
开始分开运行,现在定义处理上半层特征图的叫GPU_A
,处理下半层特征图的叫GPU_B
,每个GPU
负责48个卷积核的运算,上半层GPU_A
生成48张特征图,下半层GPU_B
生成48张特征图。这一层卷积结束之后,还需要LRN
(Local Response Normalization
局部响应归一化)和Max_Pooling
(最大池化) - 第二层和第一层同理,两个
GPU
分别处理自己上一层传来的output
(那48张特征图),卷积核的大小是5∗5∗48
,然后一共有128+128=256
个卷积核,所以两个GPU
各自利用自己上一层的output
生成128
张特征图。这一层的卷积结束之后还需要LRN
(Local Response Normalization
局部响应归一化)和Max_Pooling
(最大池化) - 第三层和前两层不同,这一层两个
GPU
都要是将两个GPU
的上一层的全部输出output
作为输入input
,所以这一层的卷积核大小是3∗3∗ (128[来自GPU_A]+128[来自GPU_B])
,也就是这层的卷积核是3∗3∗256
,而不是像前两层那样只是把自己上一层的输出当成输入,这层一共有192+192=384
个卷积核,GPU_A
负责前192个卷积核的生成的特征图,GPU_B
负责后192
个卷积核生成的特征图 - 第四层和第五层同第三层
- 第六层,接了一个全连接层
(FC)
,首先将128[来自GPU_A]和128[来自GPU_B]
的一共256张特征图拉直成一个超长的向量,连接到一个大小为4096的全连接层中,其中4096个神经元的前2048个神经元由GPU_A
运算,后2048个神经元由GPU_B
来运算 - 第七层和第六层同理
- 第八层是再连接到一个大小为1000的全连接层中,用softmax,来算1000种分类的分布
(1)pytorch代码实现
AlexNet.py
,需要注意的是,目前网络全是在一块GPU上进行加速运算的,因此与原来的架构不一样
1 | """ |
4. Data Augmentation(数据增强)
论文在训练阶段使用两种数据增强的方式减少数据的过拟合,都允许用很少的计算从原始图像生成转换
(1)第一种
从256x256
的图像中随机扣下224x224
大小的图片,并进行随机的水平翻转,这样相当于将数据增加了2048倍(32x32x2)
- (数据保证符合网络期望的输入数据)将短边减少到256,长边也保证高宽比往下降,长边多出来的以中心为界将两个边进行裁剪在第二节
2 The Dataset
中提到过,ImageNet
是一个可变分辨率的数据集因此,
实现代码:
1 | import torchvision.transforms as transforms |
(2)第二种
第二种方法改变训练图像中RGB
通道的强度,对整个ImageNet
训练集的RGB
像素值集执行PCA
主成分分析,然后对主成分上的数进行微小的扰动,以此图像色彩就会发生微小的变化,增加图像的丰富性多样性
暂时不清楚如何对其进行操作…..,在AlexNet
实现时候效果有限
同时在测试阶段也有对数据进行的操作:
(3)测试阶段数据处理
在测试时,网络通过提取5个224 × 224
的patch(四个角斑和中心斑)及其水平反射(共10个patch)进行预测,并将网络的softmax
层对这10个patch的预测取平均
1 | valid_transform = transforms.Compose([ |
5. Dropout
在网络架构的前两个全链接层后添加Dropout
,防止了过拟合(论文作者最开始的理解是Dropout
是做模型融合,实际上是在正则化,之后本文作者写了一篇JMLR
文章说明Dropout实际等价一个L2
的正则,使用Dopout
可以提高模型的泛化性
6. Details of learning
在论文中使用SGD
随机梯度下降法作为优化函数进行权重参数优化,其中dataloader
中的batch_size = 128
,momentum = 0.9
,weight decay = 0.0005
训练细节:
- 权重参数初始化,标准差=0.01 均值=0 的高斯正太分布
- 有关学习率的调整,所有层的学习率相同,但是在验证的正确率随着当前学习率停止提高时,将学习率除以10继续训练;学习率
learn_rate = 0.01
初始值 - 训练拟合时,第一层卷积的可视化,也需要进行演示
三、实现
1.模型训练
模型使用Mini-ImageNet
数据集对网络模型进行训练拟合
1 | """ |
训练结束之后,会将最优以及最后训练的模型进行保存,此外还会将训练的日志在控制台输出以及存储至log.txt
文件中
最后会得到训练损失vs验证损失
以及 训练正确率vs验证正确率
的可视化曲线
训练得到的结果出现过拟合的现象,大概在迭代的10000次(10000/282=35)轮左右出现过拟合….
训练损失在降低,但是验证损失在增加,而且此时的测试正确率不再有变化…
(1)过拟合解决方法
过拟合出现的主要原因是因为:数据太少+模型太复杂
- 增加数据量
- 多收集数据集,扩大数据集的量
- 数据增强(通过图片的旋转、平移、亮度、切割),增加数据的多样性
- 正则化方法
L1
正则、L2
正则(使得某些权重w
不会过大)- Dropout
- 多模型组合
- 贝叶斯方法
(2)Pytorch实现正则化
在pytorch
中进行L2
正则化,最直接的方式可以直接用优化器自带的weight_decay
选项指定权值衰减率,相当于L2
正则化中的λ
1 | optimizer = optim.SGD(alexnet_model.parameters(), lr=LR, momentum=0.9,weight_decay=1e-5) |
对上述模型加入L2
的正则,并加载之前过拟合的训练的权重参数,发现其训练正确率在下降….
2.模型测试
测试集数据与验证集数据的数量是一致的均为12000
张
1 | """ |
测试结果与训练输出的曲线结果类似,测试正确率与验证正确率都是在 50%
左右(这是用过拟合的模型进行测试的)—- 第一次过拟合的模型放在My_Proj/Models/model_overfitting
目录下
3.卷积核的可视化
在论文第五节中提到,将第一层的卷积核提取出来可以看到第一层96个卷积核(GPU0 GPU1
)分别48个卷积核
1 | """ |
在pycharm
控制台的终端,进入存放web可视化文件的目录下My_Proj/Visualization_Log
目录下
终端输入:
1 | tensorboard --logdir=./ |
终端输出一个主机host
点击,会在web端的0_all
出现可视化的第一层卷积核:
后面几层卷积核,特征相对高级,很抽象。而且卷积核尺寸小,看不懂卷积学习的内容是什么
第一层卷积最为低级,而且卷积核尺寸为11x11
,可以看到第一层卷积学习了图片数据的颜色、纹理、边缘这些较为低级的特征。
神经网络对数据的特征进行提取符合由低级至高级特征提取的过程
四、结论
1.重点
AlexNet
本质是一个更大更深的LeNet
,主要改进有,Dropout
丢弃法、ReLu
激活函数、maxpooling
重叠池化;ReLu
与sigmoid
相比梯度更大,且ReLu
在零点处一阶导更好(减缓梯度消失),maxpooling
取最大池化,取最大值,输出梯度更大- 局部响应标准化(
LRN
)有助于AlexNet
泛化能力的提升,受真实的神经元侧抑制启发;但是在论文VGG
说该方法作用不大,而且有更好的Batch Normalization
PCA
对数据集图片的颜色进行扰动,对于模型的性能提升并不大,而且实现相对复杂,目前就不实现了…
2.启发性
- 初始的
224x224x3
的图片经过五层卷积之后,最后会被展平成一个256x6x6
的向量进入线性层,直到最后一个分类层(输出层)之前,向量长度为4096
,则一张图片会表示为4096
的维度,这个长度为4096的向量非常好的抓住了输入图片的语义信息。若两个图片最后的4096的向量的距离(欧几里德距离非常相近的话,那么这两张图片很有可能是同一个物体的图片)————-深度学习设计的网络可以通过中间的各种隐含层的操作将一张图片最后压缩为一个特征向量(知识的压缩),而这个向量可以很好的将中间的语义信息表示出来(变成了一个机器可以理解的东西) (论文的6.1 Qualitative Evaluations 中提及) - 将神经网络在倒数第二层的输出拿出来,得到一个长向量。然后将每个图片均拿出来,然后给定一张图片看一下和我这个向量最近的图片是谁(欧几里德距离),如果两幅图像产生的特征激活向量具有小的欧几里德距离,我们可以说神经网络认为它们是相似的(注意原始的图像之间的距离是不相近的,但是通过神经网络提取得到的高级特征向量之后,欧几里德距离是相近的)—深度神经网络的图片训练出来的最后那个向量,在语义空间的表示特别好(非常好的特征),相似的图片会将其放在一起
6.1 Qualitative Evaluations
最后提出可以使用AlexNet
做图像检索、图像聚类、图像编码,利用两个4096维实值向量之间的欧氏距离来计算相似度是低效的,但通过训练自动编码器将这些向量压缩成简短的二进制码可以提高效率。这将产生一种比对原始像素应用自动编码器好得多的图像检索方法,后者不使用图像标签,因此倾向于检索具有相似边缘模式的图像,无论它们在语义上是否相似。