干货 | 一文弄懂机器学习中偏差、方差


前言:若需获取本文全部的手书版原稿资料,扫码关注公众号,回复: 偏差和方差 即可获取。

原创不易,转载请告知并注明出处!扫码关注公众号【机器学习与自然语言处理】,定期发布知识图谱,自然语言处理、机器学习等知识,添加微信号【17865190919】进讨论群,加好友时备注来自CSDN。
在这里插入图片描述

在机器学习的面试中,能不能讲清楚偏差方差,经常被用来考察面试者的理论基础,本文就机器学习中偏差和方差进行了详细总结,供参考


一、理解偏差、方差

偏差:描述的是预测值的期望与真实值之间的差距,偏差越大,越偏离真实数据
方差:预测值的方差,描述的是预测值的变化范围,离散程度,也就是离预测值期望值的距离,方差越大,数据的分布越分散,概念上理解比较抽象,下面我们通过下面一个例子来理解一下偏差和方差
在这里插入图片描述

如上图,我们假设一次射击就是一个机器学习模型对一个样本进行预测,射中红色靶心位置代表预测准确,偏离靶心越远代表预测误差越大。偏差则是衡量射击的蓝点离红圈的远近,射击位置即蓝点离红色靶心越近则偏差越小,蓝点离红色靶心越远则偏差越大;方差衡量的是射击时手是否稳即射击的位置蓝点是否聚集,蓝点越集中则方差越小,蓝点越分散则方差越大。



二、偏差、方差与模型范化能力

先给出结论:模型的泛化能力(泛化误差)是由偏差、方差与数据噪声之和,如下式:

Err ( x ) =   bias 2 ( x ) + v a r ( x ) +   ε 2 \text{Err}\left( x \right) = \ \text{bias}^{2}\left( x \right) + var\left( x \right) + \ \varepsilon^{2} Err(x)= bias2(x)+var(x)+ ε2

偏差度量的是学习算法预测误差和真实误差的偏离程度,即刻画学习算法本身的学习能力,方差度量同样大小的训练数据的变动所导致的学习性能的变化,即刻画数据扰动所造成的影响,噪声则表达了当前任务上任何学习算法所能到达的期望预测误差的下界,即刻画了学习问题本身的难度,因此泛化误差是由学习算法的能力、数据的充分性以及问题本身难度决定

学习算法刚训练时,训练不足欠拟合,此时偏差较大;当训练程度加深之后,训练数据的扰动也被算法学习到了,此时算法过拟合,方差过大,训练数据轻微扰动都会使得学习模型发生显著变化,因此我们得出结论:模型欠拟合时偏差过大,模型过拟合时方差过大。我们通过下面的例子来更形象的理解一下上面的描述的结论,看下图
在这里插入图片描述

例如现在我们选择机器学习模型对图中数据做拟合,上左图使用直线对数据进行拟合,直线不能很好的分割数据,预测值将有大量分错,如红色的叉分到了蓝色的圈一类,此时模型偏差过大,模型欠拟合;再看上右图,模型过度拟合数据,将数据中的噪音点也都学到,此时数据的轻微波动将会导致预测结果的波动,方差过大,模型过拟合;自然上中图是我们认为比较好的拟合。

如上左图模型便是高偏差,但是方差小;上右图模型是高方差,但完全分割训练样本中所有数据因此偏差小;上中图便是比较理想的方差和偏差都比较小;那么有没有想像一下高方差同时又高偏差的模型是什么样子?如下图红色线展示的模型便是高方差同时高偏差
在这里插入图片描述

上面给出了泛化误差和偏差、方差与数据噪声的公式,下面给出繁琐的推导公式,当然对公式不敏感的可以跳过此段公式推导继续看下文

Err ( x ) =   bias 2 ( x ) + v a r ( x ) +   ε 2 \text{Err}\left( x \right) = \ \text{bias}^{2}\left( x \right) + var\left( x \right) + \ \varepsilon^{2} Err(x)= bias2(x)+var(x)+ ε2

先给出各个符号的含义

x:测试样本集

D:训练数据集

yD:测试数据集x的标记

y:测试数据集x的真实标记

f:由训练集D学习到的模型

f(x,D):模型f对x的预测输出

f(x):模型f对x预测输出的均值,即期望预测输出

首先期望预测输出是由预测输出f(x,D)的均值得到:

f ‾ ( x ) = E ( f ( x , D ) ) \overset{\overline{}}{f}\left( x \right) = E(f(x,D)) f(x)=E(f(x,D))

根据上面的量我们便可以表示出偏差、方差和噪声,首先偏差是期望输出与真是标记y的误差,方便直接取平方:

bias 2 ( x ) =   ( f ‾ ( x ) − y ) 2 \text{bias}^{2}\left( x \right) = \ \left( \overset{\overline{}}{f}\left( x \right) - y \right)^{2} bias2(x)= (f(x)y)2

方差是针对预测输出上进行计算:

var ( x ) =   E [ f ( x , D ) −   f ‾ ( x ) ] 2 \text{var}\left( x \right) = \ {E\left\lbrack f\left( x,D \right) - \ \overset{\overline{}}{f}\left( x \right) \right\rbrack}^{2} var(x)= E[f(x,D) f(x)]2

噪声是真实标签和数据中的标签的差值,这里方便预算以平方计算:

ε 2 = E [ ( y D − y ) 2 ] \varepsilon^{2} = E\left\lbrack \left( y_{D} - y \right)^{2} \right\rbrack ε2=E[(yDy)2]

为了下面推导方便我们假设噪声的均值为0:

E [ y D − y ] = 0 E\left\lbrack y_{D} - y \right\rbrack = 0 E[yDy]=0

接下来我们以回归任务为例,学习算法的平方差泛化误差损失:
在这里插入图片描述
上图推导中红色部分公式为0,因此省略掉,这里解释一下为什么红色公式为0,因为有:

E [ f ( x , D ) −   f ‾ ( x ) ] = 0 E\left\lbrack f\left( x,D \right) - \ \overset{\overline{}}{f}\left( x \right) \right\rbrack = 0 E[f(x,D) f(x)]=0

E [ y D − y ] = 0 E\left\lbrack y_{D} - y \right\rbrack = 0 E[yDy]=0

因此有:

E D ( 2 ( f ( x , D ) − f ‾ ( x ) ) ( f ‾ ( x ) − y D ) ) = 0 E_{D}\left( 2\left( f\left( x,D \right) - \overset{\overline{}}{f}\left( x \right) \right)\left( \overset{\overline{}}{f}\left( x \right) - y_{D} \right) \right) = 0 ED(2(f(x,D)f(x))(f(x)yD))=0

E D ( ( f ‾ ( x ) − y ) ( y − y D ) ) = 0 E_{D}\left( (\overset{\overline{}}{f}\left( x \right) - y)\left( y - y_{D} \right) \right) = 0 ED((f(x)y)(yyD))=0

这样经过推导得出:
在这里插入图片描述
所有存在模型的泛化能力(泛化误差)是由偏差、方差与数据噪声之和:

Err ( x ) =   bias 2 ( x ) + v a r ( x ) +   ε 2 \text{Err}\left( x \right) = \ \text{bias}^{2}\left( x \right) + var\left( x \right) + \ \varepsilon^{2} Err(x)= bias2(x)+var(x)+ ε2



三、模型偏差高 or 方差高

在实际的应用中,如果一个模型对于测试集的预测不理想,那如何判断是由于高偏差导致还是高方差导致呢,这个判断对于后续模型优化至关重要。

参考方法:通过训练集误差和测试集误差来看高偏差 or 高方差

我们以猫狗分类模型为背景来看具体如何判断,对于猫狗分类首先我们有一个前提假设就是该数据本身能够达到很高的正确率,例如99%的正确率,看下面四种情况:

(1)训练集错误率:1%、测试集错误率:11% 低偏差高方差

(2)训练集错误率:15%、测试集错误率:16% 高偏差低方差

(3)训练集错误率:15%、测试集错误率:30% 高偏差高方差

(4)训练集错误率:0.5%、测试集错误率:1% 低偏差低方差

因此在实际工程中我们便可以通过比较训练集误差和测试集误差来看模型是由何种原因导致,然后采取相应的错误,下一节介绍如何优化模型



四、高偏差高方差时优化模型


1、高偏差(模型欠拟合)时模型优化方法

(1)添加特征数
当特征不足或者选取的特征与标签之间相关性不强时,模型容易出现欠拟合,通过挖掘上下文特征、ID类特征、组合特征等新特征,往往可以达到防止欠拟合的效果,在深度学习中,有很多模型可以帮助完成特征工程,如因子分解机、梯度提升决策树、Deep-crossing等都可以称为丰富特征的方法

(2)增加模型复杂度
模型过于简单则学习能力会差,通过增加模型的复杂度可以使得模型拥有更强的你和能力,例如在线性模型中添加高此项,在神经网络模型中增加隐层层数或增加隐层神经元个数

(3)延长训练时间
在决策树、神经网络中,通过增加训练时间可以增强模型的泛化能力,使得模型有足够的时间学习到数据的特征,可达到更好的效果

(4)减小正则化系数
正则化是用来方式过拟合的,但当模型出现欠拟合时则需要有针对的较小正则化系数,如xgboost算法

(5)集成学习方法Boosting
Boosting算法是将多个弱分类串联在一起,如Boosting算法训练过程中,我们计算弱分类器的错误和残差,作为下一个分类器的输入,这个过程本身就在不断减小损失函数,减小模型的偏差

(6)选用更合适的模型
有时候欠拟合的原因是因为模型选的不对,如非线性数据使用线性模型,拟合效果肯定不够好,因此有时需要考虑是否是模型使用的不合适

2、高方差(模型过拟合)时模型优化方法

(1)增加数据集
增加数据集是解决过拟合问题最有效的手段,因为更多的数据能够让模型学到更多更有效的特征,减小噪声的影响度。当然数据是很宝贵的,有时候并没有那么多数据可用或者获取代价太高,但我们也可以通过一定的规则来扩充训练数据,比如在图像分类问题上,可以通过图像的平移,旋转,缩放、模糊以及添加噪音等方式扩充数据集,在我的这篇文章中有介绍,更一步,可使用生成式对抗网络来合成大量的新数据

(2)降低模型的复杂度
数据集少时,模型复杂是过拟合的主要因素,适当降低模型复杂度可以避免模型拟合过多的采样噪音,例如在决策树算法中降低树深度、进行剪枝;在深度网络中减少网络层数、神经元个数等

(3)正则化防止过拟合
正则化思想:由于模型过拟合很大可能是因为训练模型过于复杂,因此在训练时,在对损失函数进行最小化的同时,我们要限定模型参数的数量,即加入正则项,即不是以为的去减小损失函数,同时还考虑模型的复杂程度

未加入正则项的模型损失函数:

C ( x ) =   1 2 ∑ i = 1 n ( f ( x ) − y i ) 2 C\left( x \right) = \ \frac{1}{2}\sum_{i = 1}^{n}{(f\left( x \right) - y_{i})}^{2} C(x)= 21i=1n(f(x)yi)2

加入正则项L后损失函数:

C ( x ) =   1 2 ∑ i = 1 n ( f ( x ) − y i ) 2 +   λ L C\left( x \right) = \ \frac{1}{2}\sum_{i = 1}^{n}{{(f\left( x \right) - y_{i})}^{2} + \ \lambda L} C(x)= 21i=1n(f(x)yi)2+ λL

其中λ是正则项系数,是用来权衡正则项和损失函数之间权重,正则化有以下两种:

<1> L1正则化(L1范数):权重向量w的绝对值之和

L 1 =   ∑ i = 1 k ∣ ∣ w i ∣ ∣ 1 L_{1} = \ \sum_{i = 1}^{k}{||w_{i}||}_{1} L1= i=1kwi1

<2> L2正则化(L2范数):权重向量w的平方和,欧几里得范数

L 2 =   ∑ i = 1 k ∣ ∣ w i ∣ ∣ 2 2 L_{2} = \ \sum_{i = 1}^{k}{||w_{i}||}_{2}^{2} L2= i=1kwi22

其中w代表模型的参数,k则代表了模型参数的个数

(4)集成学习方法Bagging
集成学习Bagging是把多个模型集成在一起,来降低单一模型的过拟合风险

(5)选用更合适的模型
在上诉方法都没有达到很好的效果时可以考虑选择使用其他模型处理数据



五、谈偏差和Boosting、方差和Bagging

上文在提到高偏差和高方差优化时使用集成学习方法,这小节再深入介绍一下为什么Bagging降低了模型方差,Boosting降低了模型的偏差

1、Bagging和方差

Bagging算法对数据重采样,然后在每个样本集训练出来的模型上取平均值
假设有n个随机变量,方差记为σ2,两两变量之间的相关性是ρ,则n个随机变量的均值的方差为:

v a r =   n 2 ∗ γ 2 ∗ δ 2 ∗ ρ + m ∗ γ 2 ∗ δ 2 ∗ ( 1 − ρ ) var = \ n^{2}*\gamma^{2}*\delta^{2}*\rho + m*\gamma^{2}*\delta^{2}*(1 - \rho) var= n2γ2δ2ρ+mγ2δ2(1ρ)

        = n 2 ∗ 1 n 2 ∗ δ 2 ∗ ρ + m ∗ 1 n 2 ∗ δ 2 ∗ ( 1 − ρ ) \ \ \ \ \ \ \ = n^{2}*\frac{1}{n^{2}}*\delta^{2}*\rho + m*\frac{1}{n^{2}}*\delta^{2}*(1 - \rho)        =n2n21δ2ρ+mn21δ2(1ρ)

= ρ ∗ δ 2 + ( 1 − ρ ) ∗ δ 2 n                              = \rho*\delta^{2} + \left( 1 - \rho \right)*\frac{\delta^{2}}{n}\text{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ } =ρδ2+(1ρ)nδ2                            

在随机变量完全独立的情况下,n个随机变量的方差是原来的1/n

Bagging算法对n个独立不相关的模型的预测结果取平均,方差是原来单个模型1/n,上述描述不严谨因为在实际问题中,模型不可能完全独立,但为了追求模型的独立性,Bagging的方法做了不同的改进,比如随机森林算法中,每次选取节点分裂属性时,会随机抽取一个属性子集,而不是从所有的属性中选最有属性,这就为了避免弱分类器之间过强的关联性,通过训练集的重采样也能够带来弱分类器之间的一定独立性,这样多个模型学习数据,不会因为一个模型学习到数据某个特殊特性而造成方差过高

2、Boosting和偏差

Boosting算法训练过程中,我们计算弱分类器的错误和残差,作为下一个分类器的输入,这个过程本身就在不断减小损失函数,其bias自然逐步下降。但由于是采取这种sequential、adaptive的策略,各子模型之间是强相关的,于是子模型之和并不能显著降低variance。所以说boosting主要还是靠降低bias来提升预测精度



六、偏差方差平衡(Bias-Variance Tradeoff)

在实际的问题中噪音是数据自带的,没有办法优化,因此为了优化模型,降低模型的泛化误差,我们便从降低偏差和方差入手,但是方差和偏差存在权衡问题,即在优化一个时便会导致另一个升高,下图给出了泛化误差和偏差、方差的变化关系:
在这里插入图片描述
在训练不足时,模型的拟合能力不强,此时偏差主导着总体误差(泛化误差),随着训练程度的加深,模型的拟合能力已经很强,训练数据发生的噪音扰动也被模型学到,方差逐渐主导总体误差。因此我们在实际工程中需要找到一个合适的方式来权衡模型的偏差和方差?

1、偏差方差权衡之经验风险最小化模型

从上面的分析中,我们知道偏差方差权衡既是要同时降低测试误差和训练误差,即如果模型满足下式便是一个好模型:

Error train = Error test \text{Error}_{\text{train}} = \text{Error}_{\text{test}} Errortrain=Errortest

Error train   ≈    0 \text{Error}_{\text{train}}\ \approx \ \ 0 Errortrain   0

为了说明如何得到上述模型,先要提出一个更为一般的机器学习模型,经验风险最小化,这里给出两个引理:

(1)联合界引理
时间A1,A2,…,Ak表示k个不同的事件,k个事件之间不是相互独立的,可能是有关联的:

P ( A 1 ⋃ . . ⋃ A k ) ≤ P ( A 1 ) + P ( A 2 ) + … + P ( A k ) P\left( A_{1}\bigcup..\bigcup A_{k} \right) \leq P\left( A_{1} \right) + P\left( A_{2} \right) + \ldots + P(A_{k}) P(A1..Ak)P(A1)+P(A2)++P(Ak)

(2)Hoeffding不等式
Z1,Z2,…,Zm是m个独立同分布的随机变量,他们服从均值为φ的伯努利分布(0-1分布),即表示P(Zi=1)=φ,所有对m个独立同分布的随机变量,其均值为φ,给定λ > 0

下面式子成立:

P ( ∣ ϕ − ϕ ^ ∣ > γ ) ≤ 2 e x p ( − 2 γ 2 m ) P\left( \left| \phi - \hat{\phi} \right| > \gamma \right) \leq 2exp( - 2\gamma^{2}m) P(ϕϕ^>γ)2exp(2γ2m)

不等式含义是:估计的值φ与真实值φ之间的差异,不会超过不等式右侧的这个上界

经验风险最小化ERM算法证明了:当数据集m足够大时,一般误差与最小误差之间是有上界的,简单地说,当训练误差很小时,一般误差也不会很大,具体证明请参考博文:
https://blog.csdn.net/zb123455445/article/details/78538361

2、偏差方差权衡之交叉验证

(1) Hold-out cross validation 保留交叉验证
训练子集70%、保留交叉验证子集30%,通常对于保留交叉验证70%、30%是合理的划分,先用训练子集训练模型,然后在剩下的保留交叉验证子集中测试模型,选测试误差小的模型

保留交叉验证存在两个问题:
第一: 最终模型和参数的选取将极大程度上依赖于对于训练数据和测试数据的划分
第二:部分数据用于训练,不能很好的利用数据集

有些数据获取十分珍贵,上述方法没有很好的利用数据集进行模型训练,下面提出交叉验证的变种,更好的利用数据集进行模型训练

(2)留1交叉验证
这种计算量更大,仅仅针对于样本量很少的情况,如样本数15
如果数据集有n个,留1交叉验证总共要训练n次,每次选择一个数据作为测试集,其他n-1个数据作为验证集

(3)K重交叉验证
通常情况下k取5份或10份,若k=10,每次留其中一份作为数据测试,用剩下9份做模型训练,优点是很好的利用数据,缺点是要进行多次训练,计算量大,算是上面两种方式的综合,当K值大的时候,我们会有更少的Bias(偏差), 更多的Variance。,当K值小的时候,我们会有更多的Bias(偏差),更少的Variance,因此选择k对于优化结果也有十分重要的影响,一般工程中选择k=5、10较多

注意事项1:上面提到的保留交叉验证70%,30%是针对小数据量时划分,当百万数据及以上时,我们需要对数据划分训练集、验证集、测试集,验证集目的:在多个算法中选出最有效的算法;测试集目的:正确评估分类器的性能,;例如100万,我们可能只需要10000个作为验证集,10000作为测试集,划分比例(98%,1%,1%),当数据量很大时,有时候训练集可高大99.5%

注意事项2:训练数据和验证,测试数据分布不匹配的问题,例如:训练集是非常高清标准的图片,测试集是用户随意拍照上传的不清楚模糊的图片,建议:保证验证集和测试集是来自同一个分布,有的时候验证集和测试集被看成同一概念

### 最小误差剪枝的概念与实现 #### 什么是最小误差剪枝? 最小误差剪枝是一种基于错误率评估的决策树后剪枝技术。其核心思想是在验证集上计算子树的预测误差,并将其与当前叶子节点替换后的整体误差进行比较。如果替换能够降低总误差,则执行剪枝操作[^1]。 这种剪枝方法的目标是最小化模型在未见数据上的预测误差,从而提升模型的泛化性能。它通常应用于已经完全生长的决策树,在保留重要结构的同时移除冗余部分。 --- #### 最小误差剪枝的实现步骤 以下是实现最小误差剪枝的核心逻辑: 1. **定义误差函数** 对于每个内部节点 \( n \),假设该节点对应的样本集合为 \( S_n \),则可以定义误差率为: \[ E(n) = \frac{\text{误分类样本数}}{\text{总样本数}} \] 如果将此节点转换为叶子节点并赋予多数类标签,则新的误差可以通过上述公式重新计算。 2. **递归遍历树结构** 自底向上地访问每一个非叶子节点,对于每个节点分别计算保持原状剪枝后的总体误差。选择使误差更小的操作作为最终决定。 3. **更新树结构** 当某个子树被判定应被剪掉时,用单一叶子节点替代整个子树,并标记新叶子节点的类别为其父节点中的多数类。 4. **终止条件** 遍历完整棵树之后停止过程;或者当进一步剪枝不会带来显著改进时提前结束。 下面是一个简单的 Python 实现示例: ```python class DecisionTree: def __init__(self, tree): self.tree = tree def prune(self, validation_data): """ 执行最小误差剪枝 """ pruned_tree = self._prune_recursive(self.tree, validation_data) return pruned_tree def _prune_recursive(self, node, data): if isinstance(node, LeafNode): # 已经到达叶子节点 return node # 获取当前节点的数据划分 left_data, right_data = split_data(data, node.split_feature) # 递归处理左右子树 if left_data is not None and right_data is not None: node.left_child = self._prune_recursive(node.left_child, left_data) node.right_child = self._prune_recursive(node.right_child, right_data) # 计算不剪枝情况下的误差 error_no_prune = calculate_error(node, data) # 将当前节点替换成叶子节点的情况 majority_class = get_majority_class(data) leaf_node = LeafNode(majority_class) error_with_prune = calculate_error(leaf_node, data) # 判断是否应该剪枝 if error_with_prune <= error_no_prune: return leaf_node # 替换为叶子节点 else: return node # 不剪枝 def calculate_error(node, data): predictions = [node.predict(sample) for sample in data] actuals = [sample.label for sample in data] errors = sum(p != a for p, a in zip(predictions, actuals)) return errors / len(data) ``` --- #### 关键点解析 - **验证集的重要性**:最小误差剪枝依赖于独立的验证集来估计模型的真实表现。如果没有足够的验证数据,可能会导致拟合过拟合。 - **时间复杂度**:由于需要反复计算不同状态下的误差,因此这种方法可能较为耗时,尤其针对大型决策树。 - **适用场景**:相比其他剪枝策略(如成本复杂度剪枝),最小误差剪枝更适合那些对精度要求较高而资源允许的应用场合[^2]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值