Lecture6的内容比较多,稍微复杂一点,但是在实际操作中都是非常有用的知识点。
结合视频课件还有课堂笔记可以比较好的理解这章的内容,我写这篇文章是为了梳理一下自己的理解,也方便自己以后回顾。
目录
Activation Functions
Data Preprocessing
Weight Initialization
Batch Normalization
Babysitting the Learning Process
Hyperparameter Optimization
Activation Functions(激活函数)
Sigmoid
数学公式:
图形:
优点:可以将数据挤压到(0,1)的输出,具有比较好的激活性
缺点:
sigmoid函数饱和使梯度消失。在输入值比较大或者比较小的情况下sigmoid的导数使趋近于0,使得w梯度消失,从而不能有效的进行梯度下降。所以我们必须小心的初始化w,防止输入的值过大或者过小。
sigmoid函数输出不是以0为中心的。会导致梯度下降时以z字形下降,效率不高。
分析一下为何函数输出不是以0为中心会导致梯度下降效率降低。
假设,表示loss函数,,那么可以得到
,
我们知道的值在0到1之间,所以肯定大于0,对于而言是常数,所以如果都为正数(对于sigmoid而言计算出来的下一层的输入都为正数,就是非0为中心的输出),那么必定同为正数或者负数。
假设对这种情况下,我们的最优解是需要增加,需要减少,但是是同符号的,所以必定会以一种类似z的路径下降。
exp的计算消耗稍微有点大。这个是很小的问题,因为卷积运算本身计算消耗也是非常大的。
tanh
数学公式:
图形:
优点:将数据压缩在了(-1,1)之间,输出是以0为中心
缺点:当输入很大或者很小的时候梯度会消失,exp的计算消耗。
ReLU
数学公式:
图形:
优点:1.计算简单,消耗小。2.收敛速度快。3.梯度不会饱和
缺点:1.不是以0为中心的输出。2.在训练中小于0的数据会”死掉“。
如果输入数据小于了0,那么这部分数据会死掉也不能再被激活,如果学习率设置的太高可能会导致40%的神经元都死掉。小心的设置学习率可以改善这个问题。
Leaky ReLU
数学公式:,是超参数,可以取值为0.1或者0.01之类。
图形:
优点:相对ReLU,多了一个优点,不会有神经元死掉。
还有一个PReLU,就是作为参数来学习,而不是像Leaky ReLU一样作为超参数来预设。
ELU
数学公式:
图形:
优点:1.所有ReLU的优点。2.类似于0中心化。3.相对Leaky ReLU负数区域的梯度消失前增加了一个鲁棒的干扰
缺点:1.计算有指数计算
Maxout ”Neuron“
数学公式:
优点:1.线性计算。2.不会梯度消失。3.神经元不会死掉。
缺点:参数的数量会double
总结
1.如果使用ReLU,需要小心的设置学习率
2.可以试试Leaky ReLU/Maxout/ELU
3.如果尝试tanh不要期待太好
4.不要用sigmoid
数据处理
均值减法
减去数据的均值,相当于把数据云移到以原点为中心的位置。对于图片而言可以对RGB分别求出均值,然后用RGB分别减去对应的均值。如果要归一化还可以减去数据的标准差。代码实现方式可以从下面的图片中看到。
PCA和白化
常见的数据预处理的方式,但是在图像中使用的很少。下面的图片中可以看到PCA处理后的数据云(2)和白化处理后的数据云(3)。
总结
对图像处理而言一般只需要中心化即可,一般不做其他的操作。
但是需要注意的是,我们的操作步骤应该是选对数据集分出train/val/test,然后通过训练集计算出RGB的mean,在对train/val/test这些数据集都减去这个mean的值。
Weights初始化
不应该全0初始化。如果我们对w全部初始化为0,就会陷入网络对称化的问题,使得每一层的输入都相同,并且反向传播的导数都相同,这样更新也相同,如果有n个神经元就相当于缩减成了1个神经元。
下面举个例子来说明。
有一个两层的神经网络,w11,w12,w13是与x1,x2,x3分别相乘输出是a1,w21,w22,w23是与x1,x2,x3分别相乘输出a2。h11,h12是与a1,a2分别相乘输出y。
现在假设x是x1,x2,x3列出来的列向量。w1是将w11,w12,w13列出来的列向量,w2是将w21,w22,w23列出来的列向量。a是a1,a2的列向量,h是h11,h12的列向量。
如果w1=w2,h11=h12会发生什么情况?
,因为,所以
如果,那么,
所以可以推导出,后面的梯度更新也会得到一样的值,最后的效果是相当于我们只有a1或者a2这一个神经元。
可以用小的随机数初始化。代码是:W=np.random.randn(D, H) * 0.01,randn表示随机生成的数据是符合高斯分布的(均值为0,标准差为1的分布),然后与0.01相乘后将数据缩小100倍,就生成了比较小的随机数。为什么最好用比较小的随机数呢?如果W的指都比较大,会使计算出来的结果可能接近一些激活函数的梯度饱和区域,导致梯度下降失去活性。
并不是小数值一定会有好的结果。如果神经网络中权重值很小,那么计算出来的梯度也会很小,这样在很深的网络中也会失去梯度下降的活性。
如果输入的数据量很大,可能与W计算后输出值的分布的方差会增大,因此可以初始化W的时候稍作变化,W=np.random.randn(fan_in, fan_out)/sqrt(fan_in),实验证明这种初始化方式可以提高收敛速度,推导过程参考课程笔记。另外对于ReLU激活函数有一个特殊初始化方式,W=np.random.randn(fan_in, fan_out)/sqrt(2.0/n),如果使用ReLU激活,推荐这种方式进行初始化。这种方式的初始化都叫做Xavier初始化。
偏置bias一般初始化为0.
Batch Normalization
归一化相当于对每一层的数据都进行归一预处理,使数据均值接近0,标准差接近1,为什么说是接近,因为我们会给每一层自我学习的能力带来一点灵活性。
第一个公式将数据归一为均值为0,方差为1,然后给每一层一点自我学习的能力增加了和这两个可以学习的参数,如果为输入数据的标准差,为输入数据的均值,那么就相当于归一化为了高斯分布,但是增加了这两个参数不为标准差和均值时,数据就会稍微不同于高斯分布,这样每一层数据可以稍微调整,拥有自己的特色。
BN一般放在全连接或者卷积运算之后,而在激活函数之前。
好处:
- 促进梯度在网络中的传播
- 允许更高的学习率
- 减少对参数初始化的强依赖
- 有轻微的正则化效果
注意:测试阶段均值和标准差不是由测试的batch计算出来的,而是使用训练时平均均值和标准差。所以代码中我们需要对BN接口指定是training还是test阶段。否则很可能预测的结果非常不准确(在这个细节上吃过亏)
训练步骤
1.预处理数据:X -= np.mean(X, axis=0), X /= np.std(X, axis=0)
2.选择模型:定义神经网络的层数,每一层宽度,激活函数,loss等
3.开始训练:先迭代比较少的次数,对一些超参数做一些调整,比如learning rate等。
超参数的优化
用比较小的epoch来研究超参数对loss下降的影响,然后一点点调整。
所有参数以外的配置都是超参数,需要自己进行调整,比如:网络结构,学习率,正则化方式等。
就像调音师,需要一点一点的调整来达到最好的效果。
总结:
- 激活函数用ReLU
- 输入预处理用减去均值的方式
- 参数初始化使用Xavier
- BN要使用