动手学深度学习 3.15 数值稳定性和模型初始化
前言
从零开始学习ai文章系列计划是个人在《动手学深度学习》和《磨菇书》两本书的学习中的个人笔记,文章也会以课本中的章节分开,即每个章节一片笔记。我会尽量的把主要内容以及遇到的难点进行记录与解决,如果哪里有错误的欢迎指正。或者不清晰的可以直接查看原文部分。
《动手学深度学习》原文(课本):https://tangshusen.me/Dive-into-DL-PyTorch/#/
《动手学深度学习》代码:https://github.com/ShusenTang/Dive-into-DL-PyTorch
(由于有时候公式太多,可能会直接贴图片)
1. 衰减和爆炸
深度模型有关数值稳定性的典型问题是衰减(vanishing)和爆炸(explosion)。
当神经网络的层数较多时,模型的数值稳定性容易变差。假设一个层数为\(L\) 的多层感知机的第 \(l\) 层 \(H^{(l)}\)的权重参数为\(W^{(l)}\),输出层\(H^{(L)}\) 的权重参数为\(W^{(L)}\) 。
为了便于讨论,不考虑偏差参数,且设所有隐藏层的激活函数为恒等映射(identity mapping)\(ϕ(x)=x\) 。
给定输入\(X\) ,多层感知机的第\(l\) 层的输出 \(H^{(l)}=XW^{(1)}W^{(2)}…W^{(l)}\)。此时,如果层数\(l\) 较大,\(H^{(l)}\) 的计算可能会出现衰减或爆炸。
举个例子,假设输入和所有层的权重参数都是标量,如权重参数为 \(0.2\) 和 \(5\),多层感知机的第\(30\)层输出为输入\(X\) 分别与 \(0.2^{30}≈1×10^{−21}\)(衰减)和 \(5^{30}≈9×10^{20}\)(爆炸)的乘积。
随着内容的不断深入,我们会在后面的章节进一步介绍深度学习的数值稳定性问题以及解决方法。
2. 随机初始化模型参数
在神经网络中,通常需要随机初始化模型参数。下面我们来解释这样做的原因。为了方便解释,假设输出层只保留一个输出单元 \(o_1\),且隐藏层使用相同的激活函数。
如果将每个隐藏单元的参数都初始化为相等的值,那么在正向传播时每个隐藏单元将根据相同的输入计算出相同的值,并传递至输出层。在反向传播中,每个隐藏单元的参数梯度值相等。因此,这些参数在使用基于梯度的优化算法迭代后值依然相等。之后的迭代也是如此。
在这种情况下,无论隐藏单元有多少,隐藏层本质上只有1个隐藏单元在发挥作用。因此,正如在前面的实验中所做的那样,我们通常将神经网络的模型参数,特别是权重参数,进行随机初始化。
2.1 PyTorch的默认随机初始化
在3.3节(线性回归的简洁实现)中,我们 torch.nn.init.normal_() 使模型net的权重参数采用正态分布的随机初始化方式。
不过,PyTorch中nn.Module的模块参数都采取了较为合理的初始化策略(不同类型的layer具体采样的哪一种初始化方法的可参考源代码),因此一般不用我们考虑。