上一节介绍了模型泛化误差的组成——偏差、方差、噪声。本节将介绍降低方差的集成学习方法—— Bagging \text{Bagging} Bagging。
学习模型的泛化误差由三部分组成:偏差、方差、噪声。其中噪声是数据集合自身属性,其噪声是客观存在的。因而,我们关注的目标更多在于偏差、方差的降低过程。
其中,偏差较高的核心原因在于:
相反,关于方差较高的核心原因在于:
自助采样法主要针对模型训练过程中,关于数据集合 D \mathcal D D的使用使用不够完整导致的估计偏差。自助采样法的采样过程表示如下:
机器学习(周志华著)P27.
我们可以发现,这种自助采样方式存在:某些样本可能会在 D ′ \mathcal D' D′中出现若干次,而某些样本可能不会出现。那么样本在 N N N次采样中总是无法被采样的概率是: ( 1 − 1 N ) N (1 - \frac{1}{N})^N (1−N1)N,也就是说,如果原始集合 D \mathcal D D的样本数量趋近于无穷大,那么 D ′ \mathcal D' D′中始终不会从 D \mathcal D D采样的概率是:
lim N → ∞ ( 1 − 1 N ) N = 1 e ≈ 0.368 \mathop{\text{lim}}\limits_{N \to \infty} \left(1 - \frac{1}{N}\right)^N = \frac{1}{e} \approx 0.368 N→∞lim(1−N1)N=e1≈0.368
我们可以尝试从代码的角度观察一下这个结果:
def BootstrapingSampling(SampleNum):
def GetGenerateRatio(D):
idx = np.random.randint(0, len(D), size=SampleNum)
D_ = [D[i] for i in idx]
return 1 - (len(set(D_)) / len(D))
D = [i for i in range(SampleNum)]
return GetGenerateRatio(D)
def DrawPicture():
GenerateRatioList = list()
for SampleNum in range(10,100000,100):
Ratio = BootstrapingSampling(SampleNum)
GenerateRatioList.append(Ratio)
x = [i for i in range(len(GenerateRatioList))]
plt.scatter(x,GenerateRatioList,s=4,c="tab:blue")
plt.plot(x,[0.368 for _ in x],c="tab:orange")
plt.show()
if __name__ == '__main__':
DrawPicture()
返回图像结果如下:
可以看出,仅在样本量极少的情况下(仅包含几百个样本左右的数据集),这个比值会有较大的波动。否则,总是会有数据总量约 1 3 \frac{1}{3} 31的样本用于测试。这样的测试结果也被称作包外估计( Out-of-bag Estimate \text{Out-of-bag Estimate} Out-of-bag Estimate)
因此,自助采样法它的适用范围:
我们更希望训练集和测试集之间符合相同的分布。但是如果数据特征过于复杂,无法通过人工的方式划分出一套优秀的训练/测试集,可以尝试使用该方法。
但是与之相对的,自助采样法产生的数据集相比真实数据集消掉了约 36.8 36.8 36.8%的数据信息,这改变了初始数据集的分布,从而引入了估计偏差。因而在样本足够充足的条件下,不适宜使用自助采样法。
Bagging \text{Bagging} Bagging是 Bootstrap Aggrgrating \text{Bootstrap Aggrgrating} Bootstrap Aggrgrating的缩写,这个过程可表示为:
随机森林( Random Forest,RF \text{Random Forest,RF} Random Forest,RF)是 Bagging \text{Bagging} Bagging的一个扩展变体。
对于传统决策树在划分属性时,对于每一个结点,划分属性时选择当前结点所有属性集合(假设集合中包含
d d d个属性)中的最优属性;
对于随机森林的属性划分,对于随机森林中的每一个基决策树,基决策树中的每个结点,从该结点对应的属性集合中随机选择一个‘包含
k k k个属性的子集’,并从该子集中选择一个最优属性用于划分。
每个基决策树中的每个结点均执行上述操作。而子集中包含的属性数量
k k k则是描述‘随机性的引入程度’。
当
k = 1 k=1 k=1时,每一个属性自成一个子集,即随机选择一个属性进行划分;
当
k = d k=d k=d时,此时仅包含一个集合,此时和传统决策树的划分方式相同。
整理:从整个随机森林的角度出发,它的特点有两个部分:
对于各训练模型的数据集:每个训练模型用到的数据集使用 Bagging \text{Bagging} Bagging方式进行获取;
对于各训练模型(决策树),在每棵树划分结点的过程中,每一次划分结点并非从当前属性中选择最优属性,而是先划分一个属性子集,再从属性子集中选择最优属性。
这种处理方式的优势可以使模型中的各决策树之间存在差异性。而最终集成结果的泛化性能随着这种差异性而进一步提升。
这里的泛化性能是指‘针对不同的任务类型(分类、回归)’产生的集成后结果的性能。
从随机森林的角度观察 Bagging \text{Bagging} Bagging集成方法的优势:我们可以有效地降低方差的同时,不会增加整体的泛化误差;这意味着偏差并没有产生影响。也就是说, Bagging \text{Bagging} Bagging仅仅改善了方差,并且没有使偏差增大。
随着随机森林中基学习器数量的增加,关于回归任务的泛化误差结果表示如下:
import matplotlib.pyplot as plt
from tqdm import trange
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_boston
boston = load_boston()
XTrain,XTest,YTrain,YTest = train_test_split(boston.data,boston.target)
MSEListTrain = list()
MSEListTest = list()
for EstimatorNum in trange(1,150,1):
Estimator = RandomForestRegressor(n_estimators=EstimatorNum)
Estimator.fit(XTrain,YTrain)
ScoresTrain = cross_val_score(Estimator,XTrain,YTrain,scoring = "neg_mean_squared_error",cv=5).mean()
ScoresTest = cross_val_score(Estimator,XTest,YTest,scoring = "neg_mean_squared_error",cv=5).mean()
MSEListTrain.append(ScoresTrain * -1)
MSEListTest.append(ScoresTest * -1)
x = [i for i in range(len(MSEListTrain))]
plt.plot(x,MSEListTrain,c="tab:blue",label="train")
plt.plot(x,MSEListTest,c="tab:orange",label="test")
plt.legend()
plt.show()
对应结果表示如下:
其中,横坐标表示基学习器的数量;纵坐标表示泛化误差结果。可以通过观察得到,随着基学习器数量的增加,泛化误差并没有产生过拟合的现象。这说明 Bagging \text{Bagging} Bagging集成思想可以有效地抑制方差,即便是基学习器数量很多,通常不会使误差结果变差。
Bagging \text{Bagging} Bagging主要减小泛化误差中的方差。具体做法是通过训练若干个学习器,如果关于回归任务,将各学习器的预测结果取均值。
虽然是通过取均值来得到最终结果,但这种结果并不会影响均值本身,也就是偏差;反而如果获取越多的预测结果取均值,方差会越来越小。
关于什么情况下使用 Bagging \text{Bagging} Bagging,那自然是在模型训练过程中,方差不可避免地增大时,使用 Bagging \text{Bagging} Bagging是不错的选择。也就是说,方差的大小与训练模型自身性质相关。
通常称方差较大的模型为不稳定学习器( Unstable Learner \text{Unstable Learner} Unstable Learner),依然以回归任务为例,这里假设真实模型为 f ( X ) f(\mathcal X) f(X),基学习器为 h ( i ) ( X ) ( i = 1 , 2 , ⋯ , m ) h^{(i)}(\mathcal X)(i=1,2,\cdots,m) h(i)(X)(i=1,2,⋯,m);其中 i i i表示基学习器的编号。至此,通过 Bagging \text{Bagging} Bagging集成思想得到的近似模型 f ^ ( X ) \hat f(\mathcal X) f^(X)表示如下:
f ^ ( X ) = 1 m ∑ i = 1 m h ( i ) ( X ) = E [ h ( X ) ] \hat f(\mathcal X) = \frac{1}{m}\sum_{i=1}^m h^{(i)}(\mathcal X) = \mathbb E[h(\mathcal X)] f^(X)=m1i=1∑mh(i)(X)=E[h(X)]
从方差的数学性质角度观察,它必然是一个非负结果。因而有:
Var ( x ) ≥ 0 ⇔ E ( x 2 ) − [ E ( x ) ] 2 ≥ 0 ⇔ [ E ( x ) ] 2 ≤ E ( x 2 ) \text{Var}(x) \geq 0 \Leftrightarrow \mathbb E(x^2) - [\mathbb E(x)]^2 \geq 0 \Leftrightarrow [\mathbb E(x)]^2 \leq \mathbb E(x^2) Var(x)≥0⇔E(x2)−[E(x)]2≥0⇔[E(x)]2≤E(x2)
因而有:
其中
f ( X ) f(\mathcal X) f(X)是真实模型,它不是随机变量,因而
E [ f ( X ) ] = f ( X ) \mathbb E[f(\mathcal X)] = f(\mathcal X) E[f(X)]=f(X).
{ f ( X ) − f ^ ( X ) } 2 = { E [ f ( X ) ] − E [ h ( X ) ] } 2 ≤ E [ ( f ( x ) − h ( x ) ) 2 ] ⇔ { E [ h ( X ) ] } 2 ≤ E [ h ( X ) 2 ] \{f(\mathcal X) - \hat f(\mathcal X)\}^2 = \{\mathbb E[f(\mathcal X)] - \mathbb E[h(\mathcal X)]\}^2 \leq \mathbb E\left[(f(x) - h(x))^2\right] \Leftrightarrow \{\mathbb E[h(\mathcal X)]\}^2 \leq \mathbb E\left[h(\mathcal X)^2\right] {f(X)−f^(X)}2={E[f(X)]−E[h(X)]}2≤E[(f(x)−h(x))2]⇔{E[h(X)]}2≤E[h(X)2]
那什么时候方差结果取等?意味着 m m m个基学习器 h ( i ) ( X ) ( i = 1 , 2 , ⋯ , m ) h^{(i)}(\mathcal X)(i=1,2,\cdots,m) h(i)(X)(i=1,2,⋯,m)均相等的时候方差取等。取等意味着使用基学习器 h ( X ) h(\mathcal X) h(X)近似 f ( X ) f(\mathcal X) f(X)不会得到优化,因为所有基学习器均相同有什么好优化的~
相反,如果各基学习器之间存在差异,使用基学习器这种方式降低方差是有效果的。
整理:不稳定学习器,基于它的各基学习器之间在训练过程中存在差异,这种差异在使用 Bagging \text{Bagging} Bagging处理时,得到的结果能够有效降低方差。
例如决策树,它并不是一个稳定的学习器。当数据集合发生变化时,它不仅影响的是样本数量的变化,并且还影响各属性比例的变化。可能存在数据集合发生变化后,决策树选择属性的顺序发生变化;
相反,如线性回归( Linear Regression \text{Linear Regression} Linear Regression),它就是一个稳定的学习器。在样本趋势被描述完成后,即便存在少量样本由于高噪声原因,与样本趋势不相似,但几乎不影响模型的趋势。
相关参考:
5.2 Bagging【斯坦福21秋季:实用机器学习中文版】