主要记录一下在看卷积神经网络的时候想到的、碰到的种种问题。
首先是在看TensorFlow实战google深度学习框架这本书的时候看到了ResNet——深度残差神经网络的时候,突然想到文件夹里躺着这份论文还没看,然后就放下TS(不得不说这本书写的真的是,,,烂,很多东西都没有给出合理的解释,还要自己查)
然后在看ResNet的过程中,碰到了normalized initialization和intermediate normalization layers这两个东西。前者是参数初始化,使用avg=0,stddev=?的正态分布进行参数初始化的思想。后者提到了一个internal covariate shift这一概念,然后又转向这个概念去查。解释是这样的:
internal covariate shift指的是训练样本和测试样本或者验证样本的分布不一致导致的验证或测试效果不理想。
然后又牵扯出一个概念“白化”。
白化指的是在图像训练中,一般采取将图像作avg=0,stddev=?的分布映射处理,这样可以使训练更快收敛。
于是重点来了,Batch Normal——也就是解决internal covariate shift的方法:在中间隐藏层的输出,也就是下一层的输入作白化处理,再作激活处理,这样解决梯度消失或梯度爆炸的问题。
当然这里提到了一个问题:这样做会导致整个神经网络偏向于线性,使得整个神经网络的表达能力降低(为啥???暂且先放一放,之后思考)。
猜测其原因是因为每个隐藏层在归一化处理之后,其分布都是统一的avg=0,stddev=1。那么对于任何一个激活函数而言,其分布概率相同,每个隐藏层神经元的输出概率也都是同一个分布情况,没有任何分布偏差也就无法通过正向传播得到一些不同的值,也就无法通过逆向传播得到更好的更新参数。
为了防止这个问题,在对单层隐藏层作白化处理之后,再对每个神经元作一个“补正操作”,也就是每个神经元的逆向白化操作,为X` = X * SCALE + SHIFT,此处的SCALE和SHIFT为神经网络自主训练学习到的,也就意味着每个神经元的缩放是不同程度的。
→总结下来就是:先对整体隐藏层缩放(avg=0,stddev=1),再对每个神经元缩放(逆向白化),再做激活函数处理。