1. 项目概述:这不是又一篇“XGBoost入门”,而是一次手把手的算法解剖
你肯定见过这样的场景:在Kaggle排行榜上,XGBoost模型像一道闪电划过,稳稳占据Top 3;在公司内部的数据科学分享会上,同事一句“我们用XGBoost跑通了baseline”,底下立刻响起心领神会的轻笑。但当轮到你自己要调参、要debug、要向非技术背景的业务方解释“为什么这个模型比随机森林更准”时,却常常卡在一句话上:“它……就是梯度提升加了点正则化?”——这就像说“飞机能飞,是因为它有翅膀和引擎”,没错,但离真正理解还差着万米高空。
这篇内容,就是为那个卡住的你写的。它不假设你是数学系博士,也不把你当刚学完sklearn的新人;它假设你已经用xgboost.XGBClassifier()跑过至少一个真实项目,见过learning_rate、max_depth、gamma这些参数,也踩过“训练集AUC 0.98,测试集跌到0.72”的坑。我们不讲“XGBoost是什么”,而是直接切开它的胸腔,看心脏怎么跳、血液怎么流、神经信号怎么传递。核心关键词就三个:梯度(Gradient)、曲率(Hessian)、结构化正则(Structured Regularization)。这三个词,就是XGBoost区别于传统GBM的全部秘密,也是它能在噪声数据中依然稳健、在高维稀疏特征下依然精准的根本原因。
我做机器学习工程落地超过八年,从金融风控模型到工业设备故障预测,XGBoost是我工具箱里最常被磨得发亮的那把刀。但直到我亲手用NumPy一行行复现过它的分裂逻辑、手动计算过三棵树的残差累积、在内存里追踪过缺失值的每一次路由决策,我才真正明白:所谓“强大”,从来不是黑盒里的魔法,而是每一个数学符号背后,都对应着一个明确的工程意图。比如,gamma参数不是为了“让模型更简单”,而是为了给每一次分裂设置一个“经济门槛”——只有当这次分裂带来的收益(Gain)大于gamma这个成本,它才被允许发生;再比如,lambda不是抽象的“L2惩罚”,而是直接参与最优叶节点权重w_j* = -G_j/(H_j + lambda)的计算,它让模型在修正错误时,永远保持一份克制,避免一次猛药下去把整个预测拉偏。
所以,如果你的目标是“能用”,那本文可能略显冗长;但如果你的目标是“敢改、敢调、敢解释、敢兜底”,那接下来的每一段,都是我在真实项目里反复验证过的硬核逻辑。我们不用虚构的鸢尾花数据,而是全程跟随一个20行4列的真实教学数据集,从第一棵树的根节点分裂开始,一步步算出第二棵树每个叶子的精确权重,亲眼看着-0.530和+0.624这两个数字如何从梯度与曲率的运算中自然浮现。这不是理论推导,这是手术室里的实时直播。
2. 核心设计思路:为什么XGBoost不是“GBM+更快的代码”?
2.1 传统GBM的“单点突破”思维及其瓶颈
在深入XGBoost之前,我们必须先看清它要解决的那个“旧问题”。传统梯度提升机(GBM)的核心思想非常直观:第一棵树拟合原始标签y_i,第二棵树拟合第一棵树的残差r_i = y_i - f_1(x_i),第三棵树拟合前两棵树的残差之和r_i = y_i - f_1(x_i) - f_2(x_i),以此类推。它的损失函数优化目标,可以简化为:
minimize Σ l(y_i, f_1(x_i) + f_2(x_i) + ... + f_t(x_i))其中l()是损失函数,比如回归用MSE,分类用Log Loss。这个公式本身没有错,但它隐含了一个关键假设:我们总能精确地、无代价地拟合残差。在实践中,这导致了两个致命的工程缺陷。
第一个缺陷是对残差的“暴力拟合”。GBM在构建第t棵树时,会把前t-1棵树的预测和ŷ^(t-1)_i当作一个固定常数,然后要求新树f_t(x_i)去完美匹配y_i - ŷ^(t-1)_i。这听起来很合理,但问题在于,残差本身是一个高度噪声化的信号。比如,在我们的20样本数据集中,如果Tree 1对某个样本x_3的预测是0.85,而真实标签是1.0,那么残差就是0.15。GBM会命令Tree 2必须输出0.15。但如果这个0.15的误差,其实是由一个微小的、不可靠的特征扰动引起的呢?GBM不会区分,它只会把这个噪声当作一个神圣的指令来执行。结果就是,后续的树会不断在噪声上“雕花”,模型的方差(Variance)急剧膨胀,泛化能力断崖式下跌。这就是为什么你在调参时,常常发现n_estimators=100的效果远不如n_estimators=50——后50棵树,大部分时间都在给前50棵树的噪声“擦屁股”。
第二个缺陷是分裂标准的“短视性”。GBM选择最佳分裂点时,通常使用一阶信息,比如MSE下的“方差减少”或Log Loss下的“基尼不纯度减少”。它只关心“分裂后,左右子节点的预测值平均离真实值更近了多少”,却完全忽略了“这个更近,是建立在多陡峭的山坡上”。想象一下,一个分裂能让损失下降0.1,但所有样本都挤在损失函数一个极尖锐的峰顶附近;另一个分裂只让损失下降0.08,但样本均匀分布在一片平缓的谷底。GBM会选前者,因为它只看下降的绝对值。而XGBoost会选后者,因为它还看了“这片谷底有多宽、多平”。这个“宽度和平缓度”,就是由二阶导数——曲率(Hessian)——所刻画的。
提示:你可以把梯度(Gradient)理解为“当前方向上的坡度”,它告诉你该往哪走;而曲率(Hessian)则是“当前方向上的弯曲程度”,它告诉你走一步会滑多远、会不会摔跤。只看坡度,是盲人摸象;坡度+曲率,才是全息导航。
2.2 XGBoost的“双轨制”设计哲学:同时驾驭Bias与Variance
XGBoost的整个数学框架,就是围绕着如何同时、优雅地驯服偏差(Bias)和方差(Variance)这两个宿敌而构建的。它没有试图用一个参数去平衡二者,而是为它们各自铺设了一条独立的、可精确调控的轨道。
第一条轨道:Bias(偏差)的精细化校准——通过二阶泰勒展开
XGBoost没有直接优化复杂的l(y_i, ŷ^(t-1)_i + f_t(x_i)),而是将其在ŷ^(t-1)_i处进行二阶泰勒展开:
l(y_i, ŷ^(t-1)_i + f_t(x_i)) ≈ l(y_i, ŷ^(t-1)_i) + g_i * f_t(x_i) + (1/2) * h_i * f_t²(x_i)其中:
g_i = ∂l/∂ŷ |_(ŷ=ŷ^(t-1)_i)是损失函数在当前预测点的一阶导数,即梯度。h_i = ∂²l/∂ŷ² |_(ŷ=ŷ^(t-1)_i)是损失函数在当前预测点的二阶导数,即曲率(Hessian)。
这个看似简单的数学变换,带来了革命性的效果。它把一个非线性的、依赖于具体损失函数形式的优化问题,转化成了一个通用的、二次型的优化问题。更重要的是,它把“拟合残差”这个模糊的概念,拆解成了两个清晰、可计算、可解释的物理量:
g_i告诉我们,对于样本i,当前预测是偏高(g_i > 0)还是偏低(g_i < 0),以及偏差有多大。h_i告诉我们,这个偏差的“可信度”有多高。h_i越大,说明损失函数在当前点越“平坦”,意味着我们对这个偏差的估计越有信心,可以放心地进行较大步长的修正;反之,h_i越小,说明损失函数越“陡峭”,意味着这个偏差可能只是局部噪声,我们应该谨慎,只做微调。
在我们的20样本数据集上,当Tree 1对x_3(y_3=1)的预测是0.85时,g_3 = 0.85 - 1.0 = -0.15,h_3 = 0.85 * (1-0.85) = 0.1275。这个-0.15是明确的指令:“快把预测往上提!”,而0.1275则是温和的提醒:“别提太猛,这里坡有点陡。”
第二条轨道:Variance(方差)的结构性约束——通过结构化正则项
仅仅有了梯度和曲率还不够,因为一棵过于复杂的树,哪怕每片叶子的权重都算得再准,也会过拟合。XGBoost的正则项Ω(f_t)不是简单地对叶节点权重w_j加个L2范数,而是对整棵树的结构进行惩罚:
Ω(f_t) = γ * T + (1/2) * λ * Σ w_j²其中:
T是树的叶子节点总数。γ * T这一项,是对树的复杂度(Complexity)的直接惩罚。它迫使算法思考:“为了多增加一个叶子,我获得的收益是否值得付出γ的代价?” 这就是为什么gamma被称为“分裂的经济门槛”。在我们的数据集上,如果gamma=0.1,而一个潜在分裂的Gain只有0.08,那么这个分裂就会被无情地拒绝,无论它看起来多么诱人。Σ w_j²是所有叶节点权重的平方和。(1/2) * λ * Σ w_j²这一项,是对叶节点预测强度(Prediction Magnitude)的惩罚。它确保每一棵树的贡献都是“温和的”、“渐进的”。lambda越大,w_j*就越小,模型的每一步修正就越保守。这正是XGBoost能使用learning_rate=0.1甚至0.01,并配合n_estimators=1000依然稳定的原因——它把“大步快跑”变成了“小步快走”,每一步都踏在坚实的大地上。
注意:
gamma和lambda不是超参数调优的“调味料”,它们是XGBoost算法骨架的“钢筋”。gamma控制树的“形状”(宽而浅 vs 窄而深),lambda控制树的“力度”(激进修正 vs 温和引导)。忽略它们,就等于只用了XGBoost一半的威力。
2.3 从“样本视角”到“叶节点视角”的范式跃迁
XGBoost的第三个核心洞见,是彻底改变了优化问题的求解视角。传统方法(包括GBM)的损失函数,是对所有n个样本求和:
L = Σᵢ₌₁ⁿ [g_i * f_t(x_i) + (1/2) * h_i * f_t²(x_i)] + Ω(f_t)这在计算上是低效的,因为你需要为每个样本单独计算f_t(x_i)。XGBoost的天才之处在于,它意识到:在一棵决策树中,成百上千个样本,最终只会落在几十个叶节点上;而落在同一个叶节点j的所有样本i ∈ I_j,它们的预测值f_t(x_i)是完全相同的,即叶节点权重w_j。于是,它将求和对象从“样本i”切换到了“叶节点j”:
L = Σⱼ₌₁ᵀ [ (Σᵢ∈Iⱼ g_i) * w_j + (1/2) * (Σᵢ∈Iⱼ h_i + λ) * w_j² ] + γ * T其中:
G_j = Σᵢ∈Iⱼ g_i是落入叶节点j的所有样本的梯度之和。H_j = Σᵢ∈Iⱼ h_i是落入叶节点j的所有样本的曲率之和。
这个转换,其意义远不止于计算加速。它标志着XGBoost的思考单元,从微观的“单个样本”上升到了宏观的“样本群体”。它不再问“这个样本该被分到哪”,而是问“这一群具有相似梯度和曲率的样本,作为一个整体,应该得到一个多大的修正值?” 这种群体思维,是XGBoost天然具备鲁棒性的根源。当一个叶节点里混入几个噪声样本时,它们的g_i和h_i会被淹没在群体的G_j和H_j之中,无法主导整个叶节点的权重w_j*。
在我们的数据集上,当Tree 2按Column B < 0.5分裂时,左叶(B=0)包含了10个y_i=0的样本。它们的g_i都是正值(因为Tree 1对它们的预测偏高了),G_j=1.01;h_i都比较小(因为预测值接近0或1,曲率低),H_j=0.906。于是,w_j* = -1.01/(0.906 + 1.0) = -0.530。这个-0.530,是这10个样本作为一个“负向修正集群”的集体意志,而不是某个单一样本的任性要求。
3. 核心细节解析:从数学公式到代码实现的完整映射
3.1 梯度(g_i)与曲率(h_i):驱动一切的两个引擎
在XGBoost的世界里,g_i和h_i是所有决策的源头活水。它们不是凭空产生的,而是严格由你选择的损失函数l(y, ŷ)决定的。理解它们,是理解XGBoost的第一道门。
对于回归任务(Loss = MSE):
l(y, ŷ) = (y - ŷ)²g_i = ∂l/∂ŷ = -2*(y_i - ŷ^(t-1)_i)h_i = ∂²l/∂ŷ² = 2
这是一个极其简洁的特例。g_i就是残差的两倍(带负号),h_i是一个恒定的2。这意味着,MSE下的XGBoost,其分裂逻辑与GBM高度相似,因为曲率是常数,不提供额外信息。这也是为什么XGBoost在回归问题上,优势不如在分类问题上那么显著。
对于二分类任务(Loss = Log Loss / Cross-Entropy):
l(y, ŷ) = -y * log(ŷ) - (1-y) * log(1-ŷ)g_i = ∂l/∂ŷ = ŷ^(t-1)_i - y_ih_i = ∂²l/∂ŷ² = ŷ^(t-1)_i * (1 - ŷ^(t-1)_i)
这才是XGBoost大放异彩的战场。g_i依然是残差,但h_i现在变成了一个动态的、与当前预测值强相关的量。它的取值范围是[0, 0.25],在ŷ=0.5时达到最大值0.25,在ŷ=0或ŷ=1时趋近于0。这个特性至关重要。
让我们用数据集中的两个典型样本,来感受h_i的“智慧”:
- 样本
x_3(y_3=1,ŷ^(1)_3=0.85):g_3 = 0.85 - 1.0 = -0.15,h_3 = 0.85 * 0.15 = 0.1275。预测值0.85已经相当接近1.0,所以曲率0.1275中等偏上,表明此处的损失面相对平缓,可以进行中等幅度的修正。 - 样本
x_1(y_1=0,ŷ^(1)_1=0.10):g_1 = 0.10 - 0 = 0.10,h_1 = 0.10 * 0.90 = 0.09。预测值0.10离0.0也很近,曲率0.09略低于x_3,同样支持温和修正。 - 假设一个新样本
x_new(y_new=1,ŷ^(1)_new=0.50):g_new = 0.50 - 1.0 = -0.50,h_new = 0.50 * 0.50 = 0.25。此时,g_new的绝对值是x_3的3.3倍,但h_new也是x_3的2倍。这说明,虽然偏差很大,但损失面在此处最“开阔”,模型可以且应该进行一次更大胆的修正。
实操心得:在调试XGBoost模型时,我习惯在训练过程中打印出一批样本的
g_i和h_i。如果发现大量样本的h_i都趋近于0(比如< 0.01),这往往是一个危险信号,意味着模型的预测已经“撞墙”了——要么是learning_rate太大,导致早期预测就过度饱和;要么是max_depth太小,树太浅,无法有效降低预测值的不确定性。这时,降低learning_rate或增加max_depth通常是更有效的解法,而不是盲目增加n_estimators。
3.2 最优叶节点权重(w_j*):一个闭式解的威力
有了G_j和H_j,计算最优叶节点权重w_j*就变成了一道高中数学题。我们将前面的叶节点视角损失函数L对w_j求导,并令其为零:
∂L/∂w_j = G_j + (H_j + λ) * w_j = 0解得:
w_j* = -G_j / (H_j + λ)这个公式,是XGBoost最核心、最优雅的闭式解(Closed-form Solution)。它不需要任何迭代优化,只要知道一个叶节点里所有样本的梯度和与曲率和,就能瞬间算出这个叶节点最理想的预测值。
让我们用数据集中的Tree 2的两个叶子,来完成一次完整的计算:
Leaf 1 (Column B = 0,y_i = 0for all 10 samples):
G_1 = 1.01(Sum of positive gradients)H_1 = 0.906(Sum of curvatures)λ = 1.0(Our chosen regularization strength)w_1* = -1.01 / (0.906 + 1.0) = -1.01 / 1.906 = -0.530
Leaf 2 (Column B = 1,y_i = 1for all 10 samples):
G_2 = -1.35(Sum of negative gradients)H_2 = 1.164(Sum of curvatures)λ = 1.0w_2* = -(-1.35) / (1.164 + 1.0) = 1.35 / 2.164 = 0.624
现在,我们可以清晰地看到lambda的杠杆效应:
- 如果
λ = 0(无正则):w_1* = -1.01/0.906 = -1.115,w_2* = 1.35/1.164 = 1.160。修正幅度翻倍,模型变得非常激进。 - 如果
λ = 5.0(强正则):w_1* = -1.01/5.906 = -0.171,w_2* = 1.35/6.164 = 0.219。修正幅度被压缩到原来的1/3,模型变得极度保守。
这个公式还揭示了XGBoost处理“不平衡数据”的一种隐式机制。假设一个叶节点里有99个y=0的样本和1个y=1的样本。G_j会是一个很大的正值(因为99个正梯度),而H_j也会很大(因为99个样本的ŷ都接近0,h_i很小,但数量多)。最终的w_j*会是一个中等大小的负数,它会温和地将整个叶节点的预测拉向0,而不会被那个孤零零的y=1样本牵着鼻子走。这是一种基于统计显著性的、天然的鲁棒性。
3.3 分裂增益(Gain):衡量一次分裂价值的终极标尺
知道了w_j*,我们就能计算出,对于一个给定的树结构(即一个特定的分裂方案),它的总损失是多少。这个损失值,就是L̃^(t)(q),其中q代表树的结构。但XGBoost在实际寻找最佳分裂点时,并不需要计算整个树的损失,它只需要知道:相对于不分裂,这次分裂能带来多少净收益?这个净收益,就是分裂增益(Split Gain)。
其公式为:
Gain = (1/2) * [ (G_L²)/(H_L + λ) + (G_R²)/(H_R + λ) - (G_I²)/(H_I + λ) ] - γ其中:
G_L, H_L和G_R, H_R是分裂后左右子节点的梯度和与曲率和。G_I, H_I是分裂前父节点(即当前待分裂节点)的梯度和与曲率和。γ是分裂的固定成本。
这个公式的精妙之处,在于它完美地融合了Bias-Variance权衡:
(G_L²)/(H_L + λ)和(G_R²)/(H_R + λ)是分裂后的“收益”。G²/H这个形式,本质上是(-G/H)² * H,而-G/H正是w_j*。所以,这部分衡量的是:分裂后,两个新叶节点所能提供的、经过正则化约束的“最大修正能力”的平方和。(G_I²)/(H_I + λ)是分裂前的“机会成本”。它代表了如果不分裂,而是在父节点上直接放置一个叶节点,所能达到的最佳修正能力。- 整个方括号内的部分,就是分裂带来的“净修正能力提升”。
- 最后的
- γ,则是对新增一个叶节点所带来的复杂度成本的扣除。
回到我们数据集上Column C < 3的分裂计算:
G_L = 0.64,H_L = 0.793G_R = -1.08,H_R = 1.277G_I = -0.44,H_I = 2.070λ = 1.0,γ = 0
代入公式:
Gain = 0.5 * [ (0.64²)/(0.793+1.0) + ((-1.08)²)/(1.277+1.0) - ((-0.44)²)/(2.070+1.0) ] - 0 = 0.5 * [ 0.4096/1.793 + 1.1664/2.277 - 0.1936/3.070 ] = 0.5 * [ 0.228 + 0.512 - 0.063 ] = 0.5 * 0.677 = 0.339Gain = 0.339 > 0,说明这次分裂是有价值的。如果Gain是负数,比如-0.05,那么XGBoost会果断放弃这次分裂,因为γ=0的成本已经超过了它能带来的任何收益。
注意事项:在实际代码中,XGBoost会遍历所有特征、所有可能的阈值,对每一个候选分裂点都计算一次
Gain,然后选出Gain最大的那个作为最终分裂点。这个过程是计算密集型的,也是XGBoost后续所有性能优化(如预排序、直方图、并行化)所要攻克的核心战场。
4. 实操过程:用20行数据,亲手“组装”一棵XGBoost树
4.1 数据准备与初始状态:我们的20样本“沙盒”
为了确保所有计算都真实可感,我们首先完整列出这个贯穿全文的教学数据集。它有20行,4列特征(A, B, C, D)和1列二元目标变量Y。
| Sample | A | B | C | D | Y |
|---|---|---|---|---|---|
| x₁ | 1.2 | 0 | 0 | 0.8 | 0 |
| x₂ | 2.1 | 0 | ? | 1.1 | 0 |
| x₃ | 3.0 | 1 | 6 | 1.0 | 1 |
| x₄ | 0.9 | 1 | 0 | 0.9 | 1 |
| x₅ | 1.8 | 0 | ? | 0.7 | 0 |
| x₆ | 2.5 | 1 | 5 | 1.2 | 1 |
| x₇ | 1.0 | 0 | 1 | 0.6 | 0 |
| x₈ | 2.8 | 1 | 4 | 0.9 | 1 |
| x₉ | 1.1 | 0 | 1 | 0.5 | 0 |
| x₁₀ | 2.2 | 1 | 3 | 1.0 | 1 |
| x₁₁ | 0.8 | 0 | 2 | 0.4 | 0 |
| x₁₂ | 2.9 | 1 | 3 | 1.1 | 1 |
| x₁₃ | 1.3 | 0 | 2 | 0.7 | 0 |
| x₁₄ | 2.7 | 1 | 4 | 0.8 | 1 |
| x₁₅ | 0.7 | 0 | 0 | 0.3 | 0 |
| x₁₆ | 2.6 | 1 | 5 | 0.9 | 1 |
| x₁₇ | 0.9 | 0 | 1 | 0.5 | 0 |
| x₁₈ | 2.4 | 1 | 6 | 1.0 | 1 |
| x₁₉ | 1.5 | 0 | 2 | 0.6 | 0 |
| x₂₀ | 2.3 | 1 | 5 | 0.8 | 1 |
(注:?表示缺失值,将在Part 13中处理)
我们设定初始状态:所有样本的初始预测值ŷ^(0)_i = 0.5(二分类的默认起点)。因此,对于所有样本,初始的g_i = 0.5 - y_i,h_i = 0.5 * 0.5 = 0.25。
- 对于
y_i = 0的10个样本(x₁, x₂, x₅, x₇, x₉, x₁₁, x₁₃, x₁₅, x₁₇, x₁₉),g_i = 0.5。 - 对于
y_i = 1的10个样本(x₃, x₄, x₆, x₈, x₁₀, x₁₂, x₁₄, x₁₆, x₁₈, x₂₀),g_i = -0.5。
所以,根节点的G_I = 10*0.5 + 10*(-0.5) = 0,H_I = 20*0.25 = 5.0。
4.2 构建Tree 1:一次完美的、教科书般的分裂
现在,我们站在Tree 1的根节点,所有20个样本都在这里。我们需要评估所有特征的所有可能分裂点。
评估Column B < 0.5(即B=0vsB=1):
- 左子节点(
B=0):10个样本(x₁, x₂, x₅, x₇, x₉, x₁₁, x₁₃, x₁₅, x₁₇, x₁₉),y_i全为0。G_L = 10 * 0.5 = 5.0H_L = 10 * 0.25 = 2.5
- 右子节点(
B=1):10个样本(x₃, x₄, x₆, x₈, x₁₀, x₁₂, x₁₄, x₁₆, x₁₈, x₂₀),y_i全为1。G_R = 10 * (-0.5) = -5.0H_R = 10 * 0.25 = 2.5
Gain = 0.5 * [ (5.0²)/(2.5+1.0) + ((-5.0)²)/(2.5+1.0) - (0²)/(5.0+1.0) ] - 0= 0.5 * [ 25/3.5 + 25/3.5 - 0 ]= 0.5 * [ 7.143 + 7.143 ] = 0.5 * 14.286 = 7.143
这是一个巨大的Gain!我们再快速评估其他特征,看看是否有能超越它的。
评估Column A < 1.5:
- 左子节点(
A < 1.5):x₁, x₄, x₇, x₉, x₁₁, x₁₃, x₁₅, x₁₇ → 8个样本,其中y=0的有6个,y=1的有2个(x₄)。 G_L ≈ 6*0.5 + 2*(-0.5) = 3.0 - 1.0 = 2.0H_L = 8*0.25 = 2.0- 右子节点(
A >= 1.5):12个样本,G_R = -2.0,H_R = 3.0 Gain ≈ 0.5 * [ (2.0²)/3.0 + (2.0²)/3.0 - 0 ] = 0.5 * [ 1.333 + 1.333 ] = 1.333
远小于7.143。
结论:Column B < 0.5是Tree 1的绝对最优分裂。它实现了完美的类别分离,Gain高达7.143,远超其他任何选项。这印证了我们最初的观察:“当Column B = 1时,Target Y tends to be 1”。
分裂完成后,我们计算两个叶节点的权重:
w_left* = -5.0 / (2.5 + 1.0) = -5.0 / 3.5 = -1.429w_right* = -(-5.0) / (2.5 + 1.0) = 5.0 / 3.5 = 1.429
因此,Tree 1的预测为:
- 若
B=0,f_1(x_i) = -1.429 - 若
B=1,f_1(x_i) = 1.429
注意,这是logit空间的预测,不是概率。最终概率需要经过sigmoid变换:P(Y=1|x) = 1 / (1 + exp(-f_1(x)))。
B=0时,P = 1 / (1 + exp(1.429)) ≈ 0.192B=1时,P = 1 / (1 + exp(-1.429)) ≈ 0.808
这已经是一个相当不错的模型了,AUC远高于0.5。