最近放假好空虚,而且什么也学不进去呜呜呜 o (╥﹏╥) o

看到了一个很有趣的知乎问题:

为什么传统的非线性优化需要一个很好的初值才能 work,而神经网络却不需要呢? - 知乎

就像 数值稳定性和模型初始化 - 动手学深度学习 中说的那样。此前我以为初始化策略是不重要的。但是实际上初始化对于保持模型稳定性有着重要影响。嗯,我还是直接摘录这一段比较好:

Until now, we took the initialization scheme for granted, glossing over the details of how these choices are made. You might have even gotten the impression that these choices are not especially important. On the contrary, the choice of initialization scheme plays a significant role in neural network learning, and it can be crucial for maintaining numerical stability. Moreover, these choices can be tied up in interesting ways with the choice of the nonlinear activation function. Which function we choose and how we initialize parameters can determine how quickly our optimization algorithm converges.

到目前为止,我们认为初始化方案是理所当然的,忽略了如何做出这些选择的细节。你甚至可能会觉得这些选择并不是特别重要。相反,初始化方案的选择在神经网络学习中起着重要的作用,对于保持数值稳定性至关重要。此外,这些选择可以以有趣的方式与非线性激活函数的选择联系起来。选择哪个函数以及如何初始化参数决定了优化算法的收敛速度。

然后发现了几种常见的初始化方法,已经有很好的介绍了,但是还是需要自己写一下来总结。主要的参考资料是:

深度学习:Xavier and Kaiming Initialization - 姜雪飞的文章 - 知乎

既然如此,那就用规范化的语言先说说数值稳定性的问题吧。那么首先要规范化我们讨论的框架。嗯,就是 MLP.

# MLP 训练的数值稳定性 —— 梯度消失与梯度爆炸

首先,一个多层感知机 (Multilayer Perceptrons, MLP) 是一个 LL 层的线性变换,输入为 x\bm{x}, 输出为 o\bm{o}, 输入和输出的维度不重要。第 ll 层的变换 flf_l 通过一个权重矩阵 W(l)\bm{W}^{(l)} 进行参数化,然后每一层就可以表示为

h(l)=fl(h(l1))=W(l)h(l1).\bm{h}^{(l)} = f_l(\bm{h}^{(l-1)}) = \bm{W}^{(l)} \bm{h}^{(l-1)}.

总的 MLP 就可以表示为

o=h(L)=fLf1(x).\bm{o} = \bm{h}^{(L)} = f_L \circ \cdots \circ f_1(\bm{x}).

这样,输出对某一层 W(l)\bm{W}^{(l)} 的梯度就是

W(l)o=h(L1)h(L)h(l)h(l+1)W(l)h(l).\partial_{W^{(l)}} \bm{o} = \partial_{\bm{h}^{(L-1)}} \bm{h}^{(L)} \cdots \partial_{\bm{h}^{(l)}} \bm{h}^{(l+1)} \partial_{\bm{W}^{(l)}} \bm{h}^{(l)}.

一般情况下,为了避免概率连乘带来的数值下溢 (numerical underflow), 一般会将上式取对数计算。

矩阵对数实际上是用其幂级数展开计算的。也就是

log(A)=k=1(1)k1k(A1)k.\log(\bm{A}) = \sum_{k=1}^\infty \frac{(-1)^{k-1}}{k} (\bm{A} - 1)^k.

所以,随机初始化时如果不加以限制,则矩阵的特征值可能极大或极小,从而计算时仍然可能出现溢出问题。

# 常见的模型初始化策略

常见的模型初始化策略包括:

  1. Constant Initialization
  2. Random Initialization
  3. Xaiver Initialization
  4. Kaiming Initialization

# Constant Initialization

即将模型的参数都初始化为相同的参数,这样导致模型在梯度下降和反向更新的过程中出现某种对称性,从而降低了神经网络的灵活性(表达能力)。

需要思考的是,这里使用常数初始化,在遇到非对称的数据时,更新后的参数一定是非对称的。因此,这里出现的对称性必定意味着参数的冗余。

Oh, 这样定性而非定量分析问题实在是太愚蠢了。

# Random Initialization

初始化过程中加入随机化,但是随机化的超参(例如高斯分布的均值和方差,平均分布的起止点)难以确定。

另外,感觉这里的随机化和算法竞赛的随机化还不那么一样。算法竞赛的随机化就是用来避免毒瘤数据,因此有极大的概率成功。而这里成功的概率似乎并不高?

如果忘了什么是随机化,就来回顾一下 快速排序 - OI Wiki 吧。嗯,虽然这里也没有提到随机化技巧,但是想必聪明的你已经回忆起了这些东西。

如果还没有想起来,那么其实是有 随机化技巧 - OI Wiki 的专题的。这个想法其实用起来还是很多样化的,但是证明起来有时候感觉比较玄学。

# Xaiver Initialization

Xaiver 初始化仍然是随机初始化,但是通过计算信号强度不变这一策略确定了随机化超参。

在 Xaiver 初始化中,计算信号强度采用方差度量。假设一个单层全连接神经网络为 y=Wx+b\bm{y} = \bm{W}\bm{x} + \bm{b}, 其中 xRm,y,bRn\bm{x} \in \mathbb{R}^m, \bm{y}, \bm{b} \in \mathbb{R}^n, 则信号强度不变可以表示为

Var(Yi)=Var(Xj),\text{Var}(Y_i) = \text{Var}(X_j),

且满足假设

  1. W,X,BW, X, B 是相互独立的随机向量 / 矩阵。
  2. i,j\forall i,j, WijW_{ij} i.i.d. 且 E(Wij)=0\mathbb{E}(W_ij)=0.
  3. i\forall i, BiB_{i} i.i.d. 且 E(Bi)=0\mathbb{E}(B_i)=0.
  4. j\forall j, XjX_{j} i.i.d. 且 E(Xj)=0\mathbb{E}(X_j)=0.

其实就是均值为零,独立同分布而已,没什么特殊的。

然后就可以依靠上述假设计算方差关系了。省略简单的计算步骤得到:

  1. 前向传播过程中,由于 Y=WX+BY = WX + B, 可以得到 Var(Yi)=mVar(Wij)Var(Xj)\text{Var}(Y_i) = m\text{Var}(W_{ij})\text{Var}(X_j). 此时 Var(Yi)=Var(Xj)\text{Var}(Y_i) = \text{Var}(X_j), 则 Var(Wij)=1m\text{Var}(W_{ij}) = \frac{1}{m}.
  2. 反向传播过程中,由于 ΔX=WΔY\Delta X = W ^\top \Delta Y, 则 Var(ΔXj)=nVar(Wij)Var(ΔYi)\text{Var}(\Delta X_j) = n\text{Var}(W_{ij})\text{Var}(\Delta Y_i). 此时 Var(ΔXj)=Var(ΔYi)\text{Var}(\Delta X_j) = \text{Var}(\Delta Y_i), 则 Var(Wij)=1n\text{Var}(W_{ij}) = \frac{1}{n}.

所以两者不可能相等,解决办法就是... 取一个调和平均值(眼前一黑)。所以

Var(Wij)=2m+n.\text{Var}(W_{ij}) = \frac{2}{m+n}.

# Kaiming Initialization

Kaiming 初始化就是在 Xaiver 初始化的基础上,进一步考虑激活函数得到的。

想法也比较基础,抽空再写好咯。

# References

  • 为什么传统的非线性优化需要一个很好的初值才能 work,而神经网络却不需要呢? - 知乎
  • Numerical Stability and Initialization - 动手学 DL 英文版
  • 深度学习:Xavier and Kaiming Initialization - 姜雪飞的文章 - 知乎
  • Kaiming He Initialization - Shaurya Goel - Medium
  • 快速排序 - OI Wiki
  • 随机化技巧 - OI Wiki