2.1 基于梯度的决策树 (GBDT) 基础回顾


文档摘要

2.1 基于梯度的决策树 (GBDT) 基础回顾 第二章:LightGBM 核心原理 2.1 基于梯度的决策树 (GBDT) 基础回顾 梯度提升决策树 (Gradient Boosting Decision Tree, GBDT) 是一种强大的机器学习算法,广泛应用于分类和回归任务。作为 LightGBM 的核心基学习器,深入理解 GBDT 的原理对于掌握 LightGBM 至关重要。本节将对 GBDT 的基础概念、算法流程、关键技术点以及代码实践进行详细回顾,为后续深入学习 LightGBM 打下坚实的基础。 2.1.1 决策树 (Decision Tree) 的回顾 GBDT 的基学习器是决策树,因此我们首先简要回顾决策树的基本概念。 1.

2.1 基于梯度的决策树 (GBDT) 基础回顾

第二章:LightGBM 核心原理

2.1 基于梯度的决策树 (GBDT) 基础回顾

梯度提升决策树 (Gradient Boosting Decision Tree, GBDT) 是一种强大的机器学习算法,广泛应用于分类和回归任务。作为 LightGBM 的核心基学习器,深入理解 GBDT 的原理对于掌握 LightGBM 至关重要。本节将对 GBDT 的基础概念、算法流程、关键技术点以及代码实践进行详细回顾,为后续深入学习 LightGBM 打下坚实的基础。

2.1.1 决策树 (Decision Tree) 的回顾

GBDT 的基学习器是决策树,因此我们首先简要回顾决策树的基本概念。

1. 决策树的结构与原理

决策树是一种树形结构的分类或回归模型。它通过一系列的决策规则,将数据集逐步划分到不同的叶子节点,最终每个叶子节点代表一个预测结果。决策树的核心思想是 分而治之,通过不断地将数据划分为更纯净的子集,从而实现预测。

  • 节点 (Node): 决策树的组成部分,包括根节点、内部节点和叶子节点。

    • 根节点 (Root Node): 树的顶部节点,包含所有样本。

    • 内部节点 (Internal Node): 代表一个特征属性上的测试条件,根据不同的属性值划分到不同的子节点。

    • 叶子节点 (Leaf Node): 树的底部节点,代表最终的决策结果。

  • 分支 (Branch): 连接节点和子节点的有向边,代表决策规则。

  • 决策规则 (Decision Rule): 在内部节点上定义的特征属性测试条件,例如 "年龄 > 30"。

2. 决策树的构建过程

决策树的构建是一个递归的过程,主要步骤包括:

  • 特征选择 (Feature Selection): 从所有特征中选择最优的特征作为当前节点的划分特征。最优特征的选择标准通常基于信息增益、信息增益率、基尼指数等指标,旨在最大化划分后子节点的数据纯度。

  • 节点分裂 (Node Splitting): 根据选择的特征和划分点,将当前节点的数据集划分为若干个子集,每个子集对应一个子节点。

  • 递归构建 (Recursive Building): 对每个子节点递归地重复上述步骤,直到满足停止条件。停止条件可以是:

    • 节点包含的样本数量小于预设阈值。

    • 节点中所有样本属于同一类别(对于分类树)。

    • 决策树的深度达到预设阈值。

    • 没有可用的特征进行划分。

3. 决策树的类型

常见的决策树类型包括:

  • 分类树 (Classification Tree): 用于分类任务,叶子节点输出样本的类别。常用的算法有 ID3、C4.5、CART 分类树等。

  • 回归树 (Regression Tree): 用于回归任务,叶子节点输出样本的预测值。常用的算法有 CART 回归树。

4. 决策树的优点与缺点

  • 优点:

    • 易于理解和解释: 决策树的结构直观,决策规则清晰,易于理解和解释模型的预测过程。

    • 可处理类别型和数值型数据: 决策树可以处理各种类型的数据,无需对数据进行过多预处理。

    • 训练速度快: 相对其他复杂模型,决策树的训练速度较快。

    • 对缺失值不敏感: 某些决策树算法可以处理缺失值。

  • 缺点:

    • 容易过拟合: 决策树容易生成过于复杂的树结构,导致在训练集上表现良好,但在测试集上泛化能力较差。

    • 不稳定: 数据的小幅变动可能导致树结构发生显著变化。

    • 忽略特征之间的相关性: 决策树在选择特征时,通常独立考虑每个特征,忽略特征之间的相关性。

5. Mermaid 图示

代码实践 (Python - scikit-learn):

from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score # 加载 Iris 数据集 iris = load_iris() X, y = iris.data, iris.target # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 创建决策树分类器 clf = DecisionTreeClassifier(max_depth=3) # 限制树的最大深度,防止过拟合 # 训练模型 clf.fit(X_train, y_train) # 预测测试集 y_pred = clf.predict(X_test) # 评估模型 accuracy = accuracy_score(y_test, y_pred) print(f"决策树分类器在测试集上的准确率: {accuracy:.4f}") # 可视化决策树 (需要安装 graphviz 和 pydotplus) # from sklearn.tree import export_graphviz # import pydotplus # dot_data = export_graphviz(clf, out_file=None, # feature_names=iris.feature_names, # class_names=iris.target_names, # filled=True, rounded=True, # special_characters=True) # graph = pydotplus.graph_from_dot_data(dot_data) # graph.write_png("iris_decision_tree.png") # 保存为 PNG 图片

代码详解:

  1. 导入必要的库:

    • DecisionTreeClassifier: scikit-learn 提供的决策树分类器。

    • train_test_split: 用于划分数据集。

    • load_iris: 加载 Iris 数据集。

    • accuracy_score: 评估分类模型的准确率。

  2. 加载 Iris 数据集: 使用 load_iris() 函数加载 Iris 数据集,包含特征数据 X 和目标变量 y

  3. 划分训练集和测试集: 使用 train_test_split() 函数将数据集划分为训练集和测试集,其中测试集占比 30%,random_state 用于保证每次划分结果一致。

  4. 创建决策树分类器: DecisionTreeClassifier(max_depth=3) 创建一个决策树分类器,并设置 max_depth=3 限制树的最大深度,以防止过拟合。

  5. 训练模型: clf.fit(X_train, y_train) 使用训练集数据训练决策树模型。

  6. 预测测试集: clf.predict(X_test) 使用训练好的模型对测试集数据进行预测。

  7. 评估模型: accuracy_score(y_test, y_pred) 计算模型在测试集上的准确率。

  8. 可视化决策树 (可选): 代码注释部分提供了可视化决策树的方法,需要安装 graphvizpydotplus 库。export_graphviz 函数将决策树导出为 DOT 格式,pydotplus.graph_from_dot_data 将 DOT 格式数据转换为图形对象,最后保存为 PNG 图片。

2.1.2 梯度提升 (Gradient Boosting) 的概念

GBDT 的核心在于 梯度提升 (Gradient Boosting)。提升 (Boosting) 是一种集成学习方法,它将多个弱学习器 (weak learner) 组合成一个强学习器 (strong learner)。梯度提升是提升方法的一种,它利用梯度下降的思想来优化模型。

1. Boosting 思想

Boosting 算法的核心思想是 串行训练弱学习器,并将它们 加权组合 起来。每个弱学习器都试图纠正前一个弱学习器的错误,从而逐步提升整体模型的性能。Boosting 算法的训练过程可以形象地比喻为 "三个臭皮匠,顶个诸葛亮",即多个弱学习器的组合可以达到强学习器的效果。

2. 梯度下降 (Gradient Descent)

梯度下降是一种常用的优化算法,用于求解函数的最小值。在机器学习中,我们通常需要优化损失函数 (Loss Function),使其达到最小值,从而得到最优的模型参数。梯度下降算法通过迭代的方式,沿着损失函数梯度 (Gradient) 的反方向更新参数,逐步逼近最优解。

3. 梯度提升 (Gradient Boosting) 的核心思想

梯度提升算法将梯度下降的思想应用于 Boosting 框架中。它在每一轮迭代中,训练一个新的弱学习器来 拟合负梯度 (Negative Gradient),也称为 伪残差 (Pseudo-Residuals)。负梯度反映了当前模型预测值与真实值之间的差距方向和大小。通过拟合负梯度,新的弱学习器可以有效地纠正前一轮模型的预测误差。

4. 梯度提升的优势

  • 高精度预测: 梯度提升算法能够有效地降低偏差和方差,通常能够获得较高的预测精度。

  • 灵活性: 梯度提升算法可以使用不同的弱学习器,例如决策树、线性回归等。GBDT 通常使用决策树作为弱学习器。

  • 鲁棒性: 梯度提升算法对异常值和噪声数据具有一定的鲁棒性。

5. Mermaid 图示

图示解释:

  • 绿色箭头: 代表模型迭代更新的流程。

  • 红色箭头: 代表计算负梯度和训练弱学习器的流程。

  • lr: 代表学习率 (Learning Rate),控制弱学习器对模型更新的贡献程度。

2.1.3 梯度提升决策树 (GBDT) 算法详解

梯度提升决策树 (GBDT) 将梯度提升算法与决策树相结合,使用决策树作为弱学习器进行梯度提升。GBDT 的算法流程如下:

算法 2.1: 梯度提升决策树 (GBDT) 算法

输入: 训练数据集 \mathcal{D} = \{(x_i, y_i)\}_{i=1}^{N},损失函数 L(y, F(x)),迭代次数 M,弱学习器类型 (决策树)。

输出: 梯度提升决策树模型 F_M(x).

步骤:

  1. 初始化模型:

    • F_0(x) = \arg\min_{c} \sum_{i=1}^{N} L(y_i, c) (对于回归问题,通常初始化为常数,例如均值或中位数;对于分类问题,可以初始化为对数几率)。
  2. 迭代训练: for m = 1, 2, \dots, M:

    • a. 计算负梯度 (伪残差): for i = 1, 2, \dots, N:

      • r_{im} = - \left[ \frac{\partial L(y_i, F_{m-1}(x_i))}{\partial F(x_i)} \right]_{F(x)=F_{m-1}(x)}
    • b. 训练弱学习器 (决策树) 拟合伪残差:

      • 使用数据集 \{(x_i, r_{im})\}_{i=1}^{N} 训练一个决策树 h_m(x),使其尽可能地拟合伪残差 r_{im}
    • c. 计算叶子节点区域的最佳拟合值: 对于回归问题,可以直接使用叶子节点上伪残差的均值作为最佳拟合值。对于其他损失函数,可能需要进行线搜索 (Line Search) 或其他优化方法来确定每个叶子节点区域的最佳输出值 \gamma_{jm},其中 j 表示叶子节点区域。

    • d. 更新模型:

      • F_m(x) = F_{m-1}(x) + \eta \sum_{j=1}^{J_m} \gamma_{jm} I(x \in R_{jm})

      其中:

      - $\eta$ 是学习率 (Learning Rate),通常取值范围为 (0, 1],用于控制每个弱学习器的步长,防止过拟合。 - $J_m$ 是第 $m$ 棵决策树的叶子节点数量。 - $R_{jm}$ 是第 $m$ 棵决策树的第 $j$ 个叶子节点区域。 - $I(x \in R_{jm})$ 是指示函数,当样本 $x$ 属于叶子节点区域 $R_{jm}$ 时为 1,否则为 0。
  3. 输出最终模型: F_M(x) = F_0(x) + \sum_{m=1}^{M} \eta \sum_{j=1}^{J_m} \gamma_{jm} I(x \in R_{jm}).

算法步骤详解:

  1. 初始化模型 F_0(x): GBDT 首先初始化一个弱模型,通常是一个常数模型。对于回归问题,可以初始化为训练集目标变量的均值或中位数。对于分类问题,可以初始化为对数几率。初始模型的目的是提供一个初始的预测值,后续的弱学习器将在其基础上进行改进。

  2. 迭代训练 (步骤 2a-2d): GBDT 通过迭代的方式训练 M 棵决策树。在每一轮迭代 m 中:

    • 步骤 2a: 计算负梯度 (伪残差) r_{im}: 这是梯度提升的核心步骤。负梯度 r_{im} 表示当前模型 F_{m-1}(x) 在样本 x_i 上的预测误差方向和大小。对于不同的损失函数,负梯度的计算方式不同。例如,对于平方损失函数 L(y, F(x)) = \frac{1}{2}(y - F(x))^2,负梯度为 r_{im} = y_i - F_{m-1}(x_i),即真实值与预测值之间的残差。

    • 步骤 2b: 训练决策树 h_m(x) 拟合伪残差: 使用计算得到的伪残差 r_{im} 作为新的目标变量,训练一个新的决策树 h_m(x)。决策树的目标是尽可能地拟合伪残差,即学习如何纠正前一轮模型的预测误差。

    • 步骤 2c: 计算叶子节点区域的最佳拟合值 \gamma_{jm}: 决策树 h_m(x) 将输入空间划分为若干个叶子节点区域 R_{jm}。对于每个叶子节点区域,需要确定一个最佳的输出值 \gamma_{jm},使得该区域的损失函数最小化。对于回归问题,通常可以直接使用叶子节点上伪残差的均值作为 \gamma_{jm}。对于其他损失函数,例如对数损失函数,需要通过线搜索或其他优化方法来确定 \gamma_{jm}

    • 步骤 2d: 更新模型 F_m(x): 将新训练的决策树 h_m(x) 加到之前的模型 F_{m-1}(x) 中,得到新的模型 F_m(x)。为了防止过拟合,通常会引入学习率 \eta,控制每棵树对模型更新的贡献程度。学习率越小,模型更新越平缓,但也需要更多的迭代次数才能收敛。

  3. 输出最终模型 F_M(x): 经过 M 轮迭代后,得到最终的 GBDT 模型 F_M(x),它是由 M 棵决策树加权组合而成的。

关键技术点:

  • 损失函数 L(y, F(x)): 损失函数的选择取决于具体的任务类型。常用的损失函数包括:

    • 回归问题: 平方损失函数 (Mean Squared Error, MSE)、绝对值损失函数 (Mean Absolute Error, MAE)、Huber 损失函数等。

    • 分类问题: 对数损失函数 (Log Loss, 用于二分类和多分类)、指数损失函数 (用于 AdaBoost)、hinge 损失函数 (用于支持向量机) 等。

  • 负梯度 (伪残差) 的计算: 负梯度是 GBDT 算法的核心,不同的损失函数对应不同的负梯度计算方式。

  • 决策树的构建: GBDT 通常使用 CART 回归树作为弱学习器。决策树的构建过程需要考虑特征选择、节点分裂、剪枝等问题。

  • 叶子节点区域的最佳拟合值 \gamma_{jm} 的计算: 对于不同的损失函数,\gamma_{jm} 的计算方式不同,可能需要使用线搜索或其他优化方法。

  • 学习率 \eta 的选择: 学习率是 GBDT 的重要超参数,需要根据具体问题进行调整。较小的学习率可以提高模型的泛化能力,但也需要更多的迭代次数。

代码实践 (Python - scikit-learn):

from sklearn.ensemble import GradientBoostingRegressor from sklearn.model_selection import train_test_split from sklearn.datasets import load_boston from sklearn.metrics import mean_squared_error # 加载 Boston 房价数据集 (回归任务) boston = load_boston() X, y = boston.data, boston.target # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # 创建 GBDT 回归器 gbr = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42) # n_estimators: 弱学习器 (决策树) 的数量 # learning_rate: 学习率 # max_depth: 决策树的最大深度 # 训练模型 gbr.fit(X_train, y_train) # 预测测试集 y_pred = gbr.predict(X_test) # 评估模型 mse = mean_squared_error(y_test, y_pred) print(f"GBDT 回归器在测试集上的均方误差 (MSE): {mse:.4f}")

代码详解:

  1. 导入必要的库:

    • GradientBoostingRegressor: scikit-learn 提供的 GBDT 回归器。

    • train_test_split: 用于划分数据集。

    • load_boston: 加载 Boston 房价数据集。

    • mean_squared_error: 评估回归模型的均方误差。

  2. 加载 Boston 房价数据集: 使用 load_boston() 函数加载 Boston 房价数据集,包含特征数据 X 和目标变量 y (房价)。

  3. 划分训练集和测试集: 使用 train_test_split() 函数将数据集划分为训练集和测试集。

  4. 创建 GBDT 回归器: GradientBoostingRegressor(...) 创建一个 GBDT 回归器,并设置关键参数:

    • n_estimators=100: 设置弱学习器 (决策树) 的数量为 100。

    • learning_rate=0.1: 设置学习率为 0.1。

    • max_depth=3: 设置决策树的最大深度为 3。

    • random_state=42: 设置随机种子,保证结果可复现。

  5. 训练模型: gbr.fit(X_train, y_train) 使用训练集数据训练 GBDT 模型。

  6. 预测测试集: gbr.predict(X_test) 使用训练好的模型对测试集数据进行预测。

  7. 评估模型: mean_squared_error(y_test, y_pred) 计算模型在测试集上的均方误差 (MSE)。

2.1.4 GBDT 的优缺点总结

优点:

  • 高精度预测: GBDT 通常能够获得比单一决策树更高的预测精度。

  • 可处理复杂数据: GBDT 可以处理各种类型的数据,包括数值型和类别型数据。

  • 特征重要性评估: GBDT 可以输出特征的重要性评分,帮助理解数据和进行特征选择。

  • 较好的鲁棒性: GBDT 对异常值和噪声数据具有一定的鲁棒性。

缺点:

  • 训练时间较长: GBDT 是串行训练的,训练时间相对较长,尤其是在数据集较大、迭代次数较多的情况下。

  • 容易过拟合: 如果不加以控制,GBDT 容易生成过于复杂的模型,导致过拟合。需要通过剪枝、限制树的深度、使用正则化等方法来防止过拟合。

  • 参数调优相对复杂: GBDT 有较多的参数需要调优,例如树的数量、学习率、树的深度、叶子节点数量等。

2.1.5 总结

本节回顾了基于梯度的决策树 (GBDT) 的基础知识,包括决策树的基本概念、梯度提升的思想、GBDT 算法的详细流程、关键技术点以及代码实践。GBDT 作为一种强大的机器学习算法,是 LightGBM 的核心基学习器。理解 GBDT 的原理对于后续深入学习 LightGBM 的高效特性和优化方法至关重要。在后续章节中,我们将进一步探讨 LightGBM 如何在 GBDT 的基础上进行改进和优化,从而实现更高效、更强大的梯度提升框架。


发布者: 作者: 转发
评论区 (0)
U