深度学习-权重初始化

  • 为什么要权重初始化
  • Xavier初始化的推导

权重初始化

In order to avoid neurons becoming too correlated and ending up in poor local minimize, it is often helpful to randomly initialize parameters. 为了避免神经元高度相关和局部最优化,常常需要采用随机初始化权重参数,最常用的就是Xavier initiazation.

为什么我们需要权重初始化?

如果权重参数很小的话,输入信号在前向传播过程中会不断减小(在0到1之间),那么每一层layer都会使得输入变小。同样的道理,如果权重参数过大的话,也会造成前向输入越来越大。这样会带来什么样的后果呢?以激活函数sogmoid为例:

如果以sigmoid为激活函数,我们可以发现,在每一层layer输出 \(W^Tx\) ,也就是激活函数的输入,其值越接近于0的时候,函数近似于线性的,因而就失去了非线性的性质。这种情况下,我们就失去了多层神经网络的优势了。

如果初始权重过大,在前向传播的过程中,输入数据的方差variance会增长很快。怎么理解这句话?

以one layer为例,假设输入是 \(x\in R^{1000}\), 线性输出是 \(y\in R^{100}\). \[y_j=w_{j,1}x_1+w_{j,2}x_2+...+w_{(j,1000)}x_{1000}\] x可以看作是1000维的正态分布,每一维 \(x_i\sim N(0,1)\), 如果 \(w_j\)值很大,比如 \(w_j=[100,100,...,100]\),那么输出神经元 \(y_i\) 的方差就是10000,所以就会很大,均值还是0.

那么激活函数的输入很有可能是一个远小于-1或远大于1的数,通过激活函数所得的值会非常接近于0或者1,也就是隐藏层神经元处于饱和状态(saturated),其梯度也就接近于0了。

所以初始化权重狠狠狠重要。那么应该如何初始化呢,也就是需要保证经过每一层layer,要保证线性输出的方差保持不变。这样就可以避免数值溢出,或是梯度消失。

Xavier Initialization

我们的目的是保持线性输出的方差不变。

以线性输出的一个神经元为例,也就是y的一个维度:

\[y_j=w_{j,1}x_1+w_{j,2}x_2+...+w_{j,N} x_N+b\]

其方差:

\[var(y_j) = var(w_{j,1}x_1+w_{j,2}x_2+...+w_{j,N} x_N+b)\]

其中每一项根据方差公式可得:

\[var(w_{j,i}x_i) = E(x_i)^2var(w_{j,i}) + E(w_{j,i})^2var(xi) + var(w_{j,i})var(x_i)\]

来自维基百科: https://en.wikipedia.org/wiki/Variance

其中我们假设输入和权重都是来自于均值为0的正态分布。

\[var(w_{j,i}x_i)=var(w_{j,i})var(x_i)\]

其中b是常量,那么:

\[var(y_j) = var(w_{j,1})var(x_1) + ... + var(w_{j,N})var(x_N)\]

因为 \(x_1,x_2,..,x_N\) 都是相同的分布,\(W_{j,i}\) 也是,那么就有:

\[var(y_j) = N * var(w{j,i}) * var(x_i)\]

可以看到,如果输入神经元数目N很大,参数权重W的值也很大的话,会造成线性输出的值的方差很大。 我们需要保证 \(y_j\) 的方差和 \(x_j\) 的方差一样,所以:

\[N*var(W_{j,i})=1\] \[var(W_{j,i})=1/N\]

There we go! 这样我们就得到了Xavier initialization的初始化公式,也就是说参数权重初始化为均值为0,方差为 1/N 的高斯分布,其中N表示当前层输入神经元的个数。在caffe中就是这样实现的。

更多初始化方式

Understanding the difficulty of training deep feedforward neural networks 在这篇paper中提出 \[var(w)=2/(N_{in}+N_{out})\]

Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification 针对一种专门的初始化方式,使得 \(var(w)=2.0/N\), 在实际工程中通常使用这种方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
### 正态分布
w = np.random.randn(N) * sqrt(2.0/N)
### 均匀分布
def _xavier_initializer(shape, **kwargs):
"""
Args:
shape: Tuple or 1-d array that species dimensions of requested tensor.
Returns:
out: tf.Tensor of specified shape sampled from Xavier distribution.
"""
epsilon = np.sqrt(6/np.sum(shape))
out = tf.Variable(tf.random_uniform(shape=shape, minval=-epsilon, maxval=epsilon))
return out

均匀分布[a,b]的方差:\(\dfrac{(b-a)^2}{12}\)

参考资料: