Pytorch Note23 参数初始化

Posted Real&Love

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch Note23 参数初始化相关的知识,希望对你有一定的参考价值。

Pytorch Note23 参数初始化


全部笔记的汇总贴: Pytorch Note 快乐星球

除了数据的预处理外,在进入网络训练之前,我们还需要作参数的预处理。

参数初始化对模型具有较大的影响,不同的初始化方式可能会导致截然不同的结果,所幸的是很多深度学习的先驱们已经帮我们探索了各种各样的初始化方式,所以我们只需要学会如何对模型的参数进行初始化的赋值即可。

PyTorch 的初始化方式并没有那么显然,如果你使用最原始的方式创建模型,那么你需要定义模型中的所有参数,当然这样你可以非常方便地定义每个变量的初始化方式,但是对于复杂的模型,这并不容易,而且我们推崇使用 Sequential 和 Module 来定义模型,所以这个时候我们就需要知道如何来自定义初始化方式

全0初始化

其实最简单的就是我们可以将参数全部初始化为0

但是实际上我们是不应该采用这一种策略的。首先,我们并不知道训练之后的网络最后权重更新的是多少,但是知道数据在进入网络之前经过了合适的预处理,所以我们可以假设最后的权重有一半是正的,一半是负的,所以将参数全部初始化为0似乎是一个非常好的选择。但这是不对的,因为如果神经网络中每个权重都被初始化成相同的值,那么每个神经元就会计算出相同的结果,在反向传播的时候也会计算出相同的梯度,最后导致所有权重都会有相同的更新。换句话说,如果每个权重都被初始化成相同的值,那么权重之间失去了不对称性。

随机初始化

目前知道我们希望权重初始化的时候能够尽量靠近0,但是不能全都等于0,所以可以初始化权重为一些靠近0的随机数,通过这个方式可以打破对称性。这里面的核心想法就是神经元最开始都是随机的、唯一的,所以在更新的时候也是作为独立的部分,最后一起合成在神经网络当中。

一般的随机化策略有高斯随机化均匀随机化等,需要注意的是并不是越小的随机化产生的结果越好,因为权重初始化越小,反向传播中关于权重的梯度也越小,因为梯度与参数的大小是成比例的,所以这会极大地减弱梯度流的信号,成为神经网络训练中的一个隐患。

这样还有一个问题就是网络输出分布的方差会随着输入维度的增加而增大。

稀疏初始化

另外一种初始化的方法就是稀疏初始化,将权重全部初始化为0,然后为了打破对称性在里面随机挑选一些参数附上一些随机值。这种方法的好处是参数占用的内存较少,因为里面有较多的0,但是实际中使用较少。

初始化偏置(Bias)

对于偏置(bias),通常是初始化为0,因为权重已经打破了对称性,所以使用0来初始化是最简单的

批标准化(Batch Normalization)

最近兴起的一项技术叫做批标准化,它的核心想法就是标准化这个过程是可微的,减少了很多不合理初始化的问题,所以我们可以将标准化过程应用到神经网络的每一层中做前向传播和反向传播,通常批标准化应用在全连接层后面、非线性层前面。

实际中批标准化已经变成了神经网络中的一个标准技术,特别是在卷积神经网络中,它对于很坏的初始化有很强的鲁棒性,同时还可以加快网络的收敛速度。另外,批标准化还可以理解为在网络的每一层前面都会做数据的预处理。

torch.nn.init

有一种非常流行的初始化方式叫 Xavier,方法来源于 2010 年的一篇论文 Understanding the difficulty of training deep feedforward neural networks,其通过数学的推到,证明了这种初始化方式可以使得每一层的输出方差是尽可能相等的,有兴趣的同学可以去看看论文

我们给出这种初始化的公式
w   ∼   U n i f o r m [ − 6 n j + n j + 1 , 6 n j + n j + 1 ] w\\ \\sim \\ Uniform[- \\frac{\\sqrt{6}}{\\sqrt{n_j + n_{j+1}}}, \\frac{\\sqrt{6}}{\\sqrt{n_j + n_{j+1}}}] w  Uniform[nj+nj+1 6 ,nj+nj+1 6 ]

其中 n j n_j nj n j + 1 n_{j+1} nj+1 表示该层的输入和输出数目,所以请尝试实现以下这种初始化方式

因为 PyTorch 灵活的特性,我们可以直接对 Tensor 进行操作从而初始化,PyTorch 也提供了初始化的函数帮助我们快速初始化,就是 torch.nn.init,其操作层面仍然在 Tensor 上,下面我们举例说明

from torch.nn import init
init.xavier_uniform(net1[0].weight) # 这就是上面我们讲过的 Xavier 初始化方法,PyTorch 直接内置了其实现

torch.nn.init 为我们提供了更多的内置初始化方式,避免了我们重复去实现一些相同的操作

以上是关于Pytorch Note23 参数初始化的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch Note48 DCGAN生成人脸

Pytorch Note 快乐星球

Pytorch Note13 反向传播算法

Pytorch Note21 优化算法对比

Pytorch Note10 多项式回归

Pytorch Note44 变分自动编码器(VAE)