AlexNet的创新在于:
1.ReLU激活函数
2.双GPU模型并行
3.LRN局部响应归一化
4.重叠最大池化
5.数据增强
6.Dropout正则化
首次将CNN做到又宽又深,后来的深度学习算法都绕不过alexnet的思想
要知道从lenet开始长达二十年的时间,CNN都是非常小的,无法处理自然状态下的图像分类任务
LRU 局部响应归一化
他这个归一化比一般的归一化将 值限制在一个更小的范围内,他是用的平方和做基底,分子还是用的原数。对于大数,其归一化效果更强
那么他的作用就是避免某些神经元数值过大,使模型对某些特征产生特别强的依赖
这种操作似乎并不少见,像dropout其实也是在做这件事
就是说我们要避免模型对某一些特征产生依赖,尽可能让模型的结果由全特征推出
只不过,在后来的VGGnet, 通过实验证明,LRN层没有作用,徒增内存消耗和算力消耗罢了
重叠池化:overlap pooling
后来也证明重叠池化没什么用
alexnet的参数量特别大,一旦数据集的规模不够,就很有可能无法驱动这么大的模型,这也是现在大模型存在的通用问题,数据集太小
那么alexnet采用数据增强来避免过拟合
这里提到一个没预料到的点:数据增强并非提前做好,而是在程序运行过程中生成,保存在内存和显存上,这就要好好推算临界点,生成的图像一张大概是0.15MB
dropout层
通过随机静默某些神经元,就会使得每个神经元都有机会和其他神经元协同配合,总体上还是为了让模型的输出依赖的是全部特征
关于论文的解读
综述中提到,5层CNN+3层FC是效果很好的,尤其是CNN,移除任何一层都会导致网络效果变差
imagenet这个数据集拥有超过1500W张图片,22000个类别
平时训练使用的是imagenet的一个子集,包含1000个类别,每个类别大约1000张图片,其中数据集的划分:12000张训练图片,5000张验证图片,150000张测试图片
ReLU激活函数
为线性网络增加了非线性因素,像relu在x>0的区域,y = x.把这个函数带入FC的计算公式,可以看到他就带方了,FC层数越深,就可以拟合更为复杂的非线性图形
relu比sigmoid激活函数能够更快收敛loss
之前可能觉得说好像只有learnning rate可以做这个加速,先设大点,再设小点
因此可能就需要问激活函数有哪些作用??
主要作用是为线性模型加入非线性因素,其实就是以一种更简单的方式把直线变成了曲线
并没有明确说明激活函数有加速训练的作用。但是loss function可以看作是关于激活函数的复合函数。那么在收敛loss function的过程中是需要对loss function求导的,也就意味着会对激活函数求导。要让loss function收敛得更快,就意味着梯度要大。
由这一点出发,relu激活函数可以加速训练的道理似乎就清晰了很多。
咱看看一般对激活函数的要求:
1.可微:尤其是loss function的收敛是基于梯度的时候,这个条件是必须的
2.单调:不一定遵循。但是相对的会使分类器的结构变得简单
3.输出值的范围:这个概念还会涉及到之后说的饱和激活函数。当激活函数的输出值是有限的时候,基于梯度的优化方法会比较稳定。典型的像sigmoid激活函数,他也是一个饱和激活函数,需要在训练一段时间后进行归一化,将输出值归一化到激活函数比较敏感的区域
当激活函数的输出值是无限的时候,模型的训练会更加高效,他也不需要进行归一化。比如说relu激活函数
因为relu能够更好地避免loss function的梯度消失问题,sigmoid慢很可能是因为在梯度下降过程中出现反复横跳的问题,也就是梯度弥散
包括像后面的leak relu, x > 0, y = x; x < 0, y = 0.1x
之前我们已经知道,网络不是训练一个样本迭代一次,而是迭代一个batchsize大小的样本才迭代一次,我们在做YOLO的配置时,把batchsize设为多大是要计算的。具体的大小跟网络参数的多少有关
看来还是要搞一下BP,才知道哪些参数要存起来
LRN:局部响应归一化
这里提到了饱和激活函数
何谓饱和?对于一元函数,当自变量趋近于无穷时,函数的导数趋近于0,则称函数在此方向上饱和。只有在两个方向上都饱和的激活函数才能被成为饱和激活函数。典型的就是sigmoid
这里子豪兄提到一般只有对那种采用饱和激活函数的网络才使用归一化,来使输入尽可能的分布在梯度比较大的区域??这句话怎么理解??
神经网络在训练的时候随着网络层数的加深,激活函数的输入值的整体分布逐渐往激活函数的取值区间上下限靠近,从而导致在BP时低层的神经网络的梯度消失。而BatchNormalization的作用是通过规范化的手段,将越来越偏的分布拉回到标准化的分布,使得激活函数的输入值落在激活函数对输入比较敏感的区域,从而使梯度变大,加快学习收敛速度,避免梯度消失的问题
那么对于像relu这样的非饱和激活函数就不存在这个问题,因此一般也就不太需要将中间值拉回到梯度比较大的区域