梯度提升树算法原理与python实战——机器学习笔记之集成学习PartⅣ

* * *  The Machine Learning Noting Series  * * *

目录

1 梯度提升算法原理

       梯度提升算法的原理

       梯度提升优化参数的过程

2 梯度提升回归树

3 梯度提升分类树

4 用python实现梯度提升算法

1 梯度提升算法原理

梯度提升树采用向前式分步可加建模方式,每次迭代仅需估计当前模型,而且每个模型进入“联合投票委员会”时不会影响之前的模型。在迭代过程中基于损失函数,采用梯度下降法,找到使损失函数下降最快的模型。

迭代过程中,每个新加入的模型(“联合投票委员会”)都是用于修正当前预测值的增量函数(incremental functions),会不断调整预测值,从而使得迭代预测值不断接近真实值。

梯度提升算法的原理

梯度下降法通常是用于估计复杂模型参数优化的一种优化方法。为了便于说明,假设有函数 f(w)=w²+1,现需要求解 f(w) 取最小值时的 w 的值。此简单函数可以直接求导求解,而当函数较为复杂时,采用的梯度下降法,计算 f(w) 在w处的导数并不断更新来求解,具体为:

① 取初始值w(0)=4, 计算 f(w) 在w=4时的导数:f'(w=4)=8>0. 此处 f 递增,因此只有减小w取值才能得到更小的f(也就是说,f' 的符号决定了对w的更新方向)。

② 确定了w更新方向之后,需进一步确定更新的步伐Δw,这样便可得到一个更新的w:

w(1)=w(0)+\Delta w=w(0)-\rho \left [ \frac{\partial f(w)}{\partial w} \right ]_{w=w(0)}

其中,ρ称为学习率,显然若f'越接近0(即越接近最低点),则w每次更新的幅度就会越小。随着w的不断更新,f逐渐逼近曲线的最小值,最终w=w_{opt}为最优解,这就是梯度下降法的优化过程。

梯度提升优化参数的过程

f_{b}(X_{i})为第b次迭代的预测结果,h_{b}\left ( X,\alpha _{b} \right )为基础学习器(“联合投票委员会”中的模型成员),\alpha _{b}为基础学习器的参数集合,系数\beta _{b}决定基础学习器对预测结果的实际影响大小,因此,一个梯度下降优化过程为:

f_{b}(X_{i})=f_{b-1}(X_{i})+\beta _{b}h_{b}\left ( X,\alpha _{b} \right )

按照梯度下降的思路,\beta _{b}h_{b}\left ( X_{i},\alpha _{b} \right )取决于损失函数L\left ( y_{i},f(X_{i}) \right )f_{b-1}(X_{i})处的负梯度(一阶导数)和学习率ρ(假设对每个样本Xi的倒数是已知的):

\beta _{b}h_{b}\left ( X_{i},\alpha _{b} \right )=-\rho _{b}\cdot \left [ \frac{\partial L\left ( y_{i},f(X_{i}) \right )}{\partial f(X_{i})} \right ]_{f(X_{i})=f_{b-1}(X_{i})}

尽管当前模型h的参数\alpha _{b}\beta _{b}是未知的,但可参照最小二乘法求解在-\left [ \frac{\partial L\left ( y_{i},f(X_{i}) \right )}{\partial f(X_{i})} \right ]_{f(X_{i})=f_{b-1}(X_{i})}\beta h\left ( X_{i},\alpha \right )离差平方和最小下时参数:

\alpha _{b}=\underset{\alpha ,\beta }{arg}min\sum_{i=1}^{N}\left [-\left [ \frac{\partial L\left ( y_{i},f(X_{i}) \right )}{\partial f(X_{i})} \right ]_{f(X_{i})=f_{b-1}(X_{i})}- \beta h\left ( X_{i},\alpha \right )\right ]^{2}

\widetilde{y_{i}}=-\left [ \frac{\partial L\left ( y_{i},f(X_{i}) \right )}{\partial f(X_{i})} \right ]_{f(X_{i})=f_{b-1}(X_{i})},则\alpha _{b}=\underset{\alpha ,\beta }{arg}min\sum_{i=1}^{N}\left [\widetilde{y_{i}}- \beta h\left ( X_{i},\alpha \right )\right ]^{2}。一般称\widetilde{y}为伪响应变量(pseudo response)。

此外,学习率\rho _{b}可通过线搜索(line research)获得:

\rho _{b}=\underset{\rho}{arg}min\sum_{i=1}^{N}L ( y_{i},f_{b-1}(X_{i})+\rho h_{b}\left ( X_{i},\alpha _{b} \right ))

因此,梯度提升算法的一般步骤为:

 2 梯度提升回归树

梯度提升回归树用于回归预测:

① 损失函数定义为平方损失: L\left ( y_{i},f(X_{i}) \right )=\frac{1}2{}\left [y_{i}-f(X_{i} \right ]^{2},于是伪响应变量就是当前残差\widetilde{y_{i}}=y_{i}-f(X_{i})

② 基于损失函数的定义,上述梯度提升法的三步中的ρ即为β。

 3 梯度提升分类树

梯度提升分类树用于分类预测,这里讨论输出变量为-1和1时的二分类情况

① 损失函数定义为:L\left ( y_{i},f(X_{i}) \right )=log(1+e^{-2y_{i}f(X_{i})}),此损失函数为负二项对数似然(Negative Binomial Log-Likelihood)损失,其中f(X_{i})=\frac{1}{2}ln\left [ \frac{P(y_{i}=1\mid X_{i})}{P(y_{i}=-1\mid X_{i})} \right ],于是,伪响应变量为\widetilde{y_{i}}=-\left [ \frac{\partial L\left ( y_{i},f(X_{i}) \right )}{\partial f(X_{i})} \right ]_{f(X)=f_{b-1}(X)}=\frac{2y_{i}}{1+e^{2y_{i}f_{b-1}(X_{i})}};

②学习率通过线搜索获得:

\rho _{b}=\underset{\rho}{arg}min\sum_{i=1}^{N} log(1+e^{-2y_{i}(f_{b-1}(X_{i})+\rho h\left ( X_{i},\alpha _{b} \right )})

 4 用python实现梯度提升算法

进行梯度提升树和AdaBoost预测的对比。

#本章需导入的模块
import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings(action = 'ignore')
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False
from sklearn.model_selection import train_test_split,KFold,cross_val_score
from sklearn import tree
import sklearn.linear_model as LM
from sklearn import ensemble
from sklearn.datasets import make_classification,make_circles,make_regression
from sklearn.metrics import zero_one_loss,r2_score,mean_squared_error,accuracy_score
import xgboost as xgb
N=1000
X,Y=make_regression(n_samples=N,n_features=10,random_state=123)
X_train, X_test, Y_train, Y_test = train_test_split(X,Y,train_size=0.70, random_state=123)

B=300
dt_stump = tree.DecisionTreeRegressor(max_depth=1, min_samples_leaf=1)
TrainErrAdaB=np.zeros((B,))
TestErrAdaB=np.zeros((B,))
adaBoost = ensemble.AdaBoostRegressor(base_estimator=dt_stump,n_estimators=B,loss= 'square',random_state=123)
adaBoost.fit(X_train,Y_train)
for b,Y_pred in enumerate(adaBoost.staged_predict(X_train)):
    TrainErrAdaB[b]=1-r2_score(Y_train,Y_pred) 
for b,Y_pred in enumerate(adaBoost.staged_predict(X_test)):
    TestErrAdaB[b]=1-r2_score(Y_test,Y_pred) 

GBRT=ensemble.GradientBoostingRegressor(loss='ls',n_estimators=B,max_depth=1,min_samples_leaf=1,random_state=123)
GBRT.fit(X_train,Y_train)
TrainErrGBRT=np.zeros((B,))
TestErrGBRT=np.zeros((B,))
for b,Y_pred in enumerate(GBRT.staged_predict(X_train)):
    TrainErrGBRT[b]=1-r2_score(Y_train,Y_pred)
for b,Y_pred in enumerate(GBRT.staged_predict(X_test)):
    TestErrGBRT[b]=1-r2_score(Y_test,Y_pred) 

GBRT0=ensemble.GradientBoostingRegressor(loss='ls',n_estimators=B,max_depth=3,min_samples_leaf=1,random_state=123)
GBRT0.fit(X_train,Y_train)
TrainErrGBRT0=np.zeros((B,))
TestErrGBRT0=np.zeros((B,))
for b,Y_pred in enumerate(GBRT0.staged_predict(X_train)):
    TrainErrGBRT0[b]=1-r2_score(Y_train,Y_pred) 
for b,Y_pred in enumerate(GBRT0.staged_predict(X_test)):
    TestErrGBRT0[b]=1-r2_score(Y_test,Y_pred) 

plt.plot(np.arange(B),TrainErrAdaB,linestyle='--',label="AdaBoost回归树(训练)",linewidth=0.8)
plt.plot(np.arange(B),TestErrAdaB,linestyle='--',label="AdaBoost回归树(测试)",linewidth=2)
plt.plot(np.arange(B),TrainErrGBRT,linestyle='-',label="梯度提升回归树(训练)",linewidth=0.8)
plt.plot(np.arange(B),TestErrGBRT,linestyle='-',label="梯度提升回归树(测试)",linewidth=2)
plt.plot(np.arange(B),TrainErrGBRT0,linestyle='-.',label="复杂梯度提升回归树(训练)",linewidth=0.8)
plt.plot(np.arange(B),TestErrGBRT0,linestyle='-.',label="复杂梯度提升回归树(测试)",linewidth=2)
plt.title("梯度提升回归树和AdaBoost回归树")
plt.xlabel("弱模型个数")
plt.ylabel("误差")
plt.legend()

 可见,在此例模拟中,梯度提升树效果好于其他集成算法,因为它具有更低的误差。

参考文献

《Python机器学习 数据建模与分析》,薛薇 等/著

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值