【机器学习笔记28】GBDT提升树

【参考资料】
【1】《统计学习方法》8.4
【2】lightgbm源码 LightGBM/examples/python-guide/simple_example

备注:近期用到lightbgm,回过头再好好看看提升树方面的知识点:)

一 Adaboost算法

输入: 训练数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) } T=\{(x_1, y_1), (x_2, y_2),...,(x_N, y_N)\} 其中 x i X R n x_i \in X \subseteq R^n y i Y = { 1 , 1 } y_i \in Y = \{-1, 1\}

第一步: 初始化训练数据的权值分布,有:
D 1 = ( w 11 , . . . . , w 1 i , . . . , w 1 N ) D_1=(w_{11}, ...., w_{1i}, ..., w_{1N}) ,其中 w 1 i = 1 N w_{1i}= \dfrac{1}{N} ,表示第一次划分训练数据,将其划分为N份,每份的全职为1/N。

第二步:基于划分完的训练数据进行训练

2.1 对划分出的每份训练数据计算一个基本分类器 G m ( x ) G_m(x)
2.2 计算 G m ( x ) G_m(x) 的训练误差:
e m = P ( G m ( x i ) y i ) = i = 1 N w m i I ( G m ( x i ) y i ) e_m=P(G_m(x_i) \ne y_i)=\sum\limits_{i=1}^{N}w_{mi}I(G_m(x_i) \ne y_i)
2.3 计算 G m ( x ) G_m(x) 的系数
a m = 1 2 l o g 1 e m e m a_m=\dfrac{1}{2}log\dfrac{1 - e_m}{e_m}
2.4 更新训练数据集的权值
D m + 1 = ( w m + 1 , 1 , . . . , w m + 1 , N ) D_{m+1}=(w_{m+1, 1}, ..., w_{m+1, N})
w m + 1 , i = w m i Z m e x p ( a m y i G m ( x i ) ) w_{m+1, i}=\dfrac{w_{mi}}{Z_m}exp(-a_my_iG_m(x_i))
其中Z是规范化因子 Z m = i = 1 N w m i e x p ( a m y i G m ( x i ) ) Z_m=\sum\limits_{i=1}^{N}w_{mi}exp(-a_my_iG_m(x_i))

第三步: 构建一个基本分类器的线性组合
f ( x ) = m = 1 M a m G m ( x ) f(x)=\sum\limits_{m=1}^{M}a_mG_m(x)

二 提升树

提升树的模型定义如下:
f M ( x ) = m = 1 M T ( x ; Θ m ) f_M(x)=\sum\limits_{m=1}^{M}T(x;\Theta_m) ,表示M个子树分类器, Θ m \Theta_m 是这个分类树的参数,M为树的个数

第一步:初始化 f 0 ( x ) = 0 f_0(x)=0
第二步:对M个子树计算残差:
2.1 对于训练数据划分的J个不相交的区域,某棵树(回归树)可以表示为
T ( x ; Θ ) = j = 1 J c j I ( x R j ) T(x;\Theta)=\sum\limits_{j=1}^{J}c_jI(x \in R_j) ,这里 c j c_j 是该树在这个区域输出的常量

备注:这里的算法依次计算1~M棵决策树,每棵决策树都会遍历J个区域计算损失

2.2 计算残差
r m i = y i f m 1 ( x i ) r_{mi}=y_i - f_{m-1}(x_i) ,备注:从m-1次计算第m次
第三步:将残差作为训练数据进行下一次分割,学习成一个新的回归树;
第四步: f M ( X ) = m = 1 M T ( x ; Θ m ) f_M(X)=\sum\limits_{m=1}^{M}T(x;\Theta_m)

举例

《统计学习方法》例题8.2

在这里插入图片描述

第一步:考虑分割点1.5, 2.5, …,9.5,依据下述公式计算损失最小:
min c 1 R 1 ( y i c 1 ) 2 + min c 2 R 2 ( y i c 2 ) 2 \min_{c1}\sum\limits_{R_1}(y_i - c_1)^2 + \min_{c2}\sum\limits_{R_2}(y_i - c_2)^2 ,得到结果如下:
在这里插入图片描述

由上表可知,这一次最优分割在6.5,即 R 1 = { 1 , 2 , 3 , 4 , 5 , 6 } R 2 = { 7 , 8 , 9 } R_1=\{1,2,3,4,5,6\} \quad R_2=\{7,8,9\} ,相应的 c 1 = 6.24 c 2 = 8.91 c_1=6.24 \quad c_2=8.91

此时得到回归树 f 1 ( x ) = T 1 ( x ) f_1(x)=T_1(x)
T 1 ( x ) = { 6.24 , x < 6.5 8.91 , x 6.5 T_1(x) = \begin{cases} 6.24, & x < 6.5 \\ 8.91, & x \ge 6.5 \end{cases}

第二步:计算上面这课回归树的残差值
在这里插入图片描述

第三步:在此残差值基础上继续计算后续的决策树,例如:
在这里插入图片描述

第四步: 将各个决策树累加起来形成最终的决策树
f 6 ( x ) = T 1 ( x ) + T x ( x ) + . . . + T 6 ( x ) f_6(x)=T_1(x) + T_x(x) + ... + T_6(x)

三 梯度提升

梯度提升树是将残差值得计算方法做了修改,利用损失函数的负梯度在当前模型下的值作为残差值得近似,如下:
[ L ( y , f ( x i ) f ( x i ) ] f ( x ) = f m 1 ( x ) -[\dfrac{\partial L(y, f(x_i)}{\partial f(x_i)}]_{f(x)=f_{m-1}(x)}

四 GBT回归的例子(基于lightbgm)
# -*- coding: utf-8 -*-
import numpy  as np
import matplotlib.pyplot as plt
import lightgbm as lgb
import pandas as pd
from sklearn.model_selection import train_test_split

train = pd.read_csv('../01.data/datasets/studentscores.csv', header=None, sep=',', dtype=float)
test = pd.read_csv('../01.data/datasets/test.csv', header=None, sep=',', dtype=float)


"""
由学习时间和性别来预测分数,随机构造的数据完全没有意思。。。。。。。
2.5,21,1
5.1,47,1
3.2,27,0
8.5,75,0
3.5,30,1
"""

x_train = train.drop(1, axis=1)
y_train = train.drop([0,2], axis=1)
x_test  = test.drop(1, axis=1)
y_test  = test.drop([0,2], axis=1)

lgb_train = lgb.Dataset(x_train, y_train)
lgb_eval = lgb.Dataset(x_test, y_test, reference=lgb_train)


params = {
    'boosting_type': 'gbdt',
    'objective': 'regression',   
    'metric': {'l2', 'l1'},
    'num_leaves': 16,
    'learning_rate': 0.05,
     'min_data':1, #数据量太少的时候加这个参数
    'feature_fraction': 0.9,
    'bagging_fraction': 0.8,
    'bagging_freq': 5,
    'verbose': 0
}

print('Starting training...')

# train
gbm = lgb.train(params,
                lgb_train,
                num_boost_round=4,
                valid_sets=lgb_eval,
                early_stopping_rounds=2)

y_pred = gbm.predict(x_test, num_iteration=gbm.best_iteration)

from sklearn.metrics import mean_squared_error

print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5) #The rmse of prediction is: 23.752816735400195

猜你喜欢

转载自blog.csdn.net/Fredric_2014/article/details/83716656