《机器学习公式推导与代码实现》chapter12-XGBoost

news2024/11/24 17:55:35

《机器学习公式推导与代码实现》学习笔记,记录一下自己的学习过程,详细的内容请大家购买作者的书籍查阅。

XGBoost

从算法精度、速度和泛化能力等性能指标来看GBDT,仍然有较大的优化空间。XGBoost是一种基于GBDT的顶级梯度提升模型。相较于GBDTXGBoost的最大特性在于对损失函数展开到二阶导数,使得梯度提升树模型更能逼近其真实损失。
XGBoost全称eXtreme Gradient Boosting,即极限梯度提升树,由陈天奇在其论文XGBoost:A Scalable Tree Boosting System中提出。

1 XGBoost介绍

XGBoost本质上仍属于GBDT算法,但在算法精度速度泛化能力上均要优于传统的GBDT算法。从算法精度上来看,XGBoost通过将损失函数展开到二阶导数,使得其更能逼近真是损失;从算法速度上来看,XGBoost使用了加权分位数sketch稀疏感知算法这两个技巧,通过缓存优化模型并行来提高算法速度;从算法泛化能力上来看,通过对损失函数加入正则化项、加性模型中设置缩减率列抽样等方法,来防止模型过拟合。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 XGBoost算法实现

相较于GBDT,XGBoost的主要变化在于损失函数二阶导数信息增益计算叶子结点得分计算等方面,与上一章GBDT使用回归树不同,本章以分类树为例。
使用的决策树为CART,CART实现。
整个实现过程概括为:从损失函数出发,进行二阶泰勒展开并重新定义一棵决策树,通过对叶子结点分组得到最终的损失函数形式,最后求得最优点和最优取值,并得到叶子结点的分裂标准。

from cart import BinaryDecisionTree
import numpy as np

# XGBoost单棵树类
class XGBoost_Single_Tree(BinaryDecisionTree):

    def node_split(self, y): # 结点分裂方法
        feature = int(np.shape(y)[1]/2) # 中间特征所在列
        y_true, y_pred = y[:, :feature], y[:, feature:] # 左子树为真实值,右子树为预测值
        return y_true, y_pred

    def gain(self, y, y_pred): # 信息增益计算方法
        Gradient = np.power((y * self.loss.gradient(y, y_pred)).sum(), 2) # 梯度计算(一阶导数)
        Hessian = self.loss.hess(y, y_pred).sum() # 黑塞矩阵(二阶导数)
        return 0.5 * (Gradient / Hessian)

    def gain_xgb(self, y, y1, y2): # 树分裂增益计算-式(12-22)
        y_true, y_pred = self.node_split(y)
        y1, y1_pred = self.node_split(y1)
        y2, y2_pred = self.node_split(y2)
        true_gain = self.gain(y1, y1_pred)
        false_gain = self.gain(y2, y2_pred)
        gain = self.gain(y_true, y_pred)
        return true_gain + false_gain - gain

    def leaf_weight(self, y): # 计算叶子结点最优权重 w*
        y_true, y_pred = self.node_split(y)
        gradient = np.sum(y_true * self.loss.gradient(y_true, y_pred), axis=0) # 梯度计算
        hessian = np.sum(self.loss.hess(y_true, y_pred), axis=0) # 黑塞矩阵计算
        leaf_weight = gradient / hessian
        return leaf_weight

    # 树拟合方法
    def fit(self, X, y):
        # 信息增益和叶子节点得分计算都用到了损失函数二阶导数信息
        self.impurity_calculation = self.gain_xgb
        self._leaf_value_calculation = self.leaf_weight
        super(XGBoost_Single_Tree, self).fit(X, y)
# XGBoost分类损失函数
class Sigmoid: # 定义Sigmoid类
    def __call__(self, x):
        return 1 / (1 + np.exp(-x))
    
    def gradient(self, x):
        return self.__call__(x) * (1 - self.__call__(x))

# 定义logit损失
class LogisticLoss:
    def __init__(self):
        sigmoid = Sigmoid()
        self._func = sigmoid
        self._grad = sigmoid.gradient
    
    # 定义Logit损失
    def loss(self, y, y_pred):
        y_pred = np.clip(y_pred, 1e-15, 1, 1e-15) # 截断函数
        p = self._func(y_pred)
        return y * np.log(p) + (1 - y) * np.log(1 - p)
    
    # 定义一阶梯度
    def gradient(self, y, y_pred):
        p = self._func(y_pred)
        return -(y - p)
    
    # 定义二阶梯度
    def hess(self, y, y_pred):
        p = self._func(y_pred)
        return p * (1 - p)
from utils import cat_label_convert

# XGBoost模型
class XGBoost:
    def __init__(self, n_estimators=300, learning_rate=0.001, min_samples_split=2, min_gini_impurity=999, max_depth=2):
        self.n_estimators = n_estimators # 树的棵数
        self.learning_rate = learning_rate # 学习率
        self.min_samples_split = min_samples_split # 结点分裂最小样本数
        self.min_gini_impurity = min_gini_impurity # 结点最小基尼不纯度
        self.max_depth = max_depth # 树最大深度
        self.loss = LogisticLoss() # 用于分类的对数损失,回归任务定义平方损失
        self.estimators = [] # 初始化分类树列表

        for _ in range(n_estimators): # 遍历构造每一棵决策树
            tree = XGBoost_Single_Tree(
                min_samples_split=self.min_samples_split,
                min_gini_impurity=self.min_gini_impurity,
                max_depth = max_depth,
                loss = self.loss
            )
            self.estimators.append(tree)

    def fit(self, X, y): # XGBoost拟合方法
        y = cat_label_convert(y) # one-hot
        y_pred = np.zeros(np.shape(y))
        for i in range(self.n_estimators): # 拟合每一棵树后将结果累加
            estimator = self.estimators[i]
            y_true_pred = np.concatenate((y, y_pred), axis=1)
            estimator.fit(X, y_true_pred)
            iter_pred = estimator.predict(X)
            y_pred -= np.multiply(self.learning_rate, iter_pred)

    def predict(self, X): # XGBoost预测方法
        y_pred = None
        for estimator in self.estimators: # 遍历预测
            iter_pred = estimator.predict(X)
            if y_pred is None:
                y_pred = np.zeros_like(iter_pred)
            y_pred -= np.multiply(self.learning_rate, iter_pred)
        y_pred = np.exp(y_pred) / np.sum(np.exp(y_pred), axis=1, keepdims=True)
        y_pred = np.argmax(y_pred, axis=1)
        return y_pred
# XGBoost测试
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn import datasets # 导入鸢尾花数据集
data = datasets.load_iris()
X, y = data.data, data.target # 获取输入输出
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=43)  # 数据集划分
clf = XGBoost() # 创建xgboost分类器
clf.fit(X_train, y_train) # 模型拟合
y_pred = clf.predict(X_test) # 模型预测
accuracy = accuracy_score(y_test, y_pred) # 准确率评估
print ("Accuracy: ", accuracy)
Accuracy:  0.9333333333333333

2 XGBoost原生库示例

XGBoost的作者陈天奇也提供了XGBoost原生的工业级官方库xgboost。
首先需要指定xgboost模型训练的各种参数,包括提升树类型、任务类型、类别数量和树的最大深度等,然后将原始数据类型转换为xgboost的DMatrix数据类型,接着进行模型训练和预测,最后评估分类准确率,并绘制特征重要性图,可视化地呈现每个特征在模型中的重要性评分。

import xgboost as xgb
from xgboost import plot_importance # 导入绘制特征重要性模块函数
from matplotlib import pyplot as plt

# 设置模型参数
params = {
    'booster': 'gbtree',
    'objective': 'multi:softmax',
    'num_class': 3,
    'gamma': 0.1,
    'max_depth': 2,
    'lambda': 2,
    'subsample': 0.7,
    'colsample_bytree': 0.7,
    'min_child_weight': 3,
    'eta': 0.001,
    'seed': 1000,
    'nthread': 4,
}

dtrain = xgb.DMatrix(X_train, y_train) # 转换为xgb数据集格式Dmatrix
num_rounds = 200 # 树的棵数
model = xgb.train(params, dtrain, num_rounds)
y_pred = model.predict(xgb.DMatrix(X_test)) # 对测试集进行验证
accuracy = accuracy_score(y_test, y_pred)
print(accuracy)
plot_importance(model)
plt.show()
0.9666666666666667

在这里插入图片描述
笔记本_Github地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/666496.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

提炼关键词是一种能力

提炼关键词,是一种能力 交流或写文字,都要提炼关键词 趣讲大白话:抓重点 【趣讲信息科技202期】 **************************** 大脑的信息通过关键词调取 语言的传达,通过关键词传递关键信息 搜索要输入关键词 人工智能也要提示关…

tensorRT 模型部署

讲解: 模型经过训练之后终端部署之前都会有一个模型转换的过程,英伟达也不例外, 模型转换的过程其实是一个模型优化与加速的过程,里面包含着引擎对模型的一系列操作, 比如说layer 级的融合,权重的量化、图层…

PMP考试中多少分算通过?

PMP考试成绩一般是在考完后 6-8 周开始出成绩,像之前318的PMP考试,5月8号晚上已经开始出成绩了,还没出来的也会陆续出来。 【如何查询成绩】 1、输入网址(PMI官网,不知道网址的私戳),点击 Log …

消息中间件中常见问题

如何保证消息不丢失 MQ的用途 异步发送(验证码,短信,邮件)MySQL,ES,Redis之间的数据同步分布式事务削峰填谷 消息可能丢失的环境 消息在产生端时候生产端挂掉,消息未到达交换机&#xff0c…

【新车评分】降价三万,排名第一的蔚来ES7更能打了?

去年6月,蔚来上市了该品牌第四款SUV车型——ES7,共分为两个版本标准版和首发版,发售价分别为46.8万和54.8万元。 不过近期蔚来以砍掉部分车主权益,换来了全系车型3万元的降价,ES7的起售价也来到了43.8万元和51.8万元。…

【Python 随练】利用递归方法求 5!

题目 利用递归方法求 5!。 简介 在本篇博客中,我们将使用递归方法解决一个数学问题:计算一个数的阶乘。阶乘是指将从1到某个正整数n的所有整数相乘,通常表示为n!。我们将介绍递归的概念,并给出一个完整的代码示例来计算给定数的…

P-Tuning v2: 与微调性能相等的提示性优化

原文:P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks 作者: Xiao Liu1,2 , Kaixuan Ji1 代码: https://github.com/THUDM/P-tuning-v2 一、简介 二、准备工作 ---- 2.1 NLU的任务 ---- 2.2 提示优化 三、P-Tu…

什么是云原生?

目录 1.简介2.云元素的四要素 1.简介 云原生:是一种构建和运行应用程序的方法,是一套技术体系和方法论。云原生(CloudNative)是一个组合词,Cloud Native: Cloud 表示应用程序位于云中,而不是…

基于OpenMV 循迹小车 + WIFI无线图传

文章目录 一、工程环境二、OpenMV1. 色块选定2. 色块识别3. 串口通信4. WiFi无线图传5. 代码汇总 三、MSP430四、视频演示 一、工程环境 1. 软件 OpenMV IDECode Composer StudioMicrosoft Edge 2. 硬件 MSP430F5529OpenMV4 H7及其 WiFi拓展板视觉云台旋转编码器、oled显示…

国际原油期货怎么开户?国际原油期货开户流程是什么?

随着国际原油期货交易的大众化,国际原油期货交易的入市门槛也在逐渐降低,使越来越多的国际原油期货交易爱好者能够参与到这个交易市场中。很多朋友可能对国际原油期货开户有很多的疑问,是不是很繁琐?需不需要很多的证明文件&#…

论文解读 | 皮质电图系统与软机器人致动器的完美结合

原创 | 文 BFT机器人 01 研究内容 主要研究内容是关于一种电皮层图谱系统的部署,该系统使用软体机器人致动器。论文详细介绍了该系统的制造和实验方法,并提供了相关的图表和参考文献。该系统的设计旨在提高电皮层图谱系统的灵活性和可植入性&#xff0c…

vite+vue3+cesium环境搭建

1.创建一个Vite项目 npm create vitelatest 2.安装cesium插件:vite-plugin-cesium npm i cesium vite-plugin-cesium vite -D 3、配置vite.config.js import cesium from vite-plugin-cesium; export default defineConfig({ plugins: [vue(),cesium()] }) 4、清空…

软件测试技能,JMeter压力测试教程(二)

目录 前言 一、案例场景 二、登录请求 三、Json 提取器 四、关联请求 五、遇到的坑 前言 现在很多接口的登录是返回一个json数据,token值在返回的json里面,在jmeter里面也可以直接提取json里面的值 上一个接口返回的token作为下个接口的入参 一、…

Python基础(12)——Python字符串详解

Python基础(12)——Python字符串详解 文章目录 Python基础(12)——Python字符串详解课程:字符串目标一. 认识字符串1.1 字符串特征1.2 字符串输出1.3 字符串输入 二、下标2.1 快速体验 三、切片3.1 语法3.2 体验 四、常…

Generative Adversarial Network(生成对抗网络)

目录 Generative Adversarial Network(生成对抗网络) Basic Idea of GAN GAN as structured learning Can Generator learn by itself Can Discriminator generate Theory behind GAN Conditional GAN Generative Adversarial Network(…

SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计

文章目录 环境配置开发工具下载Vue前端模板前端项目启动前端说明及修改修改导航栏自定义菜单与子菜单增加导航标签功能 前端数据格式 B站视频讲解:2023全网最简单但实用的SpringBootVue前后端分离项目实战 不想看视频可浏览此文章笔记,比较详细 环境配置…

民族工业领军企业:大族激光全流程数字化增长路径揭秘

1.关于大族激光 大族激光科技产业集团(简称“大族激光”,股票代码 002008)于 1996 年创立、2004 年上市,是亚洲最大、世界排名前三的工业激光加工及自动化整体解决方案服务商,专业从事工业激光加工设备与自动化等配套…

Python面向对象编程2-面向过程的银行账号模拟程序 项目2.2 取款与查看余额

项目总目标:用面向过程思想设计一个简单的银行账号模拟程序。本次将迭代多个程序版本,每个版本都将添加更多功能。虽然这些程序没有达到发布的质量标准,但整个项目的目的是关注于代码如何与一个或多个银行账户的数据进行交互。 分析项目的必要…

MySQL8漏洞处理之小版本升级至8.0.33

MySQL低版本经常会出现一些漏洞,有些高危漏洞就得处理,以防未知风险。 一、漏洞描述 MySQL 安全漏洞(CVE-2023-21912)(CVE-2023-21980): Oracle MySQL 5.7.41 版本及之前版本和 8.0.32 版本及之前版本的 Client programs 组件存在安全漏洞。低权限攻击…

使用Channel的一些业务场景

使用Channel的一些业务场景 首先需要明确的就是,发送方才知道什么时候关闭 channel ,这个是比较符合逻辑的。 我们需要知道哪些情况会使 channel 发生 panic 关闭一个 nil 值会引发关闭一个已经关闭的 channel 会引发向一个已经关闭的 channel 发送数据…