1. 归一化的定义

归一化用一句话说就是:把数据经过处理后使之限定在一定的范围内。比如通常限制在区间[0, 1]或者[-1, 1]等等。那么为什么要进行归一化呢?

那么首先要说到一个重要的概念,即奇异样本数据。奇异样本数据的存在会引起训练时间增大,并可能引起无法收敛。

(1)初始化

过初始化的同学会发现,输入数据的范围会影响我们初始化的效果。例如,某个神经元的值为tansig(w1*x1+w2*x2+b),由于tansig函数只有在[-1.7,1.7]的范围才有较好的非线性,所以w1*x1+w2*x2+b的取值范围就要与 [-1.7,1.7]有交集(实际上需要更细腻的条件),这个神经元才能利用到非线性部分。

我们希望初始化的时候,就把每个神经元初始化成有效的状态,所以,需要知道w1*x1+w2*x2+b的取值范围,也就需要知道输入输出数据的范围。

输入数据的范围对初始化的影响是无法避免的,一般讨论初始化方法时,我们都假设它的范围就是[0,1]或者[-1,1],这样讨论起来会方便很多。就这样,若果数据已经归一化的话,能给初始化模块带来更简便,清晰的处理思路。

(2)梯度

以输入-隐层-输出这样的三层BP为例,我们知道对于输入-隐层权值的梯度有2e*w*(1-a^2)*x的形式(e是誤差,w是隐层到输出层的权重,a是隐层神经元的值,x是输入),若果输出层的数量级很大,会引起e的数量级很大,同理,w为了将隐层(数量级为1)映身到输出层,w也会很大,再加上x也很大的话,从梯度公式可以看出,三者相乘,梯度就非常大了。这时会给梯度的更新带来数值问题。

(3)学习率

由(2)中,知道梯度非常大,学习率就必须非常小,因此,学习率(学习率初始值)的选择需要参考输入的范围,不如直接将数据归一化,这样学习率就不必再根据数据范围作调整。

隐层到输出层的权值梯度可以写成 2e*a,而输入层到隐层的权值梯度为 2e *w*(1-a^2)*x ,受 x 和 w 的影响,各个梯度的数量级不相同,因此,它们需要的学习率数量级也就不相同。对w1适合的学习率,可能相对于w2来说会太小,若果使用适合w1的学习率,会导致在w2方向上步进非常慢,会消耗非常多的时间,而使用适合w2的学习率,对w1来说又太大,搜索不到适合w1的解。

如果使用固定学习率,而数据没归一化,则后果可想而知。不过,若果像matlab工具箱一样,使用自适应学习率,学习率的问题会稍稍得到一些缓和。

(4)搜索轨迹

前面已说过,输入范围不同,对应的 w 的有效范围就不同。假设 w1 的范围在 [-10,10],而w2的范围在[-100,100],梯度每次都前进1单位,那么在w1方向上每次相当于前进了 1/20,而在w2上只相当于 1/200!某种意义上来说,在w2上前进的步长更小一些,而w1在搜索过程中会比w2“走”得更快。这样会导致,在搜索过程中更偏向于w1的方向。

下面是网友关于为什么要归一化的一些回答(欢迎补充):

1.避免数值问题。

2.使网络快速的收敛。

3.样本数据的评价标准不一样,需要对其量纲化,统一评价标准

4.bp中常采用sigmoid函数作为转移函数,归一化能够防止净输入绝对值过大引起的神经元输出饱和现象 。

2. 常用归一化方法

常用归一化方法有最大-最小标准化Z-score标准化函数转化等等。

权重初始化

我们已经知道了如何构建神经网络结构,也知道了怎么预处理数据。在我们真正开始训练网络之前,我们必须要知道如何去初始化神经网络的参数。

陷阱: 都初始化为0。

首先介绍一下我们不应该做的事情(即初始化为0)。需要注意的是我们并不知道在训练神经网络中每一个权重最后的值,但是如果进行了恰当的数据归一化后,我们可以有理由认为有一半的权重是正的,另一半是负的。令所有权重都初始化为0这个一个听起来还蛮合理的想法也许是一个我们假设中最好的一个假设了。但结果正确是一个错误(的想法),因为如果神经网络计算出来的输出值都一个样,那么反向传播算法计算出来的梯度值一样,并且参数更新值也一样(w=w−α∗dw)。更一般地说,如果权重初始化为同一个值,网络就不可能不对称(即是对称的)。

初始化为小的随机数

既然不能都初始化为0,那么很自然的我们会想到将权重初始化为非常接近0的小数(正如我们上面所讨论的不能等于0)。将权重初始化为很小的数字是一个普遍的打破网络对称性的解决办法。这个想法是,神经元在一开始都是随机的、独一无二的,所以它们会计算出不同的更新,并将自己整合到整个网络的各个部分。一个权重矩阵的实现可能看起来像W=0.01∗np.random.randn(D,H),其中randn是从均值为0的单位标准高斯分布进行取样。通过这个公式(函数),每个神经元的权重向量初始化为一个从多维高斯分布取样的随机向量,所以神经元在输入空间中指向随机的方向(so the neurons point in random direction in the input space.应该是指输入空间对于随机方向有影响)。其实也可以从均匀分布中来随机选取小数,但是在实际操作中看起来似乎对最后的表现并没有太大的影响。

警告:并不是数字越小就会表现的越好。比如,如果一个神经网络层的权重非常小,那么在反向传播算法就会计算出很小的梯度(因为梯度gradient是与权重成正比的)。在网络不断的反向传播过程中将极大地减少“梯度信号”,并可能成为深层网络的一个需要注意的问题。

用1/sqrt(n)校准方差

上述建议的一个问题是,随机初始化神经元的输出的分布有一个随输入量增加而变化的方差。结果证明,我们可以通过将其权重向量按其输入的平方根(即输入的数量)进行缩放,从而将每个神经元的输出的方差标准化到1。也就是说推荐的启发式方法(heuristic)是将每个神经元的权重向量按下面的方法进行初始化:w=np.random.randn(n)/sqrt(n),其中nn表示输入的数量。这保证了网络中所有的神经元最初的输出分布大致相同,并在经验上提高了收敛速度。

w=np.random.randn(n)/sqrt(n)推导过程大致如下:

稀疏初始化(Sparse Initialazation)

另一种解决未校准方差问题的方法是把所有的权重矩阵都设为零,但是为了打破对称性,每个神经元都是随机连接地(从如上面所介绍的一个小的高斯分布中抽取权重)到它下面的一个固定数量的神经元。一个典型的神经元连接的数目可能是小到10个。

初始化偏差

将偏差初始化为零是可能的,也是很常见的,因为非对称性破坏是由权重的小随机数导致的。因为ReLU具有非线性特点,所以有些人喜欢使用将所有的偏差设定为小的常数值如0.01,因为这样可以确保所有的ReLU单元在最开始就激活触发(fire)并因此能够获得和传播一些梯度值。然而,这是否能够提供持续的改善还不太清楚(实际上一些结果表明这样做反而使得性能更加糟糕),所以更通常的做法是简单地将偏差初始化为0.

实际操作

通常的建议是使用ReLU单元以及 He等人 推荐的公式w=np.random.randn(n)∗sqrt(2.0/n)

批量标准化

loffe和Ioffe最近开发的一项技术,称为“Batch Normalization”,在训练开始的时候,通过显式地迫使网络上的激活函数让整个网络上采用高斯分布来初始化神经网络,从而缓解了许多头痛的问题。(A recently developed technique by Ioffe and Szegedy called Batch Normalization alleviates a lot of headaches with properly initializing neural networks by explicitly forcing the activations throughout a network to take on a unit gaussian distribution at the beginning of the training.)。通过核心观察证明这是可能的,因为标准化是一个简单的可微分的操作(The core observation is that this is possible because normalization is a simple differentiable operation.)。在实际操作中,运用这项技术相当于在全连接层(或者卷积层,我们很快将会看到)后面嵌入BatchNorm层,并嵌在非线性(层)前。这里我们不会展开来讲解这项技术,因为它已经在上面那提供链接的论文中详细的介绍了,但是请注意,在神经网络中使用批量标准化已经成为一种非常常见的做法。在实践中,使用批量标准化的网络对糟糕的初始化更加健壮。还要需要提到的是,批量标准化可以解释为在网络的每一层进行预处理,但它以可微分的方式整合到网络中。

文章1:blog.csdn.net/dbat2015/

文章2:cnblogs.com/marsggbo/p/

外文解答文章:cs231n.github.io/neural