集成学习的核心:训练多棵树,并综合多棵树(可带权重)得到结果。主要分为以下两类:
Bagging(代表:随机森林Random Forest):训练多棵树(多个学习器)进行集成预测;【并行】
Boosting(代表:AdaBoost,XGBoost,GBDT):在前一棵树的基础上改进,按顺序生成新树。【串行】
Bagging(袋装法)
决策树容易受到训练数据的影响(单棵树的预测结果不稳定)
Breiman于1996年提出Bagging,其核心思想为:训练很多棵树,再投票(分类)或者取平均(回归)。其优势在于可以降低预测方差,因为每棵树的错误方向不完全一样,通过汇总可以将随机波动部分抵消。
那么从训练样本中如何得到多颗树呢?Breiman借用了统计学的方法:Bootstrap法(“自助法”) 。这一方法由美国统计学家Bradley Efron在1979年首次提出,最初用于非参数统计中。
具体而言,Bootstrap方法先在总体中抽取一次样本,然后在这个样本中多次进行有放回抽样,从而得到多个小样本。
随机森林(Random Forest)
在上面的Bagging方法中,由于Bootstrap的特性,很多树会反复使用同样的重要特征,导致大部分树都长得很像,集成的优势被削弱。为解决这一问题,随机森林方法于2001年由Breiman和Adele Cutler正式提出。
随机森林的特点是每棵树每次分裂时,只会随机看一部分特征,这会使树之间的差异更大,不同意见的投票往往更有效。
具体而言,每次节点分裂时,会从当前p p p 个特征中随机选择m ≈ p m\approx\sqrt{p} m ≈ p 个特征。
袋外样本(OOB)
在Bootstrap中,每棵树都可能会有样本没有被抽到。这些袋外样本刚好可以作为临时测试集,这样就不需要交叉验证。
可以证明,对于每个样本观测值,大约会有1 3 \dfrac{1}{3} 3 1 的决策树不会使用到。设共有B B B 棵决策树,则每个样本(作为测试样本)可以产生B 3 \dfrac{B}{3} 3 B 个预测值,再对其取平均。当B B B 很大时,其误差约等于N-fold交叉验证的误差。
所以随机森林不用额外进行交叉验证(耗时),而使用OOB误差估计测试误差。
变量重要性
随机森林的另一个功能就是得到每个特征的重要性。其衡量依据是:如果一个特征被打乱后,模型性能下降很多,说明它很重要。
具体而言:
先将袋外样本传入一棵树中记录其预测准确性;
然后对袋外样本的某个特征进行重排(perturbation),再传入树中,比较其准确性的变化;
通过所有树对这种排列造成的准确性降低值进行平均,并将其用作随机森林中该特征的重要性度量。
Boosting(提升法)
与前面Bagging的思路不同,Boosting的核心思想是:每棵树专门学习前面模型犯错的地方,树是按顺序生成的。
1997年,Freund和Schapire基于集成学习的思想提出AdaBoost,由此产生了一类Boosting算法,包括GradBoost,XGBoost,LightGBM等。
AdaBoost
AdaBoost的理论基础:弱学习器可以通过某种组合提升为强学习器。
AdaBoost的核心在于:每一轮训练一个简单分类器(决策树),并更关注之前分错的样本,最后把多个分类器(决策树)组合。
具体方法(以二分类问题为例):
使用弱学习器(一般为决策树桩Decision Stump,即只有两层的决策树),得到基本分类器G 1 ( x ) G_1(x) G 1 ( x )
根据G 1 ( x ) G_1(x) G 1 ( x ) 的分类效果,增加错误样本权重
记ϵ 1 \epsilon_1 ϵ 1 为分类错误样本的加权占比,α 1 = 1 2 ln 1 − ϵ 1 ϵ 1 \alpha_1=\dfrac{1}{2}\ln\dfrac{1-\epsilon_1}{\epsilon_1} α 1 = 2 1 ln ϵ 1 1 − ϵ 1 ,那么对分类错误样本权重乘以exp { α 1 } \exp\{\alpha_1\} exp { α 1 } ,分类正确样本权重乘以exp { − α 1 } \exp\{-\alpha_1\} exp { − α 1 } ,然后对权重进行归一化。
ϵ m < 1 2 , α m > 0 \epsilon_m< \dfrac{1}{2},\alpha_m>0 ϵ m < 2 1 , α m > 0 ,且ϵ m \epsilon_m ϵ m 越小,α m \alpha_m α m 越大。
以此类推,最终得到分类器(强学习器)y ^ = sgn ( ∑ i = 1 N α i ⋅ G i ( x ) ) \hat{y}=\displaystyle\text{sgn}\left(\sum_{i=1}^N\alpha_i\cdot G_i(x)\right) y ^ = sgn ( i = 1 ∑ N α i ⋅ G i ( x ) ) ,其中G i ( x ) G_i(x) G i ( x ) 为每棵树的预测结果。
模型理论与优化
AdaBoost的本质是一个加法模型:
G m ( x ) = sgn ( f m ( x ) ) ⟹ f ( x ) = ∑ m = 1 M α m G m ( x ) ⟹ G ( x ) = sgn ( f ( x ) ) \begin{aligned}
G_m(x)&=\text{sgn}(f_m(x))\\
\Longrightarrow f(x)&=\sum_{m=1}^M\alpha_mG_m(x)\\
\Longrightarrow G(x)&=\text{sgn}(f(x))
\end{aligned} G m ( x ) ⟹ f ( x ) ⟹ G ( x ) = sgn ( f m ( x )) = m = 1 ∑ M α m G m ( x ) = sgn ( f ( x ))
初始化:f 0 ( x ) = 0 f_0(x)=0 f 0 ( x ) = 0
优化问题:
min ∑ i = 1 N L ( y i , f ( x i ) ) \min\sum_{i=1}^N\mathcal{L}(y_i,f(x_i)) min i = 1 ∑ N L ( y i , f ( x i ))
其中损失函数取指数损失L ( y , f ( x ) ) = e − y f ( x ) \mathcal{L}(y,f(x))=e^{-yf(x)} L ( y , f ( x )) = e − y f ( x ) 。
优化时主要使用前向分步算法:
( α m , G m ) = arg min ∑ i = 1 N L ( y i , ∑ j = 1 m − 1 α j G j ( x i ) + α m G m ( x i ) ) (\alpha_m, G_m) = \arg \min \sum_{i=1}^N L\left(y_i, \sum_{j=1}^{m-1} \alpha_j G_j(x_i) + \alpha_m G_m(x_i)\right) ( α m , G m ) = arg min i = 1 ∑ N L ( y i , j = 1 ∑ m − 1 α j G j ( x i ) + α m G m ( x i ) )
其中N N N 为样本数。这也是所有Boosting优化的基础。由此可见,Boosting通过逐步学习优化:( α 1 , G 1 ) ⇒ ( α 2 , G 2 ) ⇒ ⋯ ⇒ ( α M , G M ) (\alpha_1,G_1)\Rightarrow(\alpha_2,G_2)\Rightarrow\cdots\Rightarrow(\alpha_M,G_M) ( α 1 , G 1 ) ⇒ ( α 2 , G 2 ) ⇒ ⋯ ⇒ ( α M , G M )
( α m , G m ) = arg min ∑ i = 1 N exp [ − y i { ∑ j = 1 m − 1 α j G j ( x i ) + α m G m ( x i ) } ] = arg min ∑ i = 1 N w m i exp { − y i α m G m ( x i ) } \begin{aligned}
(\alpha_m, G_m) &= \arg \min \sum_{i=1}^N \exp \left[ -y_i \left\{ \sum_{j=1}^{m-1} \alpha_j G_j(x_i) + \alpha_m G_m(x_i) \right\} \right]\\
&= \arg \min \sum_{i=1}^N w_{mi} \exp \left\{ -y_i \alpha_m G_m(x_i) \right\}
\end{aligned} ( α m , G m ) = arg min i = 1 ∑ N exp [ − y i { j = 1 ∑ m − 1 α j G j ( x i ) + α m G m ( x i ) } ] = arg min i = 1 ∑ N w mi exp { − y i α m G m ( x i ) }
其中w m i ∝ 1 N exp { − y i ∑ j = 1 m − 1 α j G j ( x i ) } \displaystyle w_{mi}\propto\frac{1}{N}\exp\left\{ -y_i \sum_{j=1}^{m-1} \alpha_j G_j(x_i) \right\} w mi ∝ N 1 exp { − y i j = 1 ∑ m − 1 α j G j ( x i ) } (在其基础上进行归一化)。代回上式可得
( α m , G m ) = arg min 1 N ∑ i = 1 N ( ∏ j = 1 m − 1 exp { − y i α j G j ( x i ) } ) ⋅ exp { − y i α m G m ( x ) } (\alpha_m, G_m) = \arg \min\frac{1}{N}\sum_{i=1}^N\left(\prod_{j=1}^{m-1}\exp\{-y_i\alpha_jG_j(x_i)\}\right)\cdot\exp\{-y_i\alpha_mG_m(x)\} ( α m , G m ) = arg min N 1 i = 1 ∑ N ( j = 1 ∏ m − 1 exp { − y i α j G j ( x i )} ) ⋅ exp { − y i α m G m ( x )}
固定α m \alpha_m α m ,则
∑ i w m i exp ( − y i α G ( x i ) ) = e − α ∑ y i = G ( x i ) w m i + e α ∑ y i ≠ G ( x i ) w m i ≜ e − α ( 1 − ϵ m ) + e α ϵ m . \begin{aligned}
\sum_i w_{mi} \exp(-y_i \alpha G(x_i))&= e^{-\alpha} \sum_{y_i = G(x_i)} w_{mi} + e^{\alpha} \sum_{y_i \neq G(x_i)} w_{mi}\\
&\triangleq e^{-\alpha}(1-\epsilon_m)+e^\alpha\epsilon_m.
\end{aligned} i ∑ w mi exp ( − y i α G ( x i )) = e − α y i = G ( x i ) ∑ w mi + e α y i = G ( x i ) ∑ w mi ≜ e − α ( 1 − ϵ m ) + e α ϵ m .
对α m \alpha_m α m 求偏导取零点得
α m = 1 2 ln 1 − ϵ m ϵ m . \alpha_m=\dfrac{1}{2}\ln\dfrac{1-\epsilon_m}{\epsilon_m}. α m = 2 1 ln ϵ m 1 − ϵ m .
于是G m ( x ) G_m(x) G m ( x ) 可表示为
G m ( x ) = arg min G ∑ i = 1 N w m i I ( y i ≠ G m ( x i ) ) G_m(x)=\argmin_G\sum_{i=1}^Nw_{mi}I(y_i\neq G_m(x_i)) G m ( x ) = G arg min i = 1 ∑ N w mi I ( y i = G m ( x i ))
即最小化加权分类误差。
这就是前面的加权系数和弱学习器如此设置的原因。
GBM(梯度提升算法)
在上面的Adaboost中,我们使用了指数损失函数,但其并不完美:它和MSE一样,对异常值敏感。
另一方面,Adaboost通过每一轮加入一个新的弱学习器以修正当前模型的不足,其本质就是降低损失函数。
1999年,Friedman提出Gradient Boosting理论,将Adaboost模型推广至任意损失函数。
将指数损失函数推广到任意损失函数后,最优解难以直接求出。而GBM采用了另一种策略:如果希望损失函数下降,应该沿着损失函数下降最快的方向更新,即负梯度方向。
模型:
g m ( x ) ← g m − 1 ( x ) + α G m ( x ) ≈ g m − 1 ( x ) − α ∂ L ( y , g ( x ) ) ∂ g ( x ) ∣ g = g m − 1 g_m(x)\leftarrow g_{m-1}(x)+\alpha G_m(x)\approx g_{m-1}(x)-\alpha\left.\frac{\partial\mathcal{L}(y,g(x))}{\partial g(x)}\right|_{g=g_{m-1}} g m ( x ) ← g m − 1 ( x ) + α G m ( x ) ≈ g m − 1 ( x ) − α ∂ g ( x ) ∂ L ( y , g ( x )) g = g m − 1
其本质可也以理解为一阶泰勒展开:
L ( y , g m − 1 + α G m ) ≈ L ( y , g m − 1 ) + α ∑ i = 1 N ∂ L ( y i , g m − 1 ( x i ) ) ∂ g m − 1 ( x i ) G m ( x i ) \mathcal{L}(y,g_{m-1} + \alpha G_m) \approx \mathcal{L}(y,g_{m-1}) + \alpha \sum_{i=1}^N \frac{\partial \mathcal{L}(y_i, g_{m-1}(x_i))}{\partial g_{m-1}(x_i)} G_m(x_i) L ( y , g m − 1 + α G m ) ≈ L ( y , g m − 1 ) + α i = 1 ∑ N ∂ g m − 1 ( x i ) ∂ L ( y i , g m − 1 ( x i )) G m ( x i )
GBM的核心:借用神经网络梯度下降的思想,使用负梯度指导模型更新。其特点包括:
可用于:回归、分类、排序
基学习器通常为回归树
分类时树用于拟合梯度/残差
具体而言,在GBM训练第m m m 轮,会利用{ ( x i , − ∂ L ( y i , g ( x i ) ) ∂ g ( x i ) ∣ g = g m − 1 ) } i = 1 N \displaystyle\left\{ \left( x_i ,- \frac{\partial\mathcal{L}(y_i,g(x_i))}{\partial g(x_i)} \bigg|_{g=g_{m-1}} \right) \right\}_{i=1}^N { ( x i , − ∂ g ( x i ) ∂ L ( y i , g ( x i )) g = g m − 1 ) } i = 1 N 训练一个回归树G m ( x ) G_m(x) G m ( x ) 。在得到回归树后再去学习参数α \alpha α (Loss修正幅度),即
α m = arg min α L ( y , g m − 1 ( x ) + α G m ( x ) ) . \alpha_m=\argmin_\alpha\mathcal{L}(y,g_{m-1}(x)+\alpha G_m(x)). α m = α arg min L ( y , g m − 1 ( x ) + α G m ( x )) .
GBRT(梯度提升回归树)
对于回归问题:T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , y N ) } T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)\} T = {( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , y N )} ,回归树使用最小二乘损失:
L ( y , f ( x ) ) = 1 2 ( y − f ( x ) ) 2 \mathcal{L}(y,f(x))=\frac{1}{2}(y-f(x))^2 L ( y , f ( x )) = 2 1 ( y − f ( x ) ) 2
其负梯度恰为残差,故新的回归树就用于拟合残差。(仍然是加法模型:f m ( x ) = f m − 1 ( x ) + γ m ( x ) f_m(x)=f_{m-1}(x)+\gamma_m(x) f m ( x ) = f m − 1 ( x ) + γ m ( x ) )
初始化:f 0 ( x ) ≡ 1 N ∑ i = 1 N y i \displaystyle f_0(x)\equiv\dfrac{1}{N}\sum_{i=1}^N y_i f 0 ( x ) ≡ N 1 i = 1 ∑ N y i (取均值)。
GBCT(梯度提升分类树)
对于二分类问题:T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , y N ) } , y i = { 0 , 1 } T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)\},y_i=\{0,1\} T = {( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , y N )} , y i = { 0 , 1 } ,可以先套用GBRT模型,再将预测值转化为预测概率。
即将f ( x ) f(x) f ( x ) 转化为P ( y = 1 ∣ X = x ) P(y=1|X=x) P ( y = 1∣ X = x ) ,使用Logistic函数:
P ( y = 1 ∣ X = x ) ≜ p ( x ) = 1 1 + e − f ( x ) . P(y=1|X=x)\triangleq p(x)=\frac{1}{1+e^{-f(x)}}. P ( y = 1∣ X = x ) ≜ p ( x ) = 1 + e − f ( x ) 1 .
也就是说,在分类问题中,GBM学习的是“概率预测”。
对于此问题,损失函数使用交叉熵损失:
L ( y , p ) = − y log p − ( 1 − y ) log ( 1 − p ) \mathcal{L}(y,p)=-y\log p-(1-y)\log(1-p) L ( y , p ) = − y log p − ( 1 − y ) log ( 1 − p )
其衡量的是概率估计与真实标签的偏离程度。其负梯度为:− ∂ L ∂ f = − ∂ L ∂ p ⋅ ∂ p ∂ f = y − p -\dfrac{\partial\mathcal{L}}{\partial f}=-\dfrac{\partial\mathcal{L}}{\partial p}\cdot\dfrac{\partial p}{\partial f}=y-p − ∂ f ∂ L = − ∂ p ∂ L ⋅ ∂ f ∂ p = y − p ,同样恰好为残差。
XGBoost
XGBoost由陈天奇等于2015年正式提出(论文:XGBoost ),并在各类机器学习竞赛中崭露头角(在LLM出现之前)。
核心思想:在GBM的基础上进一步优化,让每棵小树f m ( t ) f_m(t) f m ( t ) 在优化损失函数的同时优化正则化项(即模型复杂度)。
算法核心则依然为贪心算法,即每次分枝的时候选择目标函数下降最大的分枝方式。其推导如下:
Obj root = ∑ i = 1 N L ( y i , y ^ i ( m − 1 ) + f m ( x i ) ) + ∑ k = 1 m Ω ( f k ) \text{Obj}_{\text{root}}=\sum_{i=1}^N\mathcal{L}\left(y_i,\hat{y}_i^{(m-1)}+f_m(x_i)\right)+\sum_{k=1}^m\Omega(f_k) Obj root = i = 1 ∑ N L ( y i , y ^ i ( m − 1 ) + f m ( x i ) ) + k = 1 ∑ m Ω ( f k )
其中Ω ( f k ) \Omega(f_k) Ω ( f k ) 为正则化项,表达式为
Ω ( f k ) = γ T k + 1 2 λ ∑ t = 1 T k c t k 2 \Omega(f_k)=\gamma T_k+\frac{1}{2}\lambda\sum_{t=1}^{T_k}c_{tk}^2 Ω ( f k ) = γ T k + 2 1 λ t = 1 ∑ T k c t k 2
其中T k T_k T k 为第k k k 棵树的叶子节点个数,c t k c_{tk} c t k 则表示每个叶子结点的输出值,这两个指标都可以控制模型的复杂度,防止过拟合。
下面对目标函数进行二阶泰勒展开(记f m ( x i ) f_m(x_i) f m ( x i ) 为c c c ):
Obj root = ∑ i = 1 N L ( y i , y ^ i ( m − 1 ) + c ) + ∑ k = 1 m Ω ( f k ) ≈ ∑ i = 1 N { L ( y i , y ^ i ( m − 1 ) ) + L ′ ( y i , y ^ i ( m − 1 ) ) c + 1 2 L ′ ′ ( y i , y ^ i ( m − 1 ) ) c 2 } + ∑ k = 1 m − 1 Ω ( f ^ k ) + Ω ( f m ) ≜ { ∑ i = 1 N g i } c + 1 2 { ∑ i = 1 N h i + λ } c 2 + γ \begin{aligned}
\text{Obj}_{\text{root}}&=\sum_{i=1}^N \mathcal{L}\left(y_i, \hat{y}_i^{(m-1)} + c\right)+\sum_{k=1}^m\Omega(f_k)\\
&\approx\sum_{i=1}^N \left\{ \mathcal{L}(y_i, \hat{y}_i^{(m-1)}) + \mathcal{L}'(y_i, \hat{y}_i^{(m-1)})c + \frac{1}{2}\mathcal{L}''(y_i, \hat{y}_i^{(m-1)})c^2 \right\}+ \sum_{k=1}^{m-1} \Omega(\hat{f}_k) + \Omega(f_m)\\
&\triangleq\left\{\sum_{i=1}^N g_i\right\}c+\frac{1}{2}\left\{\sum_{i=1}^Nh_i+\lambda\right\}c^2+\gamma
\end{aligned} Obj root = i = 1 ∑ N L ( y i , y ^ i ( m − 1 ) + c ) + k = 1 ∑ m Ω ( f k ) ≈ i = 1 ∑ N { L ( y i , y ^ i ( m − 1 ) ) + L ′ ( y i , y ^ i ( m − 1 ) ) c + 2 1 L ′′ ( y i , y ^ i ( m − 1 ) ) c 2 } + k = 1 ∑ m − 1 Ω ( f ^ k ) + Ω ( f m ) ≜ { i = 1 ∑ N g i } c + 2 1 { i = 1 ∑ N h i + λ } c 2 + γ
其中g i = ∂ L ( y i , y ^ i ( m − 1 ) ) ∂ y ^ i ( m − 1 ) , h i = ∂ 2 L ( y i , y ^ i ( m − 1 ) ) ∂ ( y ^ i ( m − 1 ) ) 2 \displaystyle g_i=\frac{\partial\mathcal{L}(y_i, \hat{y}_i^{(m-1)})}{\partial \hat{y}_i^{(m-1)}},h_i=\frac{\partial^2\mathcal{L}(y_i, \hat{y}_i^{(m-1)})}{\partial\left(\hat{y}_i^{(m-1)}\right)^2} g i = ∂ y ^ i ( m − 1 ) ∂ L ( y i , y ^ i ( m − 1 ) ) , h i = ∂ ( y ^ i ( m − 1 ) ) 2 ∂ 2 L ( y i , y ^ i ( m − 1 ) ) 。
将其看作关于变量c c c 的函数,则因为∑ i = 1 N h i + λ > 0 \displaystyle\sum_{i=1}^Nh_i+\lambda>0 i = 1 ∑ N h i + λ > 0 ,所以函数为开口向上的抛物线,最小取值
c ^ = arg min c Obj root = − ∑ i = 1 N g i ∑ i = 1 N h i + λ , min Obj root = ( ∑ i = 1 N g i ) 2 2 ( ∑ i = 1 N h i + λ ) + γ . \begin{aligned}
\hat{c}=\argmin_c\text{Obj}_{\text{root}}&=\frac{-\sum_{i=1}^Ng_i}{\sum_{i=1}^Nh_i+\lambda},\\
\min\text{Obj}_{\text{root}}&=\frac{(\sum_{i=1}^Ng_i)^2}{2(\sum_{i=1}^Nh_i+\lambda)}+\gamma.
\end{aligned} c ^ = c arg min Obj root min Obj root = ∑ i = 1 N h i + λ − ∑ i = 1 N g i , = 2 ( ∑ i = 1 N h i + λ ) ( ∑ i = 1 N g i ) 2 + γ .
由此得到分枝前后的信息增益为
1 2 { G left 2 H left + λ + G right 2 H right + λ − G root 2 H root + λ } − γ \frac{1}{2}\left\{\frac{G^2_{\text{left}}}{H_{\text{left}}+\lambda}+\frac{G^2_{\text{right}}}{H_{\text{right}}+\lambda}-\frac{G^2_{\text{root}}}{H_{\text{root}}+\lambda}\right\}-\gamma 2 1 { H left + λ G left 2 + H right + λ G right 2 − H root + λ G root 2 } − γ
基于此指标寻找信息增益最大的分枝方式即可。
精确贪心算法
其他细节
XGBoost在处理缺失值时,不需要进行剔除或插补,因为对于每一个特征,只对非缺失值排序,缺失值要么统一在左枝,要么统一在右枝,取决于损失函数的大小。
其他优化方法:
并行:将特征排序后以块的形式存储在内存中,在迭代中可用重复使用。虽然提升法必须串行,但是在处理每个特征时可用并行计算。
考虑数据量比较大,内存不够时,使用多线程,数据压缩,分片等方法有效地使用磁盘和读写数据。
Shrinkage:每次估计的新模型都乘以一个学习率,避免过拟合。
以上,课内《统计机器学习》课程的内容就完结了。总体上感觉就是“小而精”,和之前的《人工智能导论》的关系好比DFS和BFS的关系(maybe可看作互补)。
另外老师讲解的这些算法都是偏科研方向,比较注重建模和优化(导致有一大堆数学推导)。不过即便如此,机器学习算法本身也有些out of date了(LLM杀死比赛……或者说ML已经脱离主流)与其说取精通算法本身,不如说本课最大作用是探究模型的进化过程。
关于之后的计划,笔者决定先按照《机器学习方法》第一册内容补充一些课上没涉及到的算法(如朴素贝叶斯、最大熵模型、隐马尔可夫模型、条件随机场等),然后补充一些第二册(无监督学习)算法(如聚类、MCMC、LSA、LDA等)。【以上下学期之前完成】
然后无缝衔接下学期《深度学习》课程内容(完美!)