3-6 决策树、CART树、GBDT、xgboost、lightgbm一些关键点梳理

article/2025/9/24 15:52:18

目录

1、决策树

2、CART树

2.1 CART分类树-输入样本特征;输出样本对应的类别(离散型)

2.2 CART回归树-输入样本特征;输出样本的回归值(连续型)

3、GBDT

3.1 提升树

3.2 GBDT

4、xgboost

4.1 损失函数及节点展开

4.2 精确贪心算法及相关近似算法

4.3 对于缺失值的处理和Shrinkage

4.4 系统设计(SYSTEM DESIGN)

 5、lightgbm

5.1 Histogram直方图算法

5.2 GOSS, Gradient-based One-Side Sampling,基于梯度的单边采样算法

5.3 EFB算法,Exclusive Feature Bundling,互斥特征绑定算法

参考了以下资料


1、决策树

树的节点代表样本的集合,通过筛选特征,将特征空间划分为互不相交的样本集合。经典的分类树算法,主要有ID3、C4.5、CART树(CART分类树、CART回归树)

(1)ID3、C4.5重点在于如何选取最优特征对样本进行划分;

(2)CART树,二叉树的结构,涉及最优特征的选择以及该特征下最优划分点的选择。

ID3决策树:计算最大信息增益的特征,对样本进行划分; 

C4.5决策树:计算最大信息增益率(也叫信息增益比)的特征,对样本进行划分。

ID3决策树、C4.5决策树输入为离散特征、输出为K分类的结果。

信息增益,也称集合D和特征A的互信息,公式: g(D,A) = H(D) - H(D| A)

其中,H(D)为当前集合的信息熵,信息熵越大说明信息不确定性越大,H(D|A)是特征A条件下集合D的信息熵(特征A下的条件熵);信息熵衡量信息的不确定性,信息增益衡量特征A对D不确定性减少的程度。H(D|A)越小,g(D,A)越大,特征更有利于分类。

通过信息熵定义,K为分类任务的类别个数,计算样本集D的信息熵,计算公式如下:

 H(D) = -\sum_{k=1}^{K}\frac{\left | C_{k} \right |}{\left | D \right |}log\frac{\left | C_{k} \right |}{\left | D \right |}         

特征A下的D的条件熵计算如下:其中,A特征有n个取值,通过每个特征取值对D样本进行划分,然后计算各划分子集的信息熵和

H(D|A) = \sum_{i=1}^{n}\frac{\left | D_{i} \right |}{\left | D \right |}H(D_{i})=-\sum_{i=1}^{n}\frac{\left | D_{i} \right |}{\left | D \right|}\sum_{k=1}^{K}\frac{\left | D_{ik} \right |}{\left | D_{i} \right |}log\frac{\left | D_{ik} \right |}{\left | D_{i} \right |}

信息增益率的引入考虑到,信息增益相近的情况下,某特征类别情况过多的情况容易产生过拟合等问题。因此,除以特征取值在D下的信息熵,信息增益率计算如下,n为A特征下特征取值的个数:

g_{R}(D,A) = \frac{g(D,A)}{H_{A}(D)},H_{A}(D)=-\sum_{i=1}^{n}\frac{\left | D_{i} \right |}{\left | D \right |}log\frac{\left | D_{i} \right |}{\left | D \right |}


2、CART树

CART树,名字叫分类与回归树(classification and regression tree, CART)。是二叉树的结构,对于离散和连续特征,都可以将样本通过特征的取值,划分到左右两个集合中。因此,原则上需要计算每个特征下每个特征取值的情况,从而选择最优划分点以及对应的特征。CART分类树和CART回归树的展开方式略有不同。

2.1 CART分类树-输入样本特征;输出样本对应的类别(离散型)

CART分类树采用基尼指数作为划分条件,基尼指数越大说明不确定性越小,计算公式如下:

Gini(D) = \sum_{i=1}^{K}p_{k}(1-p_{k})=1-\sum_{i=1}^{K}p_{k}^{2} = 1-\sum_{i=1}^{K}(\frac{\left | C_{k} \right |}{\left | D \right |})^{2},交叉熵是plogp,这里是p(1-p)

在特征A的条件下(特征取值a划分点下),集合D的基尼指数定义如下,书上都写成Gini(D,A),实际和H(D|A)的意思类似:

Gini(D,A=a) = \frac{\left | D_{1} \right |}{\left | D \right |}Gini(D_{1}) + \frac{\left | D_{2} \right |}{\left | D \right |}Gini(D_{2}),D_{1}\epsilon D_{R(A<=a)},D_{2}\epsilon D_{R(A>a)}

分类树最终叶子节点上,相同类别值最多 的类别对应 被划分集合 的类别。

2.2 CART回归树-输入样本特征;输出样本的回归值(连续型)

CART回归树通过最小化损失函数的方式来选择划分点,每个叶子节点集合对应的预测值为 使得被划分集合损失函数最小的回归值。CART回归树希望每个集合划分后,总损失函数值都能减小。

因此,选取最优特征及特征取值的划分点,如下:其中j代表特征,s代表特征的划分点,c1代表左子树使得左子树集合损失最小的回归值,c2代表右子树使得右子树集合损失最小的回归值

\underset{j,s}{min} [\underset{c_{1}}{min}\sum_{x_{i}\epsilon R_{1(j,s)}}loss(y^{i},c_{1})+\underset{c_{2}}{min}\sum_{x_{i}\epsilon R_{2(j,s)}}loss(y^{i},c_{2})]

里面的min求得左、右子树的损失最小以及c1、c2的值,外面的min保证求得整体最小损失值下的j和s。可以看出要算出候选的j、s的损失,需要先算出里面min的c1和c2。

如果loss(y^{i},c) = (y_{i}-c)^{2} 那么,c_{m} = \frac{1}{N_{m}}\sum_{x_{i}\epsilon R_{m}(j,s)}y_{i}


3、GBDT

        提升树、GBDT相关内容在李航的统计机器学习书中,讲的很简明。由于GBDT是提升树的一种,因此先简介提升树。基本参照李航书中的内容,然后简明扼要的在提一下关键点。

3.1 提升树

        提升树(boosting tree)就是boosting集成方法 + 基模型采用决策树。通过损失函数来度量模型拟合的好坏。希望每一次加入一棵决策树后,模型的预测值 与 标签 的损失最小。

        一般来说,对于分类问题,损失函数采用指数损失,基模型是二叉分类树;

        对于回归问题,损失函数采用平方,基模型是二叉回归树。

        当然损失函数也可以其他一般的形式。注意这里指的损失函数是指整个集成学习模型的损失

         提升树的关键在于这个损失函数的最小值怎么求(或者如何逼近)的问题,往损失函数最小值方向逼近的数值,就是新加决策树的label。

        采用平方误差损失的回归问题,每个树要拟合的值 = 残差 = - 梯度 ;这种情况每棵树要拟合的值就是当前模型和label的差,同时负梯度方向也意味着能够最快速到达损失函数最小值的方向。

        但是,并不是所有损失函数都能满足这样的性质,一般来说损失最小值在哪里不容易求出。只能通过每次从负梯度方向走一点,一步一步靠近。于是就有了梯度提升树。

3.2 GBDT

        GBDT每次让决策树拟合负梯度的数值,一点一点靠近损失函数的最小值。

        下图也是李航书上的截图,以回归问题为例,核心步骤就大致为3步:

(1)每一轮先算负梯度即(a),作为回归树的label;

(2)然后,回归树有label就能根据回归树的训练得到,叶子节点上挂了样本的回归树即(b);

(3)由于最终训练目的是让集成学习算法的损失最小,于是有了(c),算每个叶子节点上让损失最小的值作为这个节点的预测值。

 两个看似很重要,但是又看似很傻的疑惑:

(1)(a)中每一步残差怎么求?

答:GBDT中用当前预测值下的负梯度值来计算,也就是说损失函数定了,当前预测值定了,损失函数求导后当前预测值代入,然后加个负号,就OK了。加负号是因为,要损失函数的最小化方向是一阶导(梯度)的负方向。

(2)(b)这一步的回归树怎么展开?回归树本身的损失函数 和 整体集成学习模型损失 有什么关联吗?

答:可以看出如果按回归树展开(回归树的损失函数也就是回归树怎么展开其实没有硬性规定),回归树算出来叶子节点的预测值,未必和(c)算出来的一致。之所以算(c)这个式子,就是希望预测时候加上已经展开的回归树叶子节点的预测值,能让损失函数最小

        这两个问题实际是希望大家有所思考,并过渡到后续xgboost是什么做的,(a)和(c)这两个式子要干的事情,能不能结合起来?


4、xgboost

        xgboost采用CART回归树作为基分类器模型。上述已经介绍了GBDT的原理,那么:

(1)GBDT基分类器都是树模型,存在过拟合问题怎么办

(2)每个样本最终挂在回归树的叶子节点上面

(3)加上回归树叶子节点上面的预测值后,使得损失函数最小

GBDT每一步算负梯度后,用回归树展开叶子节点,而且回归树展开时每一个划分点上还要遍历样本算左右节点最优(回归树损失意义上的最优)的c1、c2。最终还是要算每个叶子节点在集成模型上损失值最小的节点预测值。回归树展开结果显然未必是最优的,可否直接建立样本划分和损失函数的关联呢?

通过 样本-叶子节点-损失的方式,样本组成叶子节点,叶子节点预测值决定集成模型损失,将损失函数由基于样本的求和,转换成基于叶子节点的求和。然后求极值。通过样本划分计算损失函数的大小。

4.1 损失函数及节点展开

xgboost还在GBDT的损失函数上,加了正则化项,将损失函数近似为二阶泰勒展开,将目标函数(损失函数+正则化项)基于样本形式的求和,转换为基于叶子节点预测值的求和形式(下图第一行变为第四行),求得损失函数的极值。这里每个样本gi和hi是已知的

        通过以上步骤就能将每个叶子节点样本集合的最小损失函数和叶子节点预测值Wj直接求得,通过划分点可直接得到划分以后两个区域的最小损失和。Gain衡量划分后损失函数减少量,Gain越大说明划分点越好。

4.2 精确贪心算法及相关近似算法

        这里的划分点依旧需要暴力枚举,枚举每个特征下的每个特征取值的划分点。每个叶子节点递归的采用这个过程去划分叶子节点中的样本,作为左右两部分求损失和。直到停止条件,CART树最大深度限制、最大叶子节点数量限制、Gain小于一定阈值等

 上图,算法1就是精确贪心算法,求每个树节点,每个特征下每个特征取值的划分,求Gain最大的那个划分点。但是,如果样本的特征维度过高、特征取值数量过多,展开效率还是很低。因此,在特征维度和特征取值这两方面进行筛选或取值的压缩,以减少计算量。

 上图,算法2就是特征层面的近似算法,对树的每个节点或者每层节点展开时,只采样部分特征

对于特征数值方面的压缩,采用按比例分桶的策略,通过hi作为权重的按权划分,以及设置阈值等策略。同时,还有特征数值全局分桶策略(对树的每个节点采用同样的分桶策略)、局部策略(按层采用分桶策略)

4.3 对于缺失值的处理和Shrinkage

上图,为缺失值处理的方式,在某个特征下,部分样本没有特征的取值(但样本都是有gi和hi的),这是就把缺失值样本都放左边或者都放右边,比较Gain的大小

        至于Shrinkage,就是每个基模型都会有个学习率,就如同神经网络中梯度下降的学习率(learning rate)

4.4 系统设计(SYSTEM DESIGN)

        在系统设计方面,还有xgboost还在特征并行计算(设计了一种block结构)、cache优化和数据读取优化。充分利用了CPU、磁盘、内存、缓存的资源。多线程读取数据,并行处理特征


 5、lightgbm

        整体原理和xgboost相同,可见看到xgboost的计算量主要受三方面的影响:

(1)样本特征的取值个数

(2)样本的特征维度

(3)叶子节点上样本的数量

        lightgbm分别从这每个方面有所优化。

5.1 Histogram直方图算法

        对每个特征下的特征取值进行了合并,减少了特征取值的情况,减少了特征的划分点。

1、替代XGBoost的预排序算法
2、将连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图,即将连续特征值离散化到k个bins上(比如k=255)候选分裂点数量 = k-1
3、当遍历一次数据后,直方图累积了需要的统计量(同一个bin里面gi、hi求和),然后根据直方图的离散值,遍历寻找最优的分割点
4、XGBoost需要遍历所有离散化的值,LightGBM只要遍历k个直方图的值

5.2 GOSS, Gradient-based One-Side Sampling,基于梯度的单边采样算法

        单边采样,只对梯度绝对值较小的样本按照一定比例进行采样,而保留了梯度绝对值较大的样本。减少了叶子节点样本的计算量。

5.3 EFB算法,Exclusive Feature Bundling,互斥特征绑定算法

        数据集中通常会有大量的稀疏特征(大部分为0,少量为非0)EFB算法可以通过对某些特征的取值重新编码,将多个互斥的特征绑定为一个新的特征,减少了特征的计算数量。


参考了以下资料

1、李航统计机器学习第二版

2、躺懂XGBoost,学不会来打我(doge)_哔哩哔哩_bilibili

3、树模型(六):XGBoost_雪伦的专栏-CSDN博客_xgboost

4、Xgboost原版论文:XGBoost: A Scalable Tree Boosting System:链接https://dl.acm.org/doi/pdf/10.1145/2939672.2939785


http://chatgpt.dhexx.cn/article/StEyWjoe.shtml

相关文章

CART树回归

说明&#xff1a;本博客是学习《python机器学习算法》赵志勇著的学习笔记&#xff0c;其图片截取也来源本书。 基于树的回归算法是一类基于局部的回归算法&#xff0c;通过将数据集切分成多份&#xff0c;在每一份数据中单独建模。与局部加权线性回归不同的是&#xff0c;基于…

剪枝、cart树

一、剪枝 1. 为什么要剪枝 在决策树生成的时候&#xff0c;更多考虑的是训练数据&#xff0c;而不是未知数据&#xff0c;这会导致过拟合&#xff0c;使树过于复杂&#xff0c;对于未知的样本不准确。 2. 剪枝的依据——通过极小化决策树的损失函数 损失函数的定义为&#x…

【机器学习】决策树——CART分类回归树(理论+图解+公式)

&#x1f320; 『精品学习专栏导航帖』 &#x1f433;最适合入门的100个深度学习实战项目&#x1f433;&#x1f419;【PyTorch深度学习项目实战100例目录】项目详解 数据集 完整源码&#x1f419;&#x1f436;【机器学习入门项目10例目录】项目详解 数据集 完整源码&…

CART树(分类回归树)

主要内容 &#xff08;1&#xff09;CART树简介 &#xff08;2&#xff09;CART树节点分裂规则 &#xff08;3&#xff09;剪枝 --------------------------------------------------------------------------------------------------------------------- 一、简介 CART…

CART树

算法概述 CART(Classification And Regression Tree)算法是一种决策树分类方法。 它采用一种二分递归分割的技术&#xff0c;分割方法采用基于最小距离的基尼指数估计函数&#xff0c;将当前的样本集分为两个子样本集&#xff0c;使得生成的的每个非叶子节点都有两个分支。因此…

Pytorch之view,reshape,resize函数

对于深度学习中的一下数据&#xff0c;我们通常是要变成tensor格式&#xff0c;并且需要对其调整形状&#xff0c;很多时候我们往往只关注view之后的结果&#xff08;比如输出的尺寸&#xff09;&#xff0c;而不关心过程。但有时候还是要关注一下这个到底是怎么变换过来的&…

OpenCV-Python图像处理:插值方法及使用resize函数进行图像缩放

☞ ░ 前往老猿Python博客 https://blog.csdn.net/LaoYuanPython ░ 图像缩放用于对图像进行缩小或扩大&#xff0c;当图像缩小时需要对输入图像重采样去掉部分像素&#xff0c;当图像扩大时需要在输入图像中根据算法生成部分像素&#xff0c;二者都会利用插值算法来实现。 一…

vector的resize函数和reserve函数

博客原文&#xff1a;C基础篇 -- vector的resize函数和reserve函数_VampirEM_Chosen_One的博客-CSDN博客&#xff0c;写的特别好&#xff0c;谢谢原博主。 正文&#xff1a; 对于C的vector容器模板类&#xff0c;存在size和capacity这样两个概念&#xff0c;可以分别通过vect…

OpenCV 图片尺寸缩放——resize函数

文章目录 OpenCV中的缩放&#xff1a;resize函数代码案例 OpenCV中的缩放&#xff1a; 如果要放大或缩小图片的尺寸&#xff0c;可以使用OpenCV提供的两种方法&#xff1a; resize函数&#xff0c;是最直接的方式&#xff1b;pyrUp&#xff0c;pyrDown函数&#xff0c;即图像…

OpenCV的resize函数优化

背景 在使用OpenCV做图像处理的时候&#xff0c;最常见的问题是c版本性能不足&#xff0c;以resize函数为例来说明&#xff0c;将size为[864,1323,3]的函数缩小一半&#xff1a; Mat img0;gettimeofday(&t4, NULL);cv::resize(source, img0, cv::Size(cols_out,rows_out)…

C++ | resize函数的用法

最近在leetcode用C刷题&#xff0c;刚遇到一题需要给重新弄一个容器&#xff0c;并给容器初始化。新建容器要在private类中声明resize函数用来初始化preSum容器。 resize函数是C中序列式容器的一个共性函数&#xff0c;vv.resize(int n,element)表示调整容器vv的大小为n&#x…

opencv的resize函数

一、Opencv官方文档中resize的描述&#xff1a; resize Resizes an image. C: void resize(InputArray src, OutputArray dst, Size dsize, double fx0, double fy0, int interpolationINTER_LINEAR ) Python: cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) …

resize()函数

resize()&#xff0c;设置大小&#xff08;size&#xff09;; reserve()&#xff0c;设置容量&#xff08;capacity&#xff09;; size()是分配容器的内存大小&#xff0c;而capacity()只是设置容器容量大小&#xff0c;但并没有真正分配内存。 打个比方&#xff1a;正在建造…

OpenCV 图像缩放:cv.resize() 函数详解

目录 系列前言API函数详解参数列表缩放方式其一缩放方式其二两种方式的优先级关于插值方式 扩展 —— 相关函数 系列前言 这个系列是我第一个想要更下去的系列。每篇会全面介绍一个 OpenCV 函数&#xff0c;会给出 API 和示例。示例主要是用 Python 去写&#xff0c;但是 Open…

安卓中的几种线程间通信方式

一&#xff1a;Handler实现线程间的通信 andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片&#xff0c;当它下载完成后会发送消息给主线程&#xff0c;这个消息是通过绑定在主线程的Handler来传递的。 在Android&#xff0c;这里的…

Java中的线程通信的几种方式

Java中的线程间通信是指不同线程之间相互协作&#xff0c;以完成一些复杂的任务或实现某些功能的过程。线程间通信主要包括两个方面&#xff1a;线程之间的互斥和同步&#xff0c;以及线程之间的数据共享和通信。Java提供了多种方式来实现线程间通信&#xff0c;本文将介绍Java…

创建线程的四种方式 线程通信

文章目录 1.1 创建线程1.1.1 创建线程的四种方式1.1.2 Thread类与Runnable接口的比较1.1.3 Callable、Future与FutureTask 1.2 线程组和线程优先级1.3 Java线程的状态及主要转化方法1.4 Java线程间的通信1.4.1 等待/通知机制1.4.2 信号量1.4.3 管道 1.1 创建线程 1.1.1 创建线…

【多线程间几种通信方式】

一、使用 volatile 关键字 基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想。大致意思就是多个线程同时监听一个变量&#xff0c;当这个变量发生变化的时候 &#xff0c;线程能够感知并执行相应的业务。这也是最简单的一种实现方式 代码案例 package com.han…

线程之间的通信方式

前言 我只是个搬运工&#xff0c;尊重原作者的劳动成果&#xff0c;本文来源下列文章链接&#xff1a; https://zhuanlan.zhihu.com/p/129374075 https://blog.csdn.net/jisuanji12306/article/details/86363390 线程之间为什么要通信&#xff1f; 通信的目的是为了更好的协…

Java线程间的通信方式

文章目录 线程间通信的定义一、等待—通知&#xff08;1&#xff09;等待—通知机制的相关方法&#xff1a;&#xff08;2&#xff09;注意事项&#xff1a;&#xff08;4&#xff09;notify()方法的核心原理&#xff08;5&#xff09;等待—通知机制的经典范式&#xff08;6&a…