数值稳定性和模型初始化
到目前为止,我们实现的每个模型都是根据某个预先指定的分布来初始化模型的参数。直到现在,我们认为初始化方案是理所当然的,忽略了如何做出这些选择的细节。你甚至可能会觉得,初始化方案的选择并不是特别重要。相反,初始化方案的选择在神经网络学习中起着非常重要的作用,它对保持数值稳定性至关重要。
此外,这些选择可以与非线性激活函数的选择以有趣的方式结合在一起。我们选择哪个函数以及如何初始化参数可以决定优化算法收敛的速度有多快。糟糕选择可能会导致我们在训练时遇到梯度爆炸或梯度消失。在本节中,我们将更详细地探讨这些主题,并讨论一些有用的启发式方法。你会发现这些启发式方法在你的整个深度学习生涯中都很有用。
数值稳定性
神经网络的梯度:
-
考虑如下的 d 层神经网络
h(l)=fl(h(l−1)) 因此 o=fL∘…∘f1(x)
-
如果所有隐藏变量和输入都是向量,我们可以将o关于任何一组参数W(l)的梯度写为下式:
∂W(l)o=M(L)=def∂h(L−1)h(L)⋅…⋅M(l+1)=def∂h(l)h(l+1)v(l)=def∂W(l)h(l).
可以看见,我们做了很多的矩阵乘法,大量的矩阵乘法带来数值稳定性的常见两个问题:梯度爆炸和梯度消失。
梯度爆炸
参数更新过大,破坏了模型的稳定收敛。
e.g. 使用 ReLU 函数作为激活函数。
问题:
- 值超出值域,对于16 位浮点数尤为严重
- 对学习率敏感
- 学习率过大->大参数值->更大的梯度
- 学习率太小->训练没有进展
- 可能要在训练过程中不断调整学习率
梯度消失
参数更新过小,每次更新时几乎不会移动,导致无法学习。
e.g. 使用 sigmoid 函数作为激活函数
问题:
- 梯度值变为 0,对于16 位浮点数尤为严重
- 不管如何选择学习率,训练都没有进展
- 对底部层尤为严重,仅仅顶部层训练的较好,无法让神经网络更深
总结
- 当数值过大或者过小时会导致数值问题
- 常发生在深度模型中,因为其会对 n 个数累乘
如何让训练更加稳定
目标:让梯度值在合理的范围内。
权重初始化
默认初始化
在前面的部分中,我们使用正态分布来初始化权重值。如果我们不指定初始化方法,框架将使用默认的随机初始化方法,对于中等规模的问题,这种方法通常很有效。
Xavier初始化
关键点:
- 将每层的输出和梯度都看作随机变量
- 让他们的均值和方差都保持一致
让我们看看某些没有非线性的全连接层输出(例如,隐藏变量)oi的尺度分布。
对于该层nin输入xj及其相关权重wij,输出由下式给出
oi=j=1∑ninwijxj.
权重wij都是从同一分布中独立抽取的。此外,让我们假设该分布具有零均值和方差σ2。请注意,这并不意味着分布必须是高斯的,只是均值和方差需要存在。现在,让我们假设层xj的输入也具有零均值和方差γ2,并且它们独立于wij并且彼此独立。在这种情况下,我们可以按如下方式计算oi的平均值和方差:
E[oi]Var[oi]=j=1∑ninE[wijxj]=j=1∑ninE[wij]E[xj]=0,=E[oi2]−(E[oi])2=j=1∑ninE[wij2xj2]−0=j=1∑ninE[wij2]E[xj2]=ninσ2γ2.
保持方差不变的一种方法是设置ninσ2=1。现在考虑反向传播过程,我们面临着类似的问题,尽管梯度是从更靠近输出的层传播的。使用与正向传播相同的推理,我们可以看到,除非noutσ2=1,否则梯度的方差可能会增大,其中nout是该层的输出的数量。这使我们进退两难:我们不可能同时满足这两个条件。相反,我们只需满足:
21(nin+nout)σ2=1 或等价于 σ=nin+nout2.
通常,Xavier初始化从均值为零,方差σ2=nin+nout2的高斯分布中采样权重。我们也可以利用Xavier的直觉来选择从均匀分布中抽取权重时的方差。注意均匀分布U(−a,a)的方差为3a2。将3a2代入到σ2的条件中,将得到初始化的建议:
U(−nin+nout6,nin+nout6).
尽管上述数学推理中,不存在非线性的假设在神经网络中很容易被违反,但Xavier初始化方法在实践中被证明是有效的。
检查常用激活函数
线性的激活函数若想满足 Xavier初始化,则激活函数就必须为 σ(x)=x
可以对常用的激活函数做泰勒展开,看其是否与 f(x)=x 低阶近似。
- sigmoid(x)=1/2+x/4−x3/48+O(x5)
- tanh(x)=0+x−x3/3+O(x5)
- relu(x)=0+x for x≥0
可以看出 tanh 和 relu 函数可以低阶近似于 f(x)=x ,但是 sigmoid 函数需要调整:
4×sigmoid(x)−2
总结
- 合理的权重初始值和激活函数的选取可以提升数值的稳定性