GBDT与xgBOOST代码复现

一、GBDT原理与应用

1.1 原理

GBDT由两部分组成,分别是GB(Gradient Boosting)和DT(Decison Tree)。DT采用CART的回归树,GB指的是沿着梯度方向,构造一系列的弱分类器函数,并以一定权重组合起来,形成最终决策的强分类器。

GBDT是一种基于集成思想的决策树模型,本质是基于残差学习。

特点在于:可处理各种类型的数据;有着较高的准确率;对异常值的鲁棒性强;不能并行训练数据

GBDT采用加法模型,通过不断减小训练过程产生的残差,以此对数据进行回归或分类。GBDT进行多轮迭代,每轮迭代产生一个弱分类器CART回归树,该分类器是在上一轮分类器的残差结果基础上训练得到的。对弱分类器的要求是低方差、高偏差(低方差保证模型不会过拟合+高偏差在训练过程中会减小,以此提高精度)。为了使损失函数尽可能快地减小,用损失函数的负梯度作为残差的近似值,然后去拟合CART回归树。

1.2 应用

基于GBDT的数据回归
基于GBDT的数据分类

代码实现

import CART_regression_tree #导入决策树
import numpy as np

def load_data(data_file):
    '''导入训练数据
    input:  data_file(string):保存训练数据的文件
    output: data(list):训练数据
    '''
    data_X = []
    data_Y = []
    f = open(data_file)
    for line in f.readlines():
        sample = []
        lines = line.strip().split("\t")
        data_Y.append(float(lines[-1]))
        for i in range(len(lines) - 1):
            sample.append(float(lines[i]))  # 转换成float格式
        data_X.append(sample)
    f.close()
    return data_X, data_Y


class GBDT_RT(object):
    '''GBDT回归算法类
    '''
    def __init__(self):
        self.trees = None  ##用于存放GBDT的树
        self.learn_rate = learn_rate  ## 学习率,防止过拟合
        self.init_value = None  ##初始数值
        self.fn = lambda x: x #定义lambda函数,相当于把值赋给self.fn

    def get_init_value(self, y):
        '''计算初始数值为平均值
        input:y(list):样本标签列表
        output:average(float):样本标签的平均值
        '''
        average = sum(y) / len(y) #求平均值
        return average

    def get_residuals(self, y, y_hat):
        '''计算样本标签标签与预测列表的残差
        input:y(list):样本标签列表
              y_hat(list):预测标签列表
        output:y_residuals(list):样本标签标签与预测列表的残差
        '''
        y_residuals = []
        for i in range(len(y)):
            y_residuals.append(y[i] - y_hat[i])
        return y_residuals

    def fit(self, data_X, data_Y, n_estimators, learn_rate, min_sample, min_err):
        '''训练GBDT模型
        input:self(object):GBDT_RT类
              data_X(list):样本特征
              data_Y(list):样本标签
              n_estimators(int):GBDT中CART树的个数
              learn_rate(float):学习率
              min_sample(int):学习CART时叶节点的最小样本数
              min_err(float):学习CART时最小方差
        '''
        ## 初始化预测标签和残差
        self.init_value = self.get_init_value(data_Y)

        n = len(data_Y)
        y_hat = [self.init_value] * n  ##初始化预测标签
        y_residuals = self.get_residuals(data_Y, y_hat)

        self.trees = []
        self.learn_rate = learn_rate
        ## 迭代训练GBDT
        for j in range(n_estimators):
            idx = range(n)
            X_sub = [data_X[i] for i in idx]  ## 样本特征列表
            residuals_sub = [y_residuals[i] for i in idx]  ## 标签残差列表

            tree = CART_regression_tree.CART_RT(X_sub, residuals_sub, min_sample, min_err).fit()
            res_hat = []  ##残差的预测值
            for m in range(n):
                res_hat.append(CART_regression_tree.predict(data_X[m], tree))
            ## 计算此时的预测值等于原预测值加残差预测值
            y_hat = [y_hat[i] + self.learn_rate * res_hat[i] for i in idx]
            y_residuals = self.get_residuals(data_Y, y_hat)
            self.trees.append(tree)

    def GBDT_predict(self, xi):
        '''预测一个样本
        '''
        return self.fn(
            self.init_value + sum(self.learn_rate * CART_regression_tree.predict(xi, tree) for tree in self.trees))

    def GBDT_predicts(self, X):
        '''预测多个样本
        '''
        return [self.GBDT_predict(xi) for xi in X]


def error(Y_test, predict_results):
    '''计算预测误差
    input:Y_test(list):测试样本标签
          predict_results(list):测试样本预测值
    output:error(float):均方误差
    '''
    Y = np.mat(Y_test)
    results = np.mat(predict_results)
    error = np.square(Y - results).sum() / len(Y_test)
    return error


if __name__ == '__main__':
    print("------------- 1.load data ----------------")
    X_data, Y_data = load_data("sine.txt")
    X_train = X_data[0:150]
    Y_train = Y_data[0:150]
    X_test = X_data[150:200]
    Y_test = Y_data[150:200]
    print('------------2.Parameters Setting-----------')
    n_estimators = 4
    learn_rate = 0.5
    min_sample = 30
    min_err = 0.3
    print("--------------3.build GBDT ---------------")
    gbdt_rt = GBDT_RT()
    gbdt_rt.fit(X_train, Y_train, n_estimators, learn_rate, min_sample, min_err)
    print('-------------4.Predict Result--------------')
    predict_results = gbdt_rt.GBDT_predicts(X_test)
    print('--------------5.Predict Error--------------')
    error = error(Y_test, predict_results)
    print('Predict error is: ', error)

二、XGBOOST

三个核心部分:集成算法本身,用于集成的弱评估器,以及应用中的其他过程。

2.1 XGBOOST的重要参数

1.eta[默认0.3]
通过为每一颗树增加权重,提高模型的鲁棒性。
典型值为0.01-0.2。

2.min_child_weight[默认1]
决定最小叶子节点样本权重和。
这个参数可以避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。
但是如果这个值过高,则会导致模型拟合不充分。

3.max_depth[默认6]
这个值也是用来避免过拟合的。max_depth越大,模型会学到更具体更局部的样本。
典型值:3-10

4.max_leaf_nodes
树上最大的节点或叶子的数量。
可以替代max_depth的作用。
这个参数的定义会导致忽略max_depth参数。

5.gamma[默认0]
在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma指定了节点分裂所需的最小损失函数下降值。 这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关。

6.max_delta_step[默认0]
这参数限制每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。
但是当各类别的样本十分不平衡时,它对分类问题是很有帮助的。

7.subsample[默认1]
这个参数控制对于每棵树,随机采样的比例。
减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。
典型值:0.5-1

8.colsample_bytree[默认1]
用来控制每棵随机采样的列数的占比(每一列是一个特征)。
典型值:0.5-1

9.colsample_bylevel[默认1]
用来控制树的每一级的每一次分裂,对列数的采样的占比。
subsample参数和colsample_bytree参数可以起到相同的作用,一般用不到。

10.lambda[默认1]
权重的L2正则化项。(和Ridge regression类似)。
这个参数是用来控制XGBoost的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。

11.alpha[默认1]
权重的L1正则化项。(和Lasso regression类似)。
可以应用在很高维度的情况下,使得算法的速度更快。

12.scale_pos_weight[默认1]
在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛。

2.2 XGBoost原理

XGBoost底层实现了GBDT算法,并对GBDT算法做了一系列优化:

对目标函数进行了泰勒展示的二阶展开,可以更加高效拟合误差。
提出了一种估计分裂点的算法加速CART树的构建过程,同时可以处理稀疏数据。
提出了一种树的并行策略加速迭代。
为模型的分布式算法进行了底层优化。

下面使用sklearn接口下的xgboost帮助我们处理分类问题
iris数据集算是多分类,注意一下使用的目标函数objective='multi:softmax’

from sklearn.datasets import load_iris
import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 加载样本数据集
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=12343)

# 训练模型
model = xgb.XGBClassifier(max_depth=5, learning_rate=0.1, n_estimators=160, silent=True, objective='multi:softmax')
model.fit(X_train, y_train)
# max_depth:构建树的深度,越大越容易过拟合
# silent=, 设置成1则没有运行信息输出,最好是设置为0,是否在运行升级时打印消息

# 对测试集进行预测
y_pred = model.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('accuracy:%2.f%%' % (accuracy * 100))

# 显示重要特征
plot_importance(model)
plt.show()

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值