当前位置: 首页 > news >正文

XGBoost

XGBoost

XGBoost(Extreme Gradient Boosting)全名叫 极端梯度提升树,XGBoost是集成学习方法的王牌,在Kaggle数据挖掘比赛中,大部分获胜者用了XGBoost。
XGBoost在绝大多数的 回归分类问题上表现的十分顶尖
可以理解为它是用来优化GBDT(梯度提升树)的,通过加入正则化项的方式,来解决 GBDT的过拟合问题的.

XGBoost算法思想

XGBoost 是对GBDT的改进:
  1. 求解损失函数极值时使用泰勒二阶展开
  2. 在损失函数中加入了正则化项
  3. XGB 自创一个树节点分裂指标。这个分裂指标就是从损失函数推导出来的。XGB 分裂树时考虑到了树的复杂度。
构建最优模型的方法是 最小化训练数据的损失函数
预测值和真实值经过某个函数计算出损失,并求解所有样本的平均损失,并且使得损失最小。这种方法训练得到的模型复杂度较高,很容易出现过拟合。因此,为了降低模型的复杂度,在损失函数中添加了正则化项,如下所示:
提高模型对未知数据的泛化能力。

XGboost的目标函数

XGBoost(Extreme Gradient Boosting)是对梯度提升树的改进,并且在损失函数中加入了正则化项。
目标函数的第一项表示整个强学习器的损失,第二部分表示强学习器中 K 个弱学习器的复杂度。
xgboost 每一个弱学习器的复杂度主要从两个方面来考量:
  1. γT 中的 T 表示一棵树的叶子结点数量,γ 是对该项的调节系数
  2. λ||w||
2 中的 w 表示叶子结点输出值组成的向量,λ 是对该项的调节系数
  • 模型复杂度的介绍
假设我们要预测一家人对电子游戏的喜好程度,考虑到年轻和年老相比,年轻更可能喜欢电子游戏,以及男性和女性相比,男性更喜欢电子游戏,故先根据年龄大小区分小孩和大人,然后再通过性别区分开是男是女,逐一给各人在电子游戏喜好程度上打分,如下图所示:
就这样,训练出了2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,所以:
  • 小男孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。
  • 爷爷的预测分数同理:-1 + 0.9 = -0.1。
具体如下图所示:
如下树tree1的复杂度表示为:
  • 泰勒公式展开
我们直接对目标函数求解比较困难,通过泰勒展开将目标函数换一种近似的表示方式。接下来对 y i(t-1) 进行泰勒二阶展开,得到如下近似表示的公式:
其中,g i 和 h i 的分别为损失函数的一阶导、二阶导:
  • 化简目标函数
我们观察目标函数,发现以下两项都是常数项,我们可以将其去掉。
为什么说是常数项呢?这是因为当前学习器之前的学习器都已经训练完了,可以直接通过样本得出结果。化简之后的结果为:
我们再将 Ω(f t) 展开,结果如下:
这个公式中只有 f t ,该公式可以理解为,当前这棵树如何构建能够降低损失。
  • 问题再次转换
我们再次理解下这个公式表示的含义:
  1. gi 表示每个样本的一阶导,hi 表示每个样本的二阶导
  2. ft(xi) 表示样本的预测值
  3. T 表示叶子结点的数目
  4. ||w||² 由叶子结点值组成向量的模
现在,我们发现公式的各个部分考虑的角度不同,有的从样本角度来看,例如:f t(x i) ,有的从叶子结点的角度来看,例如:T、||w|| 2。我们下面就要将其转换为相同角度的问题,这样方便进一步合并项、化简公式。我们统一将其转换为从叶子角度的问题:
例如:10 个样本,落在 D 结点 3 个样本,落在 E 结点 2 个样本,落在 F 结点 2 个样本,落在 G 结点 3 个样本
  1. D 结点计算: w1 * gi1 + w1 * gi2 + w1 * gi3 = (gi1 + gi2 + gi3) * w1
  2. E 结点计算: w2 * gi4 + w2 * gi5 = (gi4 + gi5) * w2
  3. F 结点计算: w3 * gi6 + w3 * gi6 = (gi6 + gi7) * w3
  4. G 节点计算:w4 * gi8 + w4 * gi9 + w4 * gi10 = (gi8 + gi9 + gi10) * w4
g i f t(x i) 表示样本的预测值,我们将其转换为如下形式:
  • wj 表示第 j 个叶子结点的值
  • gi 表示每个样本的一阶导
h if t2(x i) 转换从叶子结点的问题,如下:
λ||w|| 2 由于本身就是从叶子角度来看,我们将其转换一种表示形式:
我们重新梳理下整理后的公式,如下:
上面的公式太复杂了,我们令:
Gi 表示样本的一阶导之和,Hi 表示样本的二阶导之和,当确定损失函数时,就可以通过计算得到结果。
现在我们的公式变为:
  • 对叶子结点求导
此时,公式可以看作是关于叶子结点 w 的一元二次函数,我们可以对 w 求导并令其等于 0,可得到 w 的最优值,将其代入到公式中,即可再次化简上面的公式。
将 w j 代入到公式中,即可得到:
  • XGBoost的树构建方法
该公式也叫做 打分函数 (scoring function),它可以从树的损失函数、树的复杂度两个角度来衡量一棵树的优劣。
这个公式,我们怎么用呢?
当我们构建树时,可以用来选择树的最佳划分点。

结论

其过程如下:
  1. 对树中的每个叶子结点尝试进行分裂
  2. 计算分裂前 - 分裂后的分数:
    1. 如果gain > 0,则分裂之后树的损失更小,我们会考虑此次分裂
    2. 如果gain< 0,说明分裂后的分数比分裂前的分数大,此时不建议分裂
  3. 当触发以下条件时停止分裂:
    1. 达到最大深度
    2. 叶子结点样本数量低于某个阈值
    3. 等等...
1、通过损失函数+正则化来实现XGBoost(极端梯度提升树)优化GDBP(梯度提升树),
2、具体就是把公式使用泰勒公式展开,应用泰勒二阶展开式获取近似的公式
3、从样本角度转成叶子节点的角度打分是否分支

XGboost API

XGB的安装和使用
在sklean机器学习库中没有集成xgb。想要使用xgb,需要手工安装
pip install xgboost
可以在xgb的官网上查看最新版本: XGBoost Documentation — xgboost 3.1.0-dev documentation
XGB的编码风格
  • 支持非sklearn方式,也即是自己的风格
  • 支持sklearn方式,调用方式保持sklearn的形式
bst = XGBClassifier(n_estimators, max_depth, learning_rate, objective)

sklearn API参数

原生API参数

默认值

含义

说明

n_estimators

num_round

子学习器个数

boosting框架下的子学习器数量。在原生API中,该参数在train方法中定义,也即最大迭代次数

learning_rate

eta

0.3

学习率

用于限制子学习器的过拟合,提高模型的泛化能力,与n_estimators配合使用

verbosity

verbosity

1

是否输出详细信息

2是输出详细信息,1是偶尔输出,0是不输出

subsample

eta

0.3

样本子采样数

用于限制子学习器的过拟合,提高模型的泛化能力,与n_estimators配合使用

max_depth

max_depth

6

树的最大深度

对基学习器函数空间的正则化,一种预修剪手段

objective

objective

损失函数

自定义的损失函数,通过申明合适的损失函数来处理分类、回归和排序问题

booster

booster

gbtree

基学习器类型

xgboost中采用的基学习器,如梯度提升树'gbtree',梯度提升线性模型'gblinear'等

gamma

gamma

0

分裂阈值

即最小损失分裂,用来控制分裂遵循的结构分数提升下限阈值。

min_child_weight

min_child_weight

叶子节点最小权重

叶子节点允许的最小权重值(即节点中所有样本的二阶导数值之和),可视为是对叶子节点的正则化,是一种后剪枝的手段。

reg_alpha

alpha

0

L1正则化系数

对集成模型进行L1正则化(以子节点的个数为约束)的系数

reg_lambda

lambda

0

L2正则化系数

对集成模型进行L2正则化(以子节点权重w的平方和为约束)的系数

nthread

n_jobs

最大并发线程数

最大并发线程数

random_state

seed

随机种子

控制模型的随机性。

missing

missing

None

为缺失值进行标注

默认为None,即标注为np.nan。

红酒品质预测

数据集介绍
数据集共包含 11 个特征,共计 3269 条数据. 我们通过训练模型来预测红酒的品质, 品质共有 6 个各类别,分别使用数字: 1、2、3、4、5 来表示。
案例实现
导入需要的库文件
import joblib
import numpy as np
import xgboost as xgb
import pandas as pd
import numpy as np
from collections import Counter
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.model_selection import StratifiedKFold

  • 数据基本处理
def test01():
​
    # 1. 加载训练数据
    data = pd.read_csv('data/红酒品质分类.csv')
    x = data.iloc[:, :-1]
    y = data.iloc[:, -1] - 3
​
    # 2. 数据集分割
    x_train, x_valid, y_train, y_valid = train_test_split(x, y, test_size=0.2, stratify=y, random_state=22)
​
    # 3. 存储数据
    pd.concat([x_train, y_train], axis=1).to_csv('data/红酒品质分类-train.csv')
    pd.concat([x_valid, y_valid], axis=1).to_csv('data/红酒品质分类-valid.csv')

  • 模型基本训练
def test02():
    # 1. 加载训练数据
    train_data = pd.read_csv('data/红酒品质分类-train.csv')
    valid_data = pd.read_csv('data/红酒品质分类-valid.csv')
​
    # 训练集
    x_train = train_data.iloc[:, :-1]
    y_train = train_data.iloc[:, -1]
​
    # 测试集
    x_valid = valid_data.iloc[:, :-1]
    y_valid = valid_data.iloc[:, -1]
​
    # 2. XGBoost模型训练
    estimator = xgb.XGBClassifier(n_estimators=100,
                                  objective='multi:softmax',
                                  eval_metric='merror',
                                  eta=0.1,
                                  use_label_encoder=False,
                                  random_state=22)
    estimator.fit(x_train, y_train)
​
    # 3. 模型评估
    y_pred = estimator.predict(x_valid)
    print(classification_report(y_true=y_valid, y_pred=y_pred))
​
    # 4. 模型保存
    joblib.dump(estimator, 'model/xgboost.pth')

  • 模型参数调优
# 样本不均衡问题处理
from sklearn.utils import class_weight

classes_weights = class_weight.compute_sample_weight(class_weight='balanced',y=y_train)

# 训练的时候,指定样本的权重
estimator.fit(x_train, y_train,sample_weight = classes_weights)
y_pred = estimator.predict(x_valid)
print(classification_report(y_true=y_valid, y_pred=y_pred))
​
# 交叉验证,网格搜索
train_data = pd.read_csv('data/红酒品质分类-train.csv')
valid_data = pd.read_csv('data/红酒品质分类-valid.csv')
​
# 训练集
x_train = train_data.iloc[:, :-1]
y_train = train_data.iloc[:, -1]
​
# 测试集
x_valid = valid_data.iloc[:, :-1]
y_valid = valid_data.iloc[:, -1]
​
# 分层采样(一般结合网格搜索+交叉验证一起使用) 目的:避免过拟合,采样时,会让采样数据的个分类比例 保持 和元数据的 个分类比例 保持近似一致。
# 参1:采样的次数(类似于折数),shuffle:是否打乱,random_state: 随机种子。
spliter = StratifiedKFold(n_splits=5, shuffle=True)

# 2. 定义超参数
param_grid = {'max_depth': np.arange(3, 5, 1),
              'n_estimators': np.arange(50, 150, 50),
              'eta': np.arange(0.1, 1, 0.3)}
estimator = xgb.XGBClassifier(n_estimators=100,
                              objective='multi:softmax',
                              eval_metric='merror',
                              eta=0.1,
                              use_label_encoder=False,
                              random_state=22)
cv = GridSearchCV(estimator,param_grid,cv=spliter)
y_pred = cv.predict(x_valid)
print(classification_report(y_true=y_valid, y_pred=y_pred))

相关文章:

  • 1987-2023年各省进出口总额数据整理(含进口和出口)(无缺失)
  • 目标检测中归一化的目的?
  • 大模型agent的构建
  • Python高级——类的知识
  • 域渗透工具推荐:impacket
  • 第6关:部分快速排序-用分治法实现
  • 2.Linux基本指令(下)
  • conda报错activate没办法激活环境
  • 从TouchDriver Pro到Touchdriver G1,Weart触觉手套全系解析:XR交互的“真实触感”如何实现?
  • 【北京迅为】iTOP-RK3568开发板OpenHarmony系统南向驱动开发UART接口运作机制
  • 各种排序汇总
  • Linux驱动开发基础(can)
  • 文献检索与下指南
  • fetch,ajax,axios的区别以及使用
  • 【python】OpenCV—Template Matching
  • 数学建模 第三节
  • Python绘图技巧,主流绘图库
  • Day 21: 数组中的逆序对
  • Java Stream两种list判断字符串是否存在方案
  • 深度学习优化技术教程
  • 降水较常年同期少五成,安徽四大水利工程调水超11亿方应对旱情
  • 因存在安全隐患,福特公司召回约27.4万辆SUV
  • 7月纽约举办“上海日”,上海大剧院舞剧《白蛇》连演三场
  • 陕西省安康市汉阴县县长陈永乐已任汉阴县委书记
  • 国务院关税税则委员会关于调整对原产于美国的进口商品加征关税措施的公告
  • 专访|茸主:杀回UFC,只为给自己一个交代