决策树 & GBDT & XGBoost & LightGBM

一、决策树

1. 决策树有一个很强的假设:

    信息是可分的,否则无法进行特征分支

2. 决策树的种类:

2. ID3决策树:

ID3决策树的数划分标准是信息增益:

信息增益衡量的是通过某个特征进行数据划分前后熵的变化量。但是,它没有考虑到特征本身的熵,因此容易偏向于取值较多的特征

3. C4.5决策树:

C4.5决策树的数划分标准是信息增益比:

信息增益比则是 信息增益 除以 该特征自身的熵(也称为分裂信息)。这种方法旨在纠正信息增益对于取值较多特征的偏爱,通过将信息增益与特征自身的熵相除来惩罚那些拥有大量取值的特征。

C4.5并没有直接偏向于取值少的特征,而是通过分裂信息来调整信息增益,使得特征的基数大小影响其最终的选择概率。这种方式帮助算法避免了仅仅基于信息增益选择特征可能导致的过拟合问题,特别是当存在高基数特征时。

4. CART 回归树 和 分类树:

回归树:每个子树的输出是该子树节点值的均值:

步骤(1):选择最优切分变量和切分点

步骤(2):划分区域并决定输出值 

根据特征jj和切分点ss将数据集划分为两个子区域

计算子区域内的样本目标值的平均值作为该区域的预测值

这两个步骤描述了递归地应用上述过程,直到满足停止条件,并最终生成决策树的过程。

5. CART 的参数: 

6. CART 训练后的回归树常用属性:

为什么获取树的叶子节点数 就可以用于评估泛化能力?

       叶子节点数量越多,意味着决策树越复杂。每个叶子节点代表一个具体的预测规则或输出值。如果一棵树的叶子节点过多,说明它可能已经学习了训练数据中的很多细节甚至是噪音,这种现象通常被称为过拟合。过拟合模型在训练集上表现很好,但在未见过的数据(测试集)上的表现较差。

7. 回归树demo展示,可视化回归树:

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt

# 1. 加载数据
data = load_iris()
X = data.data
y = X[:, 0]  # 用 sepal length 做回归目标

# 2. 数据划分
X_train, X_test, y_train, y_test = train_test_split(X[:, 1:], y, test_size=0.2, random_state=42)

# 3. 建立模型
reg = DecisionTreeRegressor(max_depth=3, random_state=42)
reg.fit(X_train, y_train)

# 4. 模型预测与评估
y_pred = reg.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
print(f"\n【模型评估】\n均方误差 MSE: {mse:.4f}")

# 5. 打印常用属性
print("\n【模型属性展示】")
print("特征重要性 feature_importances_:", reg.feature_importances_)
print("使用特征数 n_features_in_:", reg.n_features_in_)
print("输出维度数 n_outputs_:", reg.n_outputs_)
print("实际使用的 max_features_:", reg.max_features_)
print("树最大深度 get_depth():", reg.get_depth())
print("叶子节点数 get_n_leaves():", reg.get_n_leaves())

# 6. 可视化特征重要性
feature_names = data.feature_names[1:]
plt.figure(figsize=(6, 4))
plt.bar(feature_names, reg.feature_importances_, color='teal')
plt.title("Feature Importances")
plt.ylabel("Importance")
plt.grid(axis='y')
plt.tight_layout()
plt.show()

# 7. 可视化树结构
plt.figure(figsize=(10, 6))
plot_tree(reg, feature_names=feature_names, filled=True, rounded=True)
plt.title("Decision Tree Structure")
plt.show()

8. 分类树:

sklearn 的模型参数:

模型属性对比:

demo:

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 1. 数据准备
iris = load_iris()
X = iris.data
y = iris.target

# 2. 划分数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 3. 构建模型(使用信息增益)
clf = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=42)
clf.fit(X_train, y_train)

# 4. 预测与评估
y_pred = clf.predict(X_test)
acc = accuracy_score(y_test, y_pred)
print(f"准确率: {acc:.4f}")

# 5. 展示分类专有属性
print("\n【分类树专有属性】")
print("类别标签 classes_:", clf.classes_)
print("类别数量 n_classes_:", clf.n_classes_)
print("每个测试样本的预测概率 predict_proba():\n", clf.predict_proba(X_test[:5]))

 二、Boosting:

(1)Boosting 中文是“提升方法”,是一种集成学习方法,它只是一个“策略思想”。

(2)AdaBoost、GDBT、 XGBoost、LightGBM 都是这个思想的具体实现。

(3)Boosting 将多个弱学习器(weak learner),如小决策树,串行地组合在一起,每一轮都“纠正”上一轮的错误,最终得到一个强大的集成模型。

(4)Gradient Boosting:英文缩写 GDBT ,中文是“梯度提升树”或“提升树”、“提升树模型”。

(5)注意:提升树 GBDT(及其变种) ≠  AdaBoost 

1. AdaBoost:

注意:不同于GDBT,AdaBoost 在第 t 轮不直接使用前一轮训练出的模型,而是通过样本权重的改变,间接地反映之前模型的表现。

AdaBoost 每一轮都是从头训练一个新的弱学习器  h_{t}(x) ,只是通过每次迭代将 训练样本分布进行调整,令错分样本权重更大

2. GDBT:

GBDT 是一种通过迭代拟合损失函数负梯度(即残差)的方式训练多个决策树并进行加权求和的Boosting 方法。GDBT使用回归树作为弱学习器(哪怕是分类任务)。

GBDT 的“Gradient”不是装饰,它真的是在做梯度下降,只是回归时,常用的损失函数是平方误差(MSE)的公式为:

\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 

对于MSE 的负梯度为:

MSE的负梯度刚好有一个可描述的名字,就是残差,因此可以理解为一种巧合hh

再举个例子:

GBDT 用于二分类,使用对数损失(Log Loss):

那么,在 GBDT 的每一轮中,就是用这些 负梯度 gi​ 作为新的“伪标签”来训练一个 回归树。在新的一轮迭代中,这个回归树试图学习xi → gi 。该回归树不是去做分类,而是用回归树去逼近这个负梯度值(伪残差)

你看到的是“残差”,其实它背后是“负梯度”;
这个巧合让 GBDT 在回归问题上看起来像“残差堆树”,但本质上是一种通用的函数空间梯度优化方法。

三、GDBT算法:

1. 算法步骤:

解释一下 GDBT的初始化:如果设定 f_0(x)=0,那第一步的残差就是 r_i = y_i,计算更简单

2. GDBT 模型过拟合分析:

GDBT 算法通过逐次拟合残差并不断优化模型,能够有效地提高模型的预测精度,且避免模型过拟合,具体来说,原因如下:

(1)逐步拟合残差,避免直接过拟合目标
每一步学习的目标是上一步的误差(残差),不是一次性“猜中全部”。这种“加法模型”方式可以让模型以小步慢走的方式逐渐逼近真实目标。

(2)模型弱但组合强
Boosting 通常使用弱学习器(如深度很浅的决策树)。单个模型能力弱,不容易过拟合,但组合起来又能表现强。

3. GDBT 如何解决分类问题:

GBDT 是一个加法模型,不断拟合前一轮的负梯度(即残差)来逼近真实目标。

对于分类问题,GBDT 并不是直接输出类别,而是构造一个连续值 f(x) ,被称作 logit 值,然后通过某种映射函数(比如 sigmoid 或 softmax)得到概率 P(x),用概率和真实标签计算 loss,更新树。树学习完毕,通过映射函数(比如 sigmoid 或 softmax)得到概率 P(x)再进行分类。

GBDT 的本质是:

  • 模型输出 logit 值 f(x)f(x)f(x)

  • 然后通过 sigmoid 转为概率 p(x)p(x)p(x);

  • 然后用概率和真实标签计算 loss,更新树。

3.1 二分类问题:

二分类问题的损失函数 和 根据推理出的连续预测值判断类别的方式如下:

3.2 多分类问题:

4. GDBT + LR模型组合方案 实现 特征交叉组合

总结起来:在大规模 CTR 预估中,利用 GBDT 自动学习复杂的特征交叉组合,用 GBDT 自动做特征组合/交叉,然后将其结果转换为稀疏的 one-hot 向量,作为 LR 的输入特征

可以说:在这个组合中,将GDBT作为encoder, LR作为decoder

4.1 解释一下LR的缺点:

在传统的逻辑回归(Logistic Regression)中,模型对特征之间的关系是线性加和的。假设你有两个离散特征:gender = female(性别为女性),device = mobile(使用移动设备)

你希望模型能够捕捉到这样一个复杂的行为模式:“女性使用移动设备时,点击率特别高;但在其他设备上,或者男性用户,点击率就不高。”

这就是一个特征组合效应。然而,逻辑回归本身并不能自动建模这种“组合条件”。它只会分别给gender=female 一个权重;device=mobile 一个权重;

无法表达 gender=female ∧ device=mobile 这个组合的交互含义。模型会把两个特征的权重加起来,却看不到它们组合在一起时可能呈现出的非线性行为。

为了解决这个问题,通常需要手工构造一个交叉特征 :cross_feature = (gender == female) AND (device == mobile)  这个新特征就相当于告诉模型:“这是一个特殊情况,需要关注”。然后把它作为新的输入特征加入逻辑回归模型中

因此,我们常说:

逻辑回归无法自动发现复杂的特征组合和非线性关系,必须依赖人工交叉特征,成本高、依赖专家经验和领域知识。

这正是 GBDT 等非线性模型能发挥优势的地方 —— 它们可以自动建模复杂交互关系,无需大量人工特征工程。

同时,逻辑回归属于线性模型,它的决策边界是线性的。如果点击行为的边界是非线性的,比如弯曲的、环形的,逻辑回归就无法很好拟合,因为它只能切直线。GBDT 通过决策树的分裂,自动学习特征之间的组合和非线性;神经网络通过非线性激活函数和多层结构,也能自动学复杂关系;这样将两者互补就可以很好的解决工业上面对的问题。

4.2 具体实现流程:

 

 

5. GDBT 的优缺点:

6. GDBT 与 随机森林 的区别:

四、XGBoost 算法:

1. XGBoost算法的优势:

XGBoost算法是基于GDBT算法的工程化优化,主要优化有以下几个方面:

(1)损失函数采用二次泰勒展开进行逼近,准确性更高(GDBT是一阶导数)

(2)损失函数增加了正则项,避免过拟合

(3)用了block实现并行 + 还有lambdaMART的优化【没理解完】

2. 数学推导链接:

对于XGBoost的损失函数为什么是这个样子,树的划分判断原则公式为什么长这样,给一个推导链接,这里就不细说了(主要还是看的有些含混,,)

XGBoost的原理、公式推导、Python实现和应用 - 知乎

【AI夏令营】LightGBM的数学原理解读_哔哩哔哩_bilibili  (这个也讲了XGBoost)

3.  XGBoost和GDBT的实现过程上的区别在哪?

共同点两者都是“Boosting”思想,每一轮训练一棵树来拟合 & 靠近 在该轮迭代过程中的 目标(对于GDBT来说是残差,对于XGBoost来说是目标函数,不过XGBoost迭代过程中也不涉及目标函数,直接根据目标函数进一步推导出划分树的公式 一步到位了),然后更新预测值,继续迭代。

不同点XGBoost 看起来像是“数学版 GBDT”:直接使用 损失函数的梯度信息构造切分的“分裂增益” 和 “划分的叶子赋值公式” ,而 GBDT 是“经验主义”:靠残差(近似一阶信息)手动拟合。

对比如下:

GBDT 的建树逻辑:
  • 残差 = label

  • 使用标准的 CART 树:按属性和阈值划分数据

  • 每个切分:计算左右子树的 MSE

  • 挑选损失最小的切分点

  • 递归建树

XGBoost的建树逻辑:

  • 不用残差,不重构 label

  • 每个样本 根据公式 计算出 对应的 一阶梯度 g_i 和二阶 h_i 

  • 遍历属性 + 切分点,计算基于导数推导出的 增益公式

  • 选最大增益的切分点

  • 递归建树

4. XGBoost的建树过程:

 

5. XGBoost —— Split Gain 和叶子赋值的伪代码

 下面这段伪代码是高度简化版,展示 如何枚举特征切分点并计算每个分裂的增益(Gain)与叶子输出值(weight)

# 输入: 样本列表,每个样本包含 (g_i, h_i, feature_values)
# 超参数: lambda_ (正则化),gamma (剪枝控制)

for feature in features:
    # 对特征值排序,配合 g_i, h_i 排序
    sorted_data = sort_by(feature)

    G_total = sum(g_i for g_i in sorted_data)
    H_total = sum(h_i for h_i in sorted_data)

    G_left, H_left = 0, 0

    for i in range(1, len(sorted_data)):
        g_i, h_i = sorted_data[i].g, sorted_data[i].h

        G_left += g_i
        H_left += h_i

        G_right = G_total - G_left
        H_right = H_total - H_left

        # 计算 Gain
        gain = 0.5 * (
            (G_left ** 2) / (H_left + lambda_) +
            (G_right ** 2) / (H_right + lambda_) -
            (G_total ** 2) / (H_total + lambda_)
        ) - gamma

        if gain > best_gain:
            best_gain = gain
            best_split = i
            best_feature = feature

# 最后叶子节点的输出值为:
leaf_weight = -G_j / (H_j + lambda_)

 

总结参考:

感谢大佬的无私分享,同时加入了一些自己的总结和理解,欢迎批评指正,相互交流~

决策树(ID3、C4.5、CART)的原理、Python实现、Sklearn可视化和应用 - 知乎

### 回答1: Adaboost、GBDTXGBoostLightGBM都是机器学习中常用的集成学习算法。 Adaboost是一种迭代算法,通过不断调整样本权重分类器权重,逐步提高分类器的准确率。 GBDT(Gradient Boosting Decision Tree)是一种基于决策树的集成学习算法,通过不断迭代,每次训练一个新的决策树来纠正前面树的错误,最终得到一个强分类器。 XGBoost是一种基于GBDT算法,它在GBDT的基础上引入了正则化并行化等技术,使得模型更加准确高效。 LightGBM是一种基于GBDT算法,它采用了基于直方图的决策树算法互斥特征捆绑技术,使得模型训练速度更快,占用内存更少,同时也具有较高的准确率。 ### 回答2: adaboost(Adaptive Boosting) 是一种基于不同权重的弱分类器的算法,它通过迭代的方式来逐步提高分类器的准确性。在每轮迭代中,它会调整训练样本的权重,使得前一轮分类错误的样本在当前轮得到更多的关注。最终,通过组合这些弱分类器来构建一个强分类器。其优点在于不易过拟合,但需要耗费大量的时间来训练预测。 gbdt(Gradient Boosting Decision Tree) 是一种基于决策树的集成学习算法,它通过迭代的方式来提升分类器的准确性。基于训练样本实际输出的误差进行梯度下降,将它们作为下一个分类器的训练数据。每个分类器都在之前所有分类器得到的残差的基础上进行训练,并且将它们组合成一个最终的分类器。在训练过程中,为了避免过拟合,可以限制决策树的深度等参数,并采用交叉验证等技术。gbdt可以处理缺失数据、不平衡分类高维度数据等问题,但需要注意过拟合的问题。 xgboost(Extreme Gradient Boosting) 是一种基于决策树的集成学习算法,它在gbdt的基础上引入了正则化项精细的特征选择,进一步提高了分类器的准确性效率。通过Hessian矩阵对损失函数进行二阶泰勒展开,引入正则化约束,可以优化损失函数,并通过交叉验证等技术选择最优的超参数。xgboost还支持GPU加速,提高模型训练的速度效率,但需要更多的计算资源。xgboost在分类、回归排名任务中表现优异,但需要注意过拟合计算量的问题。 lightgbm是微软旗下一款高效、快速、分布式的梯度提升框架,也是一种基于决策树的集成学习算法,定位在处理高维度数据大规模数据集上。lightgbm采用了GOSS(Gradient-based One-Side Sampling)技术EFB(Exclusive Feature Bundling)技术对数据进行处理,大大减少数据的内存占用训练时间。同时,还支持并行计算GPU加速,提高了模型的速度效率。lightgbm在排序、分类、回归等任务中表现出色,只是对离群值敏感,需要对数据进行预处理。 ### 回答3: Adaboost,Gradient Boosting Decision Tree (GBDT),XGBoostLightGBM都是常见的集成学习算法,它们用于提高模型在复杂数据集上的准确度,并处理复杂数据集上遇到的问题。 Adaboost是一种迭代算法,每次迭代它使用提高错误分类样本的加权值,并降低正确分类样本的加权值,以便让前一个弱分类器无法捕捉并由后续分类器学习。Adaboost弱分类器快速训练预测,且不需要太多超参数调整,但是它倾向于过度拟合数据,并且实力可能不足以解决大型数据集的问题。 GBDT使用决策树作为弱分类器,将每一棵树的预测结果作为下一棵树的预测输入,最后对所有树的预测结果进行加权求GBDT可以很好地处理线性非线性问题,但是它倾向于过度拟合数据,需要进行精细调整参数,并且需要较长时间的训练时间。 XGBoost结合了GBDT的优势树的强大性质。它采用了一些优秀的技术,如Boosting树算法,Shrinkage,Column SamplingPruning Nodes,以提高模型的性能降低过拟合风险。XGBoost可以处理大规模数据集高维数据集,并且速度较快,但需要的资源较多,如内存、计算能力高质量的数据集。 LightGBMXGBoost的新一代版本,采用了GOI(Gradient-based One-side Sampling)算法Histogram-based Gradient Boosting方法来加快训练速度降低内存占用。GOI算法通过对数据进行一侧采样来提高训练速度,而直方图梯度提升方法将节点分裂建模为一个直方图分桶过程,以减少节点分裂的计算成本。LightGBM对大数据集的处理能力很强,速度相对较快,但对于处理小数据集的效果可能不明显。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值