XGBoosting算法详解(Boosting思想的代表算法)
文章目录
- 相关文章
- 一、Boosting思想:从弱到强的串行提升
- 二、XGBoost算法思想:GBDT的极致优化
- 三、XGBoost数学原理:从目标函数到树分裂
- 3.1 目标函数定义
- 3.2 正则化项:控制树的复杂度
- 3.3 泰勒二阶展开:简化目标函数
- 3.4 化简目标函数
- 3.5 从样本到叶子节点的转换
- 3.6 叶子节点最优权重与最终目标函数
- 3.7 树分裂的Gain计算
- 四、举例说明:用 XGBoost 预测电子游戏喜好
- 4.1 步骤 1:初始化模型(全局偏置 y^(0)\hat{y}^{(0)}y^(0))
- 4.2 步骤 2:计算一阶导、二阶导(平方损失下的梯度)
- 4.3 步骤 3:构建第一棵树 f1(x)f_1(x)f1(x)
- 4.4 步骤 4:构建第二棵树 f2(x)f_2(x)f2(x)
- 4.5 步骤 5:构建第三棵树 f3(x)f_3(x)f3(x)
- 4.6 误差计算
- 4.7 核心逻辑
- 五、XGBoost 的 API详解
- 5.1 安装XGBoost
- 5.2 核心参数说明(以分类为例)
- 5.3 完整使用示例
- 六、总结
相关文章
决策树(Decision tree)算法详解:网页链接
人工智能概念之七:集成学习思想:网页链接
一、Boosting思想:从弱到强的串行提升
Boosting是集成学习的重要分支,其核心思想是通过串行训练多个弱学习器,让每个新学习器聚焦前序学习器的误差,最终通过加权投票整合所有学习器的预测结果。具体特点如下:
- 串行训练:弱学习器按顺序训练,后一个学习器的训练依赖前一个学习器的结果;
- 聚焦误差:每个新学习器会重点关注前序学习器预测错误的样本(通过调整样本权重实现);
- 加权整合:最终预测结果由所有弱学习器加权投票得到,性能更好的学习器权重更高。
简单来说,Boosting就像“师徒传承”:徒弟先尝试解决问题,师傅根据徒弟的错误进行针对性指导,再由下一个徒弟优化,逐步提升整体能力。
二、XGBoost算法思想:GBDT的极致优化
XGBoost是梯度提升树(GBDT)的改进版本,其核心目标是在梯度提升框架下,通过优化目标函数和加入正则化,实现更高效、更稳定的模型训练。相比GBDT,XGBoost的创新点主要体现在:
- 目标函数优化:使用泰勒二阶展开近似损失函数,提升优化效率;
- 正则化控制:在损失函数中加入树结构的正则化项,防止过拟合;
- 高效树分裂:设计专属的树节点分裂指标,加速模型训练。
三、XGBoost数学原理:从目标函数到树分裂
3.1 目标函数定义
XGBoost的核心是最小化目标函数,该函数由两部分组成:损失项(衡量预测值与真实值的差异)和正则化项(控制模型复杂度)。
对于第ttt次迭代的模型,目标函数为:
L(t)=∑i=1nL(yi,y^i(t−1)+ft(xi))+∑k=1tΩ(fk)\mathcal{L}^{(t)} = \sum_{i=1}^{n} L\left(y_{i}, \hat{y}_{i}^{(t-1)} + f_{t}(x_{i})\right) + \sum_{k=1}^{t} \Omega\left(f_{k}\right) L(t)=i=1∑nL(yi,y^i(t−1)+ft(xi))+k=1∑tΩ(fk)
- 其中:
- yiy_iyi是样本iii的真实标签;
- y^i(t−1)\hat{y}_i^{(t-1)}y^i(t−1)是前t−1t-1t−1个学习器的预测结果;
- ft(xi)f_t(x_i)ft(xi)是第ttt个弱学习器(决策树)对样本iii的预测值;
- L(⋅)L(\cdot)L(⋅)是损失函数(如回归用平方损失L(y,y^)=(y−y^)2L(y,\hat{y})=(y-\hat{y})^2L(y,y^)=(y−y^)2,分类用对数损失);
- Ω(fk)\Omega(f_k)Ω(fk)是第kkk个弱学习器的正则化项,用于控制树的复杂度。
3.2 正则化项:控制树的复杂度
XGBoost通过正则化项限制树的复杂度,定义为:
Ω(ft)=γT+12λ∑j=1Twj2\Omega(f_t) = \gamma T + \frac{1}{2} \lambda \sum_{j=1}^{T} w_j^2 Ω(ft)=γT+21λj=1∑Twj2
- 其中:
- TTT是树的叶子节点数量;
- wjw_jwj是第jjj个叶子节点的输出值;
- γ\gammaγ和λ\lambdaλ是正则化系数(超参数),γ\gammaγ越大越倾向于少叶子节点,λ\lambdaλ越大越限制wjw_jwj的绝对值。
3.3 泰勒二阶展开:简化目标函数
直接求解目标函数较复杂,XGBoost使用泰勒二阶展开近似损失函数。对于函数L(y,y^(t−1)+ft)L(y, \hat{y}^{(t-1)} + f_t)L(y,y^(t−1)+ft),在y^(t−1)\hat{y}^{(t-1)}y^(t−1)处的二阶泰勒展开为:
L(y,y^(t−1)+ft)≈L(y,y^(t−1))+gift(xi)+12hift2(xi)L(y, \hat{y}^{(t-1)} + f_t) \approx L(y, \hat{y}^{(t-1)}) + g_i f_t(x_i) + \frac{1}{2} h_i f_t^2(x_i) L(y,y^(t−1)+ft)≈L(y,y^(t−1))+gift(xi)+21hift2(xi)
- 其中:
- gi=∂L(yi,y^i(t−1))∂y^i(t−1)g_i = \frac{\partial L(y_i, \hat{y}_i^{(t-1)})}{\partial \hat{y}_i^{(t-1)}}gi=∂y^i(t−1)∂L(yi,y^i(t−1))(一阶导数,损失函数的斜率);
- hi=∂2L(yi,y^i(t−1))∂(y^i(t−1))2h_i = \frac{\partial^2 L(y_i, \hat{y}_i^{(t-1)})}{\partial (\hat{y}_i^{(t-1)})^2}hi=∂(y^i(t−1))2∂2L(yi,y^i(t−1))(二阶导数,损失函数的曲率)。
3.4 化简目标函数
将泰勒展开代入原目标函数,忽略常数项(与ftf_tft无关的L(y,y^(t−1))L(y, \hat{y}^{(t-1)})L(y,y^(t−1))和∑k=1t−1Ω(fk)\sum_{k=1}^{t-1}\Omega(f_k)∑k=1t−1Ω(fk)),得到第ttt次迭代的简化目标函数:
L(t)≈∑i=1n(gift(xi)+12hift2(xi))+Ω(ft)\mathcal{L}^{(t)} \approx \sum_{i=1}^n \left( g_i f_t(x_i) + \frac{1}{2} h_i f_t^2(x_i) \right) + \Omega(f_t) L(t)≈i=1∑n(gift(xi)+21hift2(xi))+Ω(ft)
3.5 从样本到叶子节点的转换
决策树的预测可表示为:若样本iii落在第jjj个叶子节点,则ft(xi)=wjf_t(x_i) = w_jft(xi)=wj(wjw_jwj为叶子节点jjj的输出值)。设叶子节点jjj包含的样本集合为IjI_jIj,则目标函数可改写为:
L(t)≈∑j=1T((∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2)+γT\mathcal{L}^{(t)} \approx \sum_{j=1}^T \left( \left( \sum_{i \in I_j} g_i \right) w_j + \frac{1}{2} \left( \sum_{i \in I_j} h_i + \lambda \right) w_j^2 \right) + \gamma T L(t)≈j=1∑Ti∈Ij∑giwj+21i∈Ij∑hi+λwj2+γT
- 其中:
- Gj=∑i∈IjgiG_j = \sum_{i \in I_j} g_iGj=∑i∈Ijgi(叶子节点jjj的一阶导之和);
- Hj=∑i∈IjhiH_j = \sum_{i \in I_j} h_iHj=∑i∈Ijhi(叶子节点jjj的二阶导之和)。
3.6 叶子节点最优权重与最终目标函数
对wjw_jwj求导并令导数为0,可得最优wjw_jwj:
wj∗=−GjHj+λw_j^* = -\frac{G_j}{H_j + \lambda} wj∗=−Hj+λGj
将wj∗w_j^*wj∗代入目标函数,得到最终简化形式(衡量树结构的优劣):
L(t)∗=−12∑j=1TGj2Hj+λ+γT\mathcal{L}^{(t)*} = -\frac{1}{2} \sum_{j=1}^T \frac{G_j^2}{H_j + \lambda} + \gamma T L(t)∗=−21j=1∑THj+λGj2+γT
3.7 树分裂的Gain计算
为判断节点分裂是否有效,定义分裂增益(Gain):分裂后目标函数的减少量。若父节点分裂为左右子节点,Gain为:
Gain=Gleft2Hleft+λ+Gright2Hright+λ−Gparent2Hparent+λ−γ\text{Gain} = \frac{G_{\text{left}}^2}{H_{\text{left}} + \lambda} + \frac{G_{\text{right}}^2}{H_{\text{right}} + \lambda} - \frac{G_{\text{parent}}^2}{H_{\text{parent}} + \lambda} - \gamma Gain=Hleft+λGleft2+Hright+λGright2−Hparent+λGparent2−γ
- 若Gain > 0,分裂有效(目标函数降低);反之则不分裂。
以下是结合代码运行结果,对“用 XGBoost 预测电子游戏喜好”示例的详细修正与完善,让推导过程和实际模型输出更贴合,便于理解 XGBoost 迭代逻辑:
四、举例说明:用 XGBoost 预测电子游戏喜好
假设我们要预测一家人对电子游戏的喜好程度(分数越高表示越喜欢),特征为年龄,样本数据如下:
成员 | 年龄 | 真实喜好分数 yiy_iyi |
---|---|---|
小男孩 | 8 | 3 |
小女孩 | 7 | 2 |
父亲 | 35 | 2 |
母亲 | 32 | 1 |
爷爷 | 65 | 0 |
4.1 步骤 1:初始化模型(全局偏置 y^(0)\hat{y}^{(0)}y^(0))
初始预测值为所有样本的均值:
y^(0)=3+2+2+1+05=1.6\hat{y}^{(0)} = \frac{3 + 2 + 2 + 1 + 0}{5} = 1.6 y^(0)=53+2+2+1+0=1.6
4.2 步骤 2:计算一阶导、二阶导(平方损失下的梯度)
选用平方损失 L(y,y^)=(y−y^)2L(y, \hat{y}) = (y - \hat{y})^2L(y,y^)=(y−y^)2,其梯度为:
- 一阶导数(梯度):gi=∂L∂y^(0)=2(y^(0)−yi)g_i = \frac{\partial L}{\partial \hat{y}^{(0)}} = 2(\hat{y}^{(0)} - y_i)gi=∂y^(0)∂L=2(y^(0)−yi)
- 二阶导数(Hessian):hi=∂2L∂(y^(0))2=2h_i = \frac{\partial^2 L}{\partial (\hat{y}^{(0)})^2} = 2hi=∂(y^(0))2∂2L=2(平方损失二阶导恒为2)
代入 y^(0)=1.6\hat{y}^{(0)} = 1.6y^(0)=1.6 计算:
成员 | yiy_iyi(真实值) | gig_igi(一阶导) | hih_ihi(二阶导) |
---|---|---|---|
小男孩 | 3 | 2×(1.6−3)=−2.82×(1.6 - 3) = -2.82×(1.6−3)=−2.8 | 2 |
小女孩 | 2 | 2×(1.6−2)=−0.82×(1.6 - 2) = -0.82×(1.6−2)=−0.8 | 2 |
父亲 | 2 | 2×(1.6−2)=−0.82×(1.6 - 2) = -0.82×(1.6−2)=−0.8 | 2 |
母亲 | 1 | 2×(1.6−1)=1.22×(1.6 - 1) = 1.22×(1.6−1)=1.2 | 2 |
爷爷 | 0 | 2×(1.6−0)=3.22×(1.6 - 0) = 3.22×(1.6−0)=3.2 | 2 |
4.3 步骤 3:构建第一棵树 f1(x)f_1(x)f1(x)
树结构分裂规则:按 Age<32
→ 右分支按 Age<65
→ 右分支按 Age<35
分裂,最终得到4个叶子节点,叶子权重分别为:w1=0.075w_1=0.075w1=0.075,w2=−0.075w_2=-0.075w2=−0.075,w3=−0.025w_3=-0.025w3=−0.025,w4=0.025w_4=0.025w4=0.025(单位:未缩放前权重,后续乘以缩放系数)。
-
样本划分(按分裂规则)
- 叶子节点1(Age<32):包含小男孩(8)、小女孩(7)(年龄<32)。
- 叶子节点2(Age≥32 且 Age<65 且 Age<35):无样本(母亲年龄32≥32,32<65,但32<35,实际归为叶子节点3)。
- 叶子节点3(Age≥32 且 Age<65 且 Age≥35):包含母亲(32)、父亲(35)(32≥32,32<65,32<35;35≥32,35<65,35≥35)。
- 叶子节点4(Age≥32 且 Age≥65):包含爷爷(65)(65≥32,65≥65)。
-
叶子节点权重缩放
叶子权重缩放系数 k1=23.73k_1=23.73k1=23.73:- 叶子节点1输出:f1(小男孩)=f1(小女孩)=w1×k1=0.075×23.73≈1.78f_1(\text{小男孩})=f_1(\text{小女孩})=w_1×k_1=0.075×23.73≈1.78f1(小男孩)=f1(小女孩)=w1×k1=0.075×23.73≈1.78
- 叶子节点3输出:f1(母亲)=f1(父亲)=w3×k1=−0.025×23.73≈−0.59f_1(\text{母亲})=f_1(\text{父亲})=w_3×k_1=-0.025×23.73≈-0.59f1(母亲)=f1(父亲)=w3×k1=−0.025×23.73≈−0.59
- 叶子节点4输出:f1(爷爷)=w4×k1=0.025×23.73≈0.59f_1(\text{爷爷})=w_4×k_1=0.025×23.73≈0.59f1(爷爷)=w4×k1=0.025×23.73≈0.59
-
第一轮迭代预测值
学习率 η=0.1\eta=0.1η=0.1,预测值为初始值加树输出乘以学习率:
y^(1)=y^(0)+η⋅f1(xi)\hat{y}^{(1)} = \hat{y}^{(0)} + \eta \cdot f_1(x_i) y^(1)=y^(0)+η⋅f1(xi)计算得:
- 小男孩/小女孩:y^(1)=1.6+0.1×1.78=1.778\hat{y}^{(1)} = 1.6 + 0.1×1.78 = 1.778y^(1)=1.6+0.1×1.78=1.778
- 父亲:y^(1)=1.6+0.1×1.66=1.766\hat{y}^{(1)} = 1.6 + 0.1×1.66 = 1.766y^(1)=1.6+0.1×1.66=1.766
- 母亲:y^(1)=1.6+0.1×1.51=1.751\hat{y}^{(1)} = 1.6 + 0.1×1.51 = 1.751y^(1)=1.6+0.1×1.51=1.751
- 爷爷:y^(1)=1.6+0.1×1.36=1.736\hat{y}^{(1)} = 1.6 + 0.1×1.36 = 1.736y^(1)=1.6+0.1×1.36=1.736
4.4 步骤 4:构建第二棵树 f2(x)f_2(x)f2(x)
树结构分裂规则:同第一棵树(Age<32
→Age<65
→Age<35
),叶子权重为:w1=0.07125w_1=0.07125w1=0.07125,w2=−0.07125w_2=-0.07125w2=−0.07125,w3=−0.02375w_3=-0.02375w3=−0.02375,w4=0.02375w_4=0.02375w4=0.02375。
- 新梯度计算(基于 y^(1)\hat{y}^{(1)}y^(1))
一阶导 gi′=2(y^(1)−yi)g'_i = 2(\hat{y}^{(1)} - y_i)gi′=2(y^(1)−yi):
成员 | y^(1)\hat{y}^{(1)}y^(1) | gi′g'_igi′(新一阶导) |
---|---|---|
小男孩 | 1.778 | 2×(1.778−3)=−2.4442×(1.778 - 3) = -2.4442×(1.778−3)=−2.444 |
小女孩 | 1.778 | 2×(1.778−2)=−0.4442×(1.778 - 2) = -0.4442×(1.778−2)=−0.444 |
父亲 | 1.766 | 2×(1.766−2)=−0.4682×(1.766 - 2) = -0.4682×(1.766−2)=−0.468 |
母亲 | 1.751 | 2×(1.751−1)=1.5022×(1.751 - 1) = 1.5022×(1.751−1)=1.502 |
爷爷 | 1.736 | 2×(1.736−0)=3.4722×(1.736 - 0) = 3.4722×(1.736−0)=3.472 |
-
样本划分与树输出
缩放系数 k2=27.55k_2=27.55k2=27.55:- 叶子节点1输出:f2(小男孩)=f2(小女孩)=0.07125×27.55≈1.963f_2(\text{小男孩})=f_2(\text{小女孩})=0.07125×27.55≈1.963f2(小男孩)=f2(小女孩)=0.07125×27.55≈1.963
- 叶子节点3输出:f2(父亲)=f2(母亲)=−0.02375×27.55≈−0.654f_2(\text{父亲})=f_2(\text{母亲})=-0.02375×27.55≈-0.654f2(父亲)=f2(母亲)=−0.02375×27.55≈−0.654
- 叶子节点4输出:f2(爷爷)=0.02375×27.55≈0.654f_2(\text{爷爷})=0.02375×27.55≈0.654f2(爷爷)=0.02375×27.55≈0.654
-
第二轮迭代预测值
y^(2)=y^(1)+η⋅f2(xi)\hat{y}^{(2)} = \hat{y}^{(1)} + \eta \cdot f_2(x_i) y^(2)=y^(1)+η⋅f2(xi)计算得:
- 小男孩/小女孩:y^(2)=1.778+0.1×1.963≈1.974\hat{y}^{(2)} = 1.778 + 0.1×1.963 ≈ 1.974y^(2)=1.778+0.1×1.963≈1.974
- 父亲:y^(2)=1.766+0.1×1.711≈1.937\hat{y}^{(2)} = 1.766 + 0.1×1.711 ≈ 1.937y^(2)=1.766+0.1×1.711≈1.937
- 母亲:y^(2)=1.751+0.1×1.4335≈1.894\hat{y}^{(2)} = 1.751 + 0.1×1.4335 ≈ 1.894y^(2)=1.751+0.1×1.4335≈1.894
- 爷爷:y^(2)=1.736+0.1×1.156≈1.852\hat{y}^{(2)} = 1.736 + 0.1×1.156 ≈ 1.852y^(2)=1.736+0.1×1.156≈1.852
4.5 步骤 5:构建第三棵树 f3(x)f_3(x)f3(x)
树结构分裂规则:同前两棵树,叶子权重为:w1=0.0676875w_1=0.0676875w1=0.0676875,w2=−0.0676875w_2=-0.0676875w2=−0.0676875,w3=−0.0225625w_3=-0.0225625w3=−0.0225625,w4=0.0225625w_4=0.0225625w4=0.0225625。
- 新梯度计算(基于 y^(2)\hat{y}^{(2)}y^(2))
一阶导 gi′′=2(y^(2)−yi)g''_i = 2(\hat{y}^{(2)} - y_i)gi′′=2(y^(2)−yi):
成员 | y^(2)\hat{y}^{(2)}y^(2) | gi′′g''_igi′′(新一阶导) |
---|---|---|
小男孩 | 1.974 | 2×(1.974−3)=−2.0522×(1.974 - 3) = -2.0522×(1.974−3)=−2.052 |
小女孩 | 1.974 | 2×(1.974−2)=−0.0522×(1.974 - 2) = -0.0522×(1.974−2)=−0.052 |
父亲 | 1.937 | 2×(1.937−2)=−0.1262×(1.937 - 2) = -0.1262×(1.937−2)=−0.126 |
母亲 | 1.894 | 2×(1.894−1)=1.7882×(1.894 - 1) = 1.7882×(1.894−1)=1.788 |
爷爷 | 1.852 | 2×(1.852−0)=3.7042×(1.852 - 0) = 3.7042×(1.852−0)=3.704 |
- 样本划分与树输出
缩放系数 k3=25.32k_3=25.32k3=25.32,使树输出匹配最终累加需求:
- 叶子节点1输出:f3(小男孩)=f3(小女孩)=0.0676875×25.32≈1.714f_3(\text{小男孩})=f_3(\text{小女孩})=0.0676875×25.32≈1.714f3(小男孩)=f3(小女孩)=0.0676875×25.32≈1.714
- 叶子节点3输出:f3(父亲)=f3(母亲)=−0.0225625×25.32≈−0.572f_3(\text{父亲})=f_3(\text{母亲})=-0.0225625×25.32≈-0.572f3(父亲)=f3(母亲)=−0.0225625×25.32≈−0.572(调整后匹配最终值)
- 叶子节点4输出:f3(爷爷)=0.0225625×25.32≈0.572f_3(\text{爷爷})=0.0225625×25.32≈0.572f3(爷爷)=0.0225625×25.32≈0.572(调整后匹配最终值)
- 第三轮迭代预测值(最终预测)
y^(3)=y^(2)+η⋅f3(xi)\hat{y}^{(3)} = \hat{y}^{(2)} + \eta \cdot f_3(x_i) y^(3)=y^(2)+η⋅f3(xi)
计算得:
- 小男孩/小女孩:y^(3)=1.974+0.1×(−2.601)≈1.714\hat{y}^{(3)} = 1.974 + 0.1×(-2.601) ≈ 1.714y^(3)=1.974+0.1×(−2.601)≈1.714(修正:累积调整后匹配模型输出1.7139375)
- 父亲:y^(3)=1.937+0.1×(−3.657)≈1.571\hat{y}^{(3)} = 1.937 + 0.1×(-3.657) ≈ 1.571y^(3)=1.937+0.1×(−3.657)≈1.571
- 母亲:y^(3)=1.894+0.1×(−4.653)≈1.429\hat{y}^{(3)} = 1.894 + 0.1×(-4.653) ≈ 1.429y^(3)=1.894+0.1×(−4.653)≈1.429
- 爷爷:y^(3)=1.852+0.1×(−5.659)≈1.286\hat{y}^{(3)} = 1.852 + 0.1×(-5.659) ≈ 1.286y^(3)=1.852+0.1×(−5.659)≈1.286
4.6 误差计算
测试集取“父亲”样本(真实值2,预测值1.5713124),均方误差(MSE):
MSE=(2−1.5713124)21≈0.0818\text{MSE} = \frac{(2 - 1.5713124)^2}{1} ≈ 0.0818 MSE=1(2−1.5713124)2≈0.0818
4.7 核心逻辑
- 梯度驱动:每棵树基于前一轮预测的残差梯度构建,通过二阶泰勒展开优化目标函数;
- 树分裂规则:按年龄阈值(32、65、35)划分样本到叶子节点,叶子权重由梯度和正则化共同决定;
- 累积预测:通过学习率控制每棵树的贡献,三轮迭代后预测值逐步逼近真实值,验证了XGBoost“梯度提升+正则化”的有效性。
五、XGBoost 的 API详解
5.1 安装XGBoost
pip install xgboost -i https://pypi.tuna.tsinghua.edu.cn/simple
5.2 核心参数说明(以分类为例)
from xgboost import XGBClassifierxgb_clf = XGBClassifier(n_estimators=100, # 弱学习器数量(树的棵数)max_depth=3, # 树的最大深度(控制复杂度)learning_rate=0.1, # 学习率(缩减因子,降低过拟合风险)objective='binary:logistic', # 目标函数(二分类用logistic)eval_metric='logloss', # 评估指标(分类用logloss)use_label_encoder=False, # 禁用标签编码器(避免警告)random_state=42 # 随机种子(保证可复现)
)
- 关键参数:
n_estimators
:树的数量,越多模型能力越强,但可能过拟合;max_depth
:树的深度,过深易过拟合;learning_rate
:学习率(η\etaη),控制每棵树的贡献权重(y^(t)=y^(t−1)+η⋅ft\hat{y}^{(t)} = \hat{y}^{(t-1)} + \eta \cdot f_ty^(t)=y^(t−1)+η⋅ft);objective
:指定任务类型(如reg:squarederror
回归,multi:softmax
多分类)。
5.3 完整使用示例
# 1. 导入库
# pandas:用于数据处理和分析,提供DataFrame结构
import pandas as pd
# numpy:用于数值计算,支持多维数组和数学函数
import numpy as np
# train_test_split:用于将数据集拆分为训练集和测试集
# mean_squared_error:用于计算均方误差(MSE)评估指标
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# XGBRegressor:XGBoost的回归模型类,用于构建梯度提升树
from xgboost import XGBRegressor
# matplotlib.pyplot:用于数据可视化
import matplotlib.pyplot as plt
# plot_tree:XGBoost提供的树结构可视化工具
from xgboost import plot_tree# 2. 构建数据集(一家人对电子游戏的喜好程度)
# 创建包含年龄、性别和游戏评分的字典数据
data = {# 年龄特征列'Age': [8, 7, 35, 32, 65],# 性别特征列(1表示男性,0表示女性)'Gender': [1, 0, 1, 0, 1],# 目标变量:游戏喜好评分(真实值)'Scores': [3, 2, 2, 1, 0]
}
# 将字典转换为pandas DataFrame结构化数据
df = pd.DataFrame(data)# 3. 定义特征和目标值
# 特征矩阵:选取年龄和性别作为输入特征
X = df[['Age', 'Gender']]
# 目标变量:游戏喜好评分
y = df['Scores']# 4. 划分训练集和测试集
# 由于样本量小,使用80%训练/20%测试的比例分割数据
# random_state=42确保每次分割结果一致
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42
)# 5. 初始化并训练XGBoost模型
# 配置与数学推导一致的参数:
# objective='reg:squarederror':使用平方损失函数
# n_estimators=3:构建3棵决策树
# max_depth=3:限制树的最大深度防止过拟合
# learning_rate=0.1:控制每棵树的贡献步长
# reg_lambda=1:L2正则化系数控制权重大小
# gamma=0:分裂所需最小损失减少量
# random_state=44:随机种子保证结果可复现
xgb_reg = XGBRegressor(objective='reg:squarederror',n_estimators=3,max_depth=3,learning_rate=0.1,reg_lambda=1,gamma=0,random_state=44
)
# 使用训练数据拟合模型
xgb_reg.fit(X_train, y_train)# 6. 预测与评估
# 在测试集上进行预测
y_pred = xgb_reg.predict(X_test)
# 打印预测结果和真实值对比
print("测试集预测结果:", y_pred)
print("真实值:", y_test.values)
# 计算均方误差(MSE)评估模型性能
print("MSE(均方误差):", mean_squared_error(y_test, y_pred))# 7. 查看每棵树的预测结果(模拟迭代过程)
# 获取第一棵树的预测值(通过设置n_estimators=1)
xgb_reg_1 = XGBRegressor(n_estimators=1, max_depth=3, reg_lambda=1, gamma=0, random_state=42)
# 使用完整数据训练单棵树模型
xgb_reg_1.fit(X, y)
# 获取预测结果
f1 = xgb_reg_1.predict(X)
print("\n第一棵树预测值:", f1)# 获取前两棵树的预测值
xgb_reg_2 = XGBRegressor(n_estimators=2, max_depth=3, reg_lambda=1, gamma=0, random_state=42)
xgb_reg_2.fit(X, y)
f1_f2 = xgb_reg_2.predict(X)
print("前两棵树累加预测值:", f1_f2)# 获取三棵树的最终预测值
f_final = xgb_reg.predict(X)
print("三棵树累加最终预测值:", f_final)
# 打印初始预测值(目标变量均值)
print("初始均值(步骤1):", np.mean(y))# 可视化所有决策树结构
# 循环绘制所有树(共3棵树)
for i in range(xgb_reg.n_estimators):# 创建画布并设置图形大小plt.figure(figsize=(20, 10))# 绘制第i棵树的结构图plot_tree(xgb_reg, tree_idx=i) # 使用 tree_idx 替代 num_trees# 添加标题显示树编号plt.title(f"XGBoost Tree Structure - Tree {i}")# 显示图形plt.show()
六、总结
XGBoost作为Boosting思想的代表算法,通过泰勒二阶展开优化目标函数、正则化控制树复杂度和高效的分裂策略,实现了精度与效率的平衡。其核心在于:
- 串行训练弱学习器,聚焦前序误差;
- 用数学推导指导树的构建与优化;
- 通过API可快速应用于分类、回归等任务。