偏差 & 方差
要理解模型的泛化能力,我们首先要量化它的"泛化误差",即模型在未知数据上的表现。然而,泛化误差并非一个单一的问题,它源于三种不同性质的错误:模型固有的近似能力不足、对训练数据的过度敏感、模型数据本身的不可约噪声。
偏差 - 方差分解公式
规定:
- �data(�,�)Pdata(x,y):数据生成分布
- �D:从�dataPdata中独立同分布采样得到的训练数据集
- �(�;�)f(x;D):由训练集 �D 学得的模型 �f 对 �x 的预测输出。
- �‾(�)f(x):��∼�data⊗�[�(�;�)]ED∼Pdata⊗n[f(x;D)],对所有可能训练集的期望
- ��∼�data⊗�[⋅]ED∼Pdata⊗n[⋅]:对训练集采样的期望
有:
��∣���[(�(�;�)−�)2]=Bias2(�(�))+Var(�(�))+��2Ey∣xED[(f(x;D)−y)2]=Bias2(f(x))+Var(f(x))+σϵ2
其中,
- Bias2(�(�))Bias2(f(x)):偏差,反映模型拟合能力。设真实函数为 ℎ(�)=�[�∣�]h(x)=E[y∣x](条件期望),则偏差应定义为 (�‾(�)−ℎ(�))2(f(x)−h(x))2
- Var(�(�))Var(f(x)):方差,反映不同数据集表现波动情况即泛化能力,:=��[(�(�;�)−�‾(�))2]:=ED[(f(x;D)−f(x))2]
- ��2σϵ2:噪声,反映学习难度,:=�[(�−ℎ(�))2]:=E[(y−h(x))2]
这里正好对应两种模型:线性拟合 vs. 神经网络
- 若线性拟合,模型容量低,并且假设空间简单,即大偏差小方差,泛化误差大,欠拟合。
- 若复杂度过高的神经网络(如未正则化),会学到训练数据中的噪声,导致在训练数据上表现很好(小偏差),但在未见过的数据上表现波动很大(大方差),泛化误差大,过拟合。
- 若复杂度适中的神经网络,中等偏差中等方差,泛化误差小,最佳了。
得出结论:偏差大(欠拟合)意味着模型能力不足,未能捕捉数据中的真实模式;方差大(过拟合)意味着模型过于复杂,对训练数据中的噪声和随机波动过度敏感。
影响偏差与方差的三大因素
1. 学习算法能力(模型复杂度)
如果模型欠拟合(偏差大),就换更复杂的模型;如果过拟合(方差大),就换更简单的模型(或对复杂模型做正则化)。
2. 训练数据量
可间接降低偏差,对方差影响大
如果模型过拟合(方差大),优先增加训练数据。
3. 学习任务本身的难度(任务复杂度)
如果任务简单但方差大,就控制模型复杂度或增加数据;如果任务复杂导致偏差大,就提升模型复杂度
处理模型高偏差、高方差的一些方法
欠拟合(高偏差):应该换更复杂的模型、增加特征维数、仔细判断训练误差是否收敛到最低。
过拟合(高方差):应该增加训练数据、正则化(如使用L1正则化、L2正则化(即权重衰减)、Dropout等)、批量归一化、剪枝降复杂度、降低特征维度。
偏差-方差权衡
偏差与方差通常是对立的,提高模型复杂度可以减少偏差,但可能增加方差;反之,降低模型复杂度可以减少方差,但偏差可能会升高。这种权衡关系被称为 偏差-方差权衡(Bias-Variance Tradeoff)
在此我们应该拓展一下 ,经典理论认为模型复杂度(如参数数量)增加,泛化误差会先因偏差降低而下降,后因方差增大而上升,形成单一的U型曲线。双重下降 则揭示了在插值阈值(模型刚好能完美拟合训练数据)后,随着复杂度进一步增加,误差会再次下降,形成"下降-上升-下降"的波浪形曲线。在过参数化区域,模型并非必然过拟合到更差的程度,优化过程会引导其找到一个泛化良好的解。在过参数化体制下,模型好像是先"记忆"(拟合噪声),后通过漫长的优化过程"逐渐获得"泛化规则。(其实真正的原因是隐式正则化使得优化算法(如SGD)倾向于找到最小范数解或平坦极小值)
这告诉我们,如果观察到增加模型参数后性能先变差,不要立即止步。这可能只是处于插值阈值附近的危险区。继续增加规模,并配合足够的训练,性能可能会突破并变得更好。
理解了模型的误差问题由偏差、方差间的权衡决定,我们大体了解如何选择模型的复杂度。但是,当我们着手训练一个复杂深层模型,尤其是现代网络层数不断加深时,我们应该考虑,训练本身是否能够正常进行?否则结果上的"偏差、方差"都成空谈。这就引出了深度学习中的 梯度问题 。
梯度问题
我们可以认为,
ℎ(�)=��(ℎ(�−1))h(l)=fl(h(l−1))
因此
�=��∘��−1∘...∘�2∘�1(�)o=fL∘fL−1∘...∘f2∘f1(x)
那么不难得到:
∂�(�)�=∂ℎ(�−1)ℎ(�)⏟�(�)=def⋅...⋅∂ℎ(�)ℎ(�+1)⏟�(�+1)=def∂�(�)ℎ(�)⏟�(�)=def.∂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).
也因此,梯度 ∂�(�)�∂W(l)o 是 (�−�)(L−l) 个雅可比矩阵 �(�),...,�(�+1)M(L),...,M(l+1) 与一个二维张量 �(�)v(l) 的乘积。在深层网络中,连续矩阵乘法可能导致结果数值过大(爆炸 )或过小(消失)。
梯度消失:
如果使用Sigmoid函数,就要考虑 Sigmoid 函数在其饱和区梯度逼近于零的情况。因此当输入很大或很小时,梯度消失。为此我们最好用ReLU函数替代之。
如果每一次的 梯度都减小一点,那么多层传播后梯度值会非常小。
如果权重的初始值太小,向前传播过程中每层线性变换的输出方差大幅衰减,进而使激活函数的输入落入该函数的危险区(如 Sigmoid 的饱和区、ReLU的斩杀区)。
梯度爆炸:
特指反向传播过程中,梯度值随着层级增加而不断变大,乃至指数型增加。
很可能因为 ����ℎ�weight 的初始值太大,层数过多等等
参数化的对称性 :
若同一层内的的所有权重均初始化为相同值,那么该层所有的神经元在反向传播中都会获得完全一样的梯度,永远学习相同的特征,极大降低模型容量。
那么,如何为我们模型的训练提供一个良好、稳健的起点呢?这就是神经网络 参数初始化 的showtime了。良好的初始化方式,能够前向传播中保持传递强度,在反向传播中保证梯度流动,从而打破上文的 参数化的对称性 等等问题。
三种常见的初始化
Xavier初始化
目标:保持各层激活值方差稳定,确保前向传播的信号强度和反向传播的梯度强度在初始化时不衰减也不爆炸。
Xavier 初始化因为提出的时间较早,它主要针对像 ���ℎtanh 这样在原点附近近似线性且对称的饱和激活函数。因此对于后来广泛使用的 ReLU 及其变种,它的效果并非最优。
这里的3个函数都有饱和区,也就是梯度消失的那段区域,太大或太小时函数导数趋于 00 。
这个理论的基本原则就是:在前向传播中,保持各层激活值的方差一致;在反向传播中,保持各层梯度的方差一致。 也就是说初始化阶段的激活值和梯度的期望均为 00。Xavier初始化是为 ���ℎtanh 这类在零点附近近似线性且对称的激活函数设计的,对于 �������Sigmoid,虽然 Xavier初始化可以用于 �������Sigmoid ,但不是最优的。实际应用中,对 �������Sigmoid 可以使用 Xavier初始化,但可能需要调整缩放因子。
用数学语言表述,就是要激活函数在原点泰勒展开的一阶近似(当然 �x 也在 00 附近) �(�)f(x) 满足:
�(�)=−�(−�),即�(0)=0�′(0)=1f(x)=−f(−x),即f(0)=0f′(0)=1
再换句话,由观察,我们希望任意层的输入信号方差应等于其输出信号方差:
���(�(�−1))≈���(�(�))Var(a(l−1))≈Var(a(l))
观察第 �l 层的线性变换:
���=∑�=1������(�)⋅��(�−1)zil=j=1∑ninwij(l)⋅aj(l−1)
这里先基本假设一下:
- 权重 ���(�)wij(l) 独立同分布,均值为 00,方差 ��2σw2
- 激活值 ��(�−1)aj(l−1) 独立同分布,均值为 00,方差 ��2σa2
- 权重和激活值相互独立
先看看期望:
�[��(�)]=�[∑�=1������(�)��(�−1)]�[��(�)]=∑�=1����[���(�)]⋅�[��(�−1)]�[��(�)]=0E[zi(l)]E[zi(l)]E[zi(l)]=E[j=1∑ninwij(l)aj(l−1)]=j=1∑ninE[wij(l)]⋅E[aj(l−1)]=0
再看看方差,先着眼于前向传播的过程:
���(��(�))=�[(��(�))2]−(�[��(�)])2=�[(��(�))2]=�[(∑�=1�in���(�)��(�−1))2]=�[∑�=1�in∑�=1�in���(�)���(�)��(�−1)��(�−1)]=...=∑�=1����[(���(�))2]⋅�[(��(�−1))2] (�=�)=���⋅��2⋅��2Var(zi(l))=E[(zi(l))2]−(E[zi(l)])2=E[(zi(l))2]=E(j=1∑ninwij(l)aj(l−1))2=E[j=1∑nink=1∑ninwij(l)wik(l)aj(l−1)ak(l−1)]=...=j=1∑ninE[(wij(l))2]⋅E[(aj(l−1))2] (j=k)=nin⋅σw2⋅σa2
上文公式推导省略号中的内容:
- 当 �≠�j=k,式子为 00
- 当 �=�j=k,式子为 ∑�=1����[(���(�))2]⋅�[(��(�=1))2]∑j=1ninE[(wij(l))2]⋅E[(aj(l=1))2]
- 因此,求和中仅 �=�j=k 的项有贡献。
为了保证激活方差不变,即
���(��(�))=���(��(�−1))���⋅�2⋅��2=��2���⋅��2=1Var(zi(l))nin⋅σ2⋅σa2nin⋅σw2=Var(aj(l−1))=σa2=1
接着推导一下反向传播:
反向传播的梯度传播公式如下
∂�∂��(�−1)=∑�=1�������(�)⋅∂�∂��(�)∂aj(l−1)∂L=i=1∑noutwij(l)⋅∂zi(l)∂L
那么假设 ∂�∂��(�)∂zi(l)∂L 独立同分布,方差为 ��2σg2 ,可以得到梯度方差的表示:
���(∂�∂��(�−1))=∑�=1�����[(���(�))2]⋅�[(∂�∂��(�))2]=����⋅��2⋅��2Var(∂aj(l−1)∂L)=i=1∑noutE[(wij(l))2]⋅E(∂zi(l)∂L)2=nout⋅σw2⋅σg2
我们希望反向传播前后梯度方差不变。即希望:
���(∂�∂��(�−1))=���(∂�∂��(�))Var(∂aj(l−1)∂L)=Var(∂zi(l)∂L)
那么就可以得到反向传播保持方差不变时应满足的条件:
����⋅��2⋅��2=��2����⋅��2=1nout⋅σw2⋅σg2nout⋅σw2=σg2=1
因此,这种一下这两个条件,取调和平均:
���⋅��2=1����⋅��2=1��2=2���+����nin⋅σw2nout⋅σw2σw2=1=1=nin+nout2
即:
���(�)=2���+����Var(w)=nin+nout2
这样,标准差就出来了:
�=2���+����σ=nin+nout2
因此初始权值应符合的正态分布:
�∼�(0,�2)W∼N(0,σ2)
或者转化为均匀分布形式,即
�∼�[−6���+����,6���+����]w∼U[−nin+nout6,nin+nout6]
然而,Xavier初始化提出的时间有点早,ReLU激活函数还没有得到广泛应用。
对于ReLU函数,Xavier初始化力不从心:
- ReLU的函数输出非对称:�∈[0,+∞)y∈[0,+∞)
- 负的输入反向输出时梯度为 00
- 会将 50%50% 的神经元输出清零,从而
- 前向传播:���(�)≈12���(�)Var(a)≈21Var(y)
- 反向传播:梯度方差同样减半
而且对于深层神经网络而言,线性激活函数价值不大,因为它需要非线性激活函数来构建复杂的非线性神经网络。
面对这些问题,He初始化(Kaiming初始化)被提了出来。
Kaiming 初始化
与 Xavier 初始化类似,Kaiming 初始化的目的也是尽量让每一层输出层的方差与输入层的方差一致,以缓解深层网络中的梯度消失、梯度爆炸问题,最后使极深整流网络(如30层)能从零开始直接训练并收敛。
对于向前传播:
Var(��)=Var(∑�=1�in���⋅��)=�input⋅Var(���)⋅Var(��)Var(yi)=Var(j=1∑ninwij⋅xj)=ninput⋅Var(wij)⋅Var(xj)
对��yi加入ReLU函数得到��ai,那么我们就希望:
Var(��)≈Var(��),∀�,�Var(ai)≈Var(xj),∀i,j
这里的初始化假设与 Xavier 相同。
因为 ���wij 与 ��xj 独立且均值为 00,有
Var(�����)=Var(���)Var(��)=��2��2Var(wijxj)=Var(wij)Var(xj)=σw2σx2
则 ��yi 的方差为:
Var(��)=Var(∑�=1��������)=∑�=1���Var(�����)=∑�=1�����2��2=�����2��2=���⋅Var(�)⋅Var(�)Var(yi)=Var(j=1∑ninwijxj)=j=1∑ninVar(wijxj)=j=1∑ninσw2σx2=ninσw2σx2=nin⋅Var(w)⋅Var(x)
我们假设 ��yi 的分布是关于 0 对称的,那么 ��yi 取正数和取负数的概率各占一半。
再看 ��2yi2。因为平方把正负都变成了正数,所以 ��2yi2 的期望值 �[��2]E[yi2] 可以拆成两半:一半来自 ��>0yi>0,一半来自 ��<0yi<0。由于对称,这两半的贡献是一模一样的。
而 ReLU 函数 ��=max(0,��)ai=max(0,yi) 只取 ��yi 的正值部分,负数部分直接归零。所以 ��2ai2 其实就是 ��2yi2 在 ��>0yi>0 时的值,其他情况为 0。
因此,��2ai2 的期望 �[��2]E[ai2] 正好就等于 ��2yi2 期望的一半,即
�[��2]=12�[��2]E[ai2]=21E[yi2]
而 �[��]=0E[yi]=0,有 �[��2]=Var(��)E[yi2]=Var(yi),故
�[��2]=12Var(��)E[ai2]=21Var(yi)
当 (�[��])2(E[ai])2 相较于 �[��2]E[ai2] 可以忽略时,可近似为:
Var(��)≈12Var(��)Var(ai)≈21Var(yi)
我们希望 Var(��)=Var(�)Var(ai)=Var(x)(当然至少得是近似的),结合可得:
12⋅���⋅���(�)⋅���(�)=���(�)���(�)=2���21⋅nin⋅Var(w)⋅Var(x)Var(w)=Var(x)=nin2
以此类推,可以得到反向传播时,
���(�)=2����Var(w)=nout2
不过一般情况,我们使用前向传播优先,即
�∼�(0,2���)W∼N(0,nin2)
我们为什么不常见类比Xavier做调和平均呢?(其实是可以的,见 PyTorch 中的 mode='fan_avg' )因为ReLU的单向激活特性使得前向传播和反向传播的方差传播规律不同:
- 对前向传播,ReLU 杀死一半的神经元,方差减半;对反向传播,相当于简单的伯努利掩码,方差依旧减半。
- 问题在于正向反向的网格结构可能是不同的,且正向反向的衰减机制有席位差别。
pytorch实现:
- 1
- 2
- 3
- 4
layer = nn.Linear(64, 128) init.kaiming_normal_(layer.weight, a=0, mode='fan_in', nonlinearity='relu') # a:负斜率(Leaky ReLU 的情况,默认为0) # Leaky ReLU : 负x轴设置为 ax ,而不是 0 ,通常 a = 0.01
正交初始化
上面两种方法都是对每个权重分别进行随机独立采样,但是由于采样的随机性,仍不可避免出现各种梯度问题。
对于一个 L 层的等宽线性网络,可以很容易得到这个等式:
�=�(�)�(�−1)�(�−2)⋯�(2)�(1)�y=W(L)W(L−1)W(L−2)⋯W(2)W(1)x
那么,我们可以直接将 �(�)W(i) 初始化为正交矩阵。
根据线代知识,我们对这个初始权重矩阵的构建分为两步:
- 用均值 00 , 方差 11 的高斯分布构建一个矩阵
- 奇异值分解这个矩阵,得到两个正交矩阵,选择其中一个作为权重矩阵
根据正交矩阵的性质,这个线性网络就会在前向、反向传播中都有一定的范数保持性。如果这个网络是非线性的,只需在矩阵前面乘上一个系数 �ρ,这个系数与激活函数有关,如对于 ����ReLU 应该 �=2ρ=2 ,对于 ���ℎtanh 应该 �≈1.0ρ≈1.0,这是为了补偿激活函数对信号幅度的压缩(扩张)效应。
更加现代的初始化方法
Fixup
可使在不使用批量归一化的情况下完成深度残差网络训练。
通过缩放残差网络分支的权重来控制梯度规模,避免深层网络的梯度爆炸
方法:
- 将分类层、残差分支的最后一层初始化为 00
- 对其他层使用标准方法的初始化,然后将残差分支中的权重层乘以缩放系数 �−12�−2L−2m−21
- 在每个分支中添加一个标量乘数(就是前面的缩放系数),在每个卷积、线性和元素级激活层前面添加一个可学习标量偏差(初始为 00 )。
其中