白话Xavier | 神经网络初始化的工程选择

时间:2022-07-22
本文章向大家介绍白话Xavier | 神经网络初始化的工程选择,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
“Xavier”初始化方法是一种很有效的神经网络初始化方法,方法来源于2010年的一篇论文《Understanding the difficulty of training deep feedforward neural networks》。

论文的链接在这里:https://machinelearning.wustl.edu/mlpapers/paper_files/AISTATS2010_GlorotB10.pdf

PyTorch代码

在介绍论文和理论之前,先讲一下如何使用在PyTorch中使用Xavier初始化:

 def _initialize_weights(self):
        # print(self.modules())
 
        for m in self.modules():
            print(m)
            if isinstance(m, nn.Linear):
                # print(m.weight.data.type())
                # input()
                # m.weight.data.fill_(1.0)
                init.xavier_uniform_(m.weight, gain=1)
                print(m.weight)

通俗讲理论

论文提出的Xavier的主要思想:每一层输出的方差应该尽量相等

前向传播

下面进行推导:每一层的权重应该满足什么条件才能实现这个目标

目前我们需要用到下面方差相关的定理:假设有随机变量x和w,他们都能服从均值为0,方差为

sigma

的分布,两者独立同分布,那么:

w*x

就会服从均值为0,方差为

sigma * sigma

的分布

w*x+w*x

服从均值为0,方差为

2* sigma * sigma

对于上面的内容不了解的可以看下面的推导:

这里用激活函数tanh来做讲解(论文中是用tanh激活函数来讲解的),下图中左图是tanh的形状,右边是tanh的导数的形状:

从上图可以看到,当x处于0附近的时候,导数接近1,因此这就是tanh激活函数的线性区域,也就是在x=0的附近,

tanh(x)approx x

假设我们的所有输入数据满足均值为0,方差为

sigma_x

的分布;参数w满足均值为0,方差为

sigma_w

。假设第一层是卷积层,卷积层的参数为n:

n=channeltimes kernel_h times kernel_w

于是我们可以得到经过卷积层输出的结果:

z=sum^n_i{w_itimes x_i}

这里面忽略偏执b。

因为我们假设输入x和权重w相互独立,所以可以得到输出z的方差:

为了更好的展示,我们把网络层的层号写在变量的上标处:

因此我们也可以得到:

如果这是一个k层的网络(包括卷积层和全链接层),可以得到:

sigma_x^k=n^{k-1}times sigma_x^{k-1} times sigma_w^{k-1}
=n^{k-1}times n^{k-2} times sigma_x^{k-1} times sigma_w^{k-2} times sigma_w^{k-1}

继续展开,可以得到:

sigma_x^k=sigma_x^1 times prod^{k-1}_{i=1}n^i times sigma_w^i

【我们来消化一下】首先为什么卷积层也可以用w*x这样全链接的线性形式呢?其实想一想,x是输入数据,不管是全连接还是图像数据,都可以是服从均值为0,方差为

sigma_x

的分布。为什么均值为0呢? 因为一般图像数据中会进行normalization,将均值置为0.

那么,卷积层的n是通道数乘上卷积核的尺寸,全连接层的n就是一层的神经元的数量。

为什么这里不考虑激活函数呢?其实是考虑了,之前提到的tanh在均值为0的附近,是相当于线性函数

f(x)=x

的,所以上面的推导忽略了激活函数的部分。


我们继续往下走,从上式可以看出,后面的连乘是非常危险的,假设

n_i times sigma_w^i

总是大于1,这意味着,随着层数的越深,数据的方差会越来越大;当然如果小于1的话,层数越深,数值的方差就会越来越小。

回到这个公式:

如果想要达成一开始说的目标:每一层的权重应该满足什么条件才能实现这个目标,那么也就是

sigma_x^2 = sigma_x ^1

,应该满足:

sigma_w^1 = frac{1}{n^1}

推广到任意层:

目前为止,介绍了前向传播的情况。也就是如果要让每一层的数据的方差相等,需要满足:

反向传播

反向传播的原理也是一样的。

假设我们还是k层的网络,然后第k层的梯度是:

frac{partial Loss}{partial x^k}

这里想象一下,每一层的一个数据,会对下一层的n个数据有连接,连接的权重就是

w_i

,这就是视野域。因此第k层的每一个数据反向传播的时候,也会受到k+1层中在视野域内n个数据的梯度的影响,因此可以得到:

frac{partial Loss}{partial x_j^{k}}=sum^n_{i=1}frac{partial Loss}{partial x_i^{k+1}}times w_i^{k}

假设每一层的数据的梯度数据都服从均值为0,方差为

var(frac{partial Loss}{partial x_j^k})

的分布的话,那么可以得到下面的公式:

Var(frac{partial Loss}{partial x_j^{k-1}})=n^{k}times Var(frac{partial Loss}{partial x^{k}}) times sigma_w^{k-1}

【这里是

n^{k-1}

还是

n^{k}

因为这里说的是k-1层的一个数据到底能对k层的多少数据产生影响。我分析了之后发现卷积和全连接层其实有略微的差别。全连接层中,k-1层的一个数据与k层的所有数据都有连接,所以这里是

n^{k}

,如果是卷积层的话,k-1层的一个数据只与k层中的

n^{k-1}

个数据连接,所以应该使用

n^{k-1}

。但是原文论文中似乎仅仅考虑了全连接层,所以这里使用的还是

n^{k}

。如果还是不明白可以画一画全连接的图再思考一下,类似这样的图。


继续往下走,我们假设有k层网络,对上面的公式不断展开,可以得到:

Var(frac{partial Loss}{partial x^1})=Var(frac{partial Loss}{partial x^k}) prod^{k-1}_{i=1}{n^{i+1} sigma_w^i}

同样的连乘,为了让每一层的数据的梯度的方差相等,需要满足:

也就是:

sigma_w^k=frac{1}{n^{k+1}}

与前向传播的形式大致相同。


现在我们为了让正向传播的数据的方差相同反向传播的数据梯度的方差相同,得到了下面两个公式:

为了均衡考虑,所以最终的权重方差应该满足:

论文中依然使用的是均匀分布进行初始化参数,我们假设权重均匀分布初始化的范围为[-a,a],那么这个均匀分布的方差就是:

Var(uniform)=frac{(a+a)^2}{12}=frac{a^2}{3}=sigma_w^k

关于平均分布的均值和方差的推导可以看下面的步骤:


所以呢,我们最后可以得到:

因此,xavier的初始化方法,就是把参数初始化成下面范围内的均匀分布:

参考文章:

  1. https://zhuanlan.zhihu.com/p/220280792
  2. https://zhuanlan.zhihu.com/p/22044472
  3. https://blog.csdn.net/shuzfan/article/details/51338178
  4. https://www.cnblogs.com/hejunlin1992/p/8723816.html
  5. https://blog.csdn.net/CHS007chs/article/details/78133563
  6. https://zhuanlan.zhihu.com/p/27919794