当前位置: 代码迷 >> 综合 >> 机器篇——集成学习(七) 细说 XGBoost 算法
  详细解决方案

机器篇——集成学习(七) 细说 XGBoost 算法

热度:56   发布时间:2023-12-15 08:47:47.0

返回主目录

返回集成学习目录

上一章:机器篇——集成学习(六) 细说 GBDT 算法

下一章:机器篇——集成学习(八) 细说 ball49_pred 项目(彩票预测)

 

本小节,细说 XGBoost 算法,下一小节细说 ball49_pred 项目

 

论文参考以下链接: XGBoost: A Scalable Tree Boosting System

 

二. 具体算法

7. XGBoost 算法(Extreme Gradient Boostin, XGBoost)

   XGBoost 是 GB 算法的一种高效实现。XGBoost 中的基学习器除了可以是 CART(gbtree),也可以是线性分类器(gblinear)。

    (1). XGBoost 是一种监督学习算法,它实现了一个称为增强的过程,以产生准确的模型。

          监督学习的常用目标函数,通常包含两个部分:训练误差 + 正则化

                     

                :为损失函数,度量模型预测值和真实值的误差。

                               

                               平方损失函数:

                                      

                                交叉熵损失函数:

                                      

                                       为分类数,特别地,当  时,为 二分类的交叉熵损失函数:

                                            

                                 logistic 损失函数:

                                       

                :为正则化项,度量模型的复杂度,避免过拟合。常用的正则化有  正则化。

                                正则:

                                正则:

 

    (2). 模型融合

     一棵 CART 往往过于简单,而无法有效地进行预测,因此更加高效的是使用多个 CART 进行融合,使用集成的方法提升预测效果。

     ①. 假设有两棵回归树,进行融合预测结果,公式为:

                

               :为树的棵数

              :为第  棵树对于输入  输出的得分

              :为相应函数

              :为相应函数空间

     ②. 目标函数:

               

                :为损失函数。

 

    (3). 模型训练

     ①. 假设每次迭代生成一棵树,则训练目标函数可以写成:

                 

                 :为第  步迭代的预测值。

     ②. 迭代关系:

              

              

              

              

     ③. 训练目标函数可以写成:

              

                             

            对于第  步来说,  是已知的,则:

               

     ④. 如果  使用平方损失函数,则

              

                        

                 

            其中,对于第  步来说, 也是常数。

            则目标函数可化为:

                

                :为残差。

     ⑤. 泰勒展开

      a. 泰勒展开公式:

            在  处有  阶导数

                   

                         

      b.  目标函数:

                        

            令 ,  则 

                      

      c. 其中  和  为常数项。

          由于目标是让这个目标函数最小化,所以常数项并没有什么用,去掉常数项后,得到的目标函数:

                

     ⑥. 对于平方损失函数

                 

                 

 

    (4). 模型正则化项

     ①. 如何衡量一棵树的正则化项,为此,首先对 CART 树作另一番定义:

               

     ②. 定义的解释

           一棵树有  个叶子节点,这  个叶子节点的值组成了一个  维向量 , 是一个映射,用来将样本映射成 1 到  的某个值。也就是把它分到某个叶子节点, 其实就代表了 CART 树的结构。 自然就是这棵树对样本  的预测值了。

     ③. XGBoost 的正则化项

               

      a.  和  为 XGBoost 中的两个超参

      b.  越大,表示越希望获得结构简单的树,因为此时对较多叶子节点的树惩罚越大。

      c.  越大,也是希望获得结构越简单的树,因为此时对  惩罚越大。

     

    (5). 简化目标函数

     ①. 令 

                 

                                

     ②. 对于第  棵 CART 树的某一个确定的结构(可用  表示),所有的  和  都是正确的。而且  中各叶子节点的值  之间是相互独立的。因此,可求出各个叶子节点的最佳值以及此时目标函数的值:

               

               

               :最佳树结构的最佳叶子权重

                         

                         

                         

                         

                         :为学习率

                         :为反向梯度

                          的最佳值就是负的梯度乘以一个权重系数,该系数类似于随机梯度下降中的学习率。当  越大时,这个系数越小,也就是学习率越小; 越大,代表在该点附近梯度变化非常剧烈。

               :表示这棵树的结构有多好。值越小,代表的结构越好。也就是说,它是衡量第  棵 CART 树的结构好坏的标准。该值仅仅是用来衡量结构的好坏,与叶子节点的值可是无关的。 和  和  和  有关,而它们又和树的结构  有关,与叶子节点的值没有任何关系。

     

    (6). 最优目标函数

     在实践中,贪婪地种植这棵树

     ①. 从树深度为 0

     ②. 对每棵树的叶子节点尝试添加分裂。目标是添加拆分后的变化。

     ③. 对于每个节点,枚举所有特性。

     ④. 时间复杂度增加树的深度

               

               :为左子树节点的分数

               :为右子树节点的分数

               :为不分割时树节点的分数

               :为加入新的叶子节点引入的复杂度代价。

               

               

                          

               Gain 值为分裂后的值减去分裂前的值。

 

    (7). XGBoost 的小结

     ①. XGBoost 是对 GBDT 进行的优化。GBDT 在优化中只用到了一阶导数信息,而 XGBoost 则对代价函数进行了二阶泰勒展开,并同时用到了一阶和二阶导数,所以 XGBoost 的效率相较于 GBDT 大大的提高,并且 XGBoost 由于可以并行计算一阶和二阶导数,所以 XGBoost 可以并行建树。

     ②. XGBoost 的代价函数里加入了正则项,用于控制模型的复杂度。

     ③. 对于缺失值的处理。对于特征的值有缺失的样本,XGBoost 可以自动学习出它的分裂方向。XGBoost 对于缺失值能预先学习一个默认的分裂方向。

     

    (8). 代码演示

   代码的操作和之前的 随机森林,GBDT 一样的,利用网格搜索,寻找出较优的参数,来进行模型训练,预测。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# ============================================
# @Time     : 2020/01/14 21:50
# @Author   : WanDaoYi
# @FileName : xgboost_demo.py
# ============================================import os
import numpy as np
import pandas as pd
from sklearn import metrics
from sklearn.model_selection import GridSearchCV, train_test_split
from xgboost.sklearn import XGBClassifierimport matplotlib.pyplot as plt
import matplotlib
# 用于解决画图中文乱码
font = {"family": "SimHei"}
matplotlib.rc("font", **font)class XGBoostDemo(object):def __init__(self):self.base_path = os.getcwd()self.data_path_last = "data_info/car.csv"self.data_path = os.path.join(self.base_path, self.data_path_last)self.x_train, self.x_val, self.y_train, self.y_val = self.read_data()pass# 获取数据集def read_data(self):# 读取数据文件data_info = pd.read_csv(self.data_path, encoding="gbk")print(data_info.head())print("data_info_shape: {}".format(data_info.shape))# 划分数据为训练集和验证集x = data_info.values[:, : -1]y = data_info.values[:, -1]x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=0.3)print("x_train_shape: {}".format(x_train.shape))return x_train, x_val, y_train, y_valpassdef best_estimators_depth(self):# np.arange 可以生成 float 类型,range 只能生成 int 类型best_param = {'n_estimators': range(10, 201, 5),'max_depth': range(1, 20, 1)}best_gsearch = GridSearchCV(estimator=XGBClassifier(learning_rate=0.1,gamma=0,subsample=0.8,colsample_bytree=0.8,objective='binary:logistic',nthread=4,min_child_weight=5,seed=27),param_grid=best_param, scoring='roc_auc', iid=False, cv=10)best_gsearch.fit(self.x_train, self.y_train)print("best_param:{0}".format(best_gsearch.best_params_))print("best_score:{0}".format(best_gsearch.best_score_))# best_param: {'max_depth': 7, 'n_estimators': 45}# best_score: 0.9627551020408163return best_gsearch.best_params_passdef best_lr_gamma(self):# np.arange 可以生成 float 类型,range 只能生成 int 类型best_param = {'learning_rate': np.arange(0.1, 1.1, 0.1),'gamma': np.arange(0.1, 5.1, 0.2)}best_gsearch = GridSearchCV(estimator=XGBClassifier(n_estimators=45,max_depth=7,# learning_rate=0.1,# gamma=0,subsample=0.8,colsample_bytree=0.8,objective='binary:logistic',nthread=4,min_child_weight=5,seed=27),param_grid=best_param, scoring='roc_auc', iid=False, cv=10)best_gsearch.fit(self.x_train, self.y_train)print("best_param:{0}".format(best_gsearch.best_params_))print("best_score:{0}".format(best_gsearch.best_score_))# best_param: {'gamma': 4.500000000000001, 'learning_rate': 0.6}# best_score: 0.9671996144784749return best_gsearch.best_params_passdef best_subsmaple_bytree(self):# np.arange 可以生成 float 类型,range 只能生成 int 类型# 调整subsample(行),colsample_bytree(列)best_param = {'subsample': np.arange(0.1, 1.1, 0.1),'colsample_bytree': np.arange(0.1, 1.1, 0.1)}best_gsearch = GridSearchCV(estimator=XGBClassifier(n_estimators=45,max_depth=7,learning_rate=0.6,gamma=4.5,# subsample=1.0,# colsample_bytree=0.8,objective='binary:logistic',nthread=4,min_child_weight=5,seed=27),param_grid=best_param, scoring='roc_auc', iid=False, cv=10)best_gsearch.fit(self.x_train, self.y_train)print("best_param:{0}".format(best_gsearch.best_params_))print("best_score:{0}".format(best_gsearch.best_score_))# best_param: {'colsample_bytree': 0.8, 'subsample': 0.9}# best_score: 0.9680867346938775return best_gsearch.best_params_passdef best_nthread_weight(self):# np.arange 可以生成 float 类型,range 只能生成 int 类型best_param = {'nthread': range(1, 20, 1),'min_child_weight': range(1, 20, 1)}best_gsearch = GridSearchCV(estimator=XGBClassifier(n_estimators=45,max_depth=7,learning_rate=0.1,gamma=4.3,subsample=0.9,colsample_bytree=0.8,objective='binary:logistic',# nthread=4,# min_child_weight=5,seed=27),param_grid=best_param, scoring='roc_auc', iid=False, cv=10)best_gsearch.fit(self.x_train, self.y_train)print("best_param:{0}".format(best_gsearch.best_params_))print("best_score:{0}".format(best_gsearch.best_score_))# best_param: {'min_child_weight': 2, 'nthread': 1}# best_score: 0.9648386521025202return best_gsearch.best_params_passdef best_seek(self):# np.arange 可以生成 float 类型,range 只能生成 int 类型best_param = {'seed': range(1, 500, 1)}best_gsearch = GridSearchCV(estimator=XGBClassifier(n_estimators=45,max_depth=7,learning_rate=0.1,gamma=4.3,subsample=0.9,colsample_bytree=0.8,nthread=1,min_child_weight=2,# seed=27,objective='binary:logistic'),param_grid=best_param, scoring='roc_auc', iid=False, cv=10)best_gsearch.fit(self.x_train, self.y_train)print("best_param:{0}".format(best_gsearch.best_params_))print("best_score:{0}".format(best_gsearch.best_score_))# best_param: {'seed': 134}# best_score: 0.9773406154065825return best_gsearch.best_params_pass# 较好的 模型参数 进行训练def best_param_xgboost(self):best_model = XGBClassifier(n_estimators=45,max_depth=7,learning_rate=0.1,gamma=4.3,subsample=0.9,colsample_bytree=0.8,nthread=1,min_child_weight=2,seed=134,objective='binary:logistic')best_model.fit(self.x_train, self.y_train)y_pred = best_model.predict(self.x_val)acc_score = metrics.accuracy_score(self.y_val, y_pred)print("acc_score: {}".format(acc_score))print("score: {}".format(best_model.score(self.x_val, self.y_val)))print("AUC Score: {}".format(metrics.roc_auc_score(self.y_val, y_pred)))y_proba = best_model.predict_proba(self.x_val)# 预测为 0 的概率y_zero = y_proba[:, 0]# 预测为 1 的概率y_one = y_proba[:, 1]print("AUC Score2: {}".format(metrics.roc_auc_score(self.y_val, y_one)))# 得到误判率、命中率、门限fpr, tpr, thresholds = metrics.roc_curve(self.y_val, y_one)# 计算aucroc_auc = metrics.auc(fpr, tpr)# 对ROC曲线图正常显示做的参数设定# 用来正常显示中文标签, 上面设置过# plt.rcParams['font.sans-serif'] = ['SimHei']# 用来正常显示负号plt.rcParams['axes.unicode_minus'] = Falseplt.plot(fpr, tpr, label='{0}_AUC = {1:.5f}'.format("xgboost", roc_auc))plt.title('ROC曲线')plt.xlim([-0.05, 1.05])plt.ylim([-0.05, 1.05])plt.legend(loc='lower right')plt.plot([0, 1], [0, 1], 'r--')plt.ylabel('命中率: TPR')plt.xlabel('误判率: FPR')plt.show()passif __name__ == "__main__":demo = XGBoostDemo()# demo.best_estimators_depth()# demo.best_lr_gamma()# demo.best_subsmaple_bytree()# demo.best_nthread_weight()# demo.best_seek()demo.best_param_xgboost()pass

 

在代码中,我们不难发现,xgboost 利用 二阶求导,迭代次数明显下降了很多,而且,精度也提高了。xgboost,在目前的这集成学习里面,算是比较顶级的方法。所以,在生产当中,如果需要用到机器学习中的集成学习方法,我们一般优先选择 xgboost 算法来对业务进行实现。

 

在接下来下一章,我将用实例,讲解现实生产中,用xgboost 进行 训练和预测。

 

 

 

                 

 

返回主目录

返回集成学习目录

上一章:机器篇——集成学习(六) 细说 GBDT 算法

下一章:机器篇——集成学习(八) 细说 ball49_pred 项目(彩票预测)