WARNING
🧪 Beta公测版本提示:教程主体已完成,正在优化细节,欢迎大家提Issue反馈问题或建议。
ml07 集成学习:Boosting 与 Stacking — demo.py 代码详解
运行方式
cd docs/ml/advanced/boosting/code
python demo.py代码逐段详解
第1步:DecisionStump — 最小的弱学习器
class DecisionStump:
def fit(self, X, y, sample_weight=None):
# 对每个特征搜索最优阈值
# 区分两种极性:左=0/右=1 和 左=1/右=0决策树桩(Decision Stump)是深度为 1 的决策树——它只做一次分裂。作为 AdaBoost 的弱学习器,它只需比随机猜测稍好即可(错误率 < 50%)。
树桩搜索最优分裂的复杂度为
第2步:AdaBoost 迭代训练
def fit(self, X, y):
w = np.ones(n_samples) / n_samples
for m in range(self.n_estimators):
stump.fit(X, y, sample_weight=w)
err = np.sum(w * incorrect) / np.sum(w)
alpha = 0.5 * np.log((1.0 - err) / err)
w = w * np.exp(alpha * incorrect)
w = w / np.sum(w)这段代码是 AdaBoost 的核心。让我们逐步理解:
加权错误率:不是简单的
incorrect/n,而是sum(w * incorrect) / sum(w)——考虑了每个样本的不同权重(困难样本权重大)alpha 的计算:
当
(随机猜测): ,该学习器不被考虑 当
(完美): ,该学习器权重极大 权重更新:
正确样本:权重不变(乘
) 错误样本:权重乘
(放大,让下轮更关注这些样本) 归一化:
w = w / np.sum(w)——确保权重和为 1
第3步:AdaBoost 预测 — 累积置信度
def predict(self, X):
for alpha, stump in zip(self.alphas, self.stumps):
pred_svm = 2 * stump.predict(X) - 1 # 0/1 → -1/+1
scores += alpha * pred_svm
return (scores >= 0).astype(np.int64)最终分类结果 = 所有学习器加权投票的符号:
其中
第4步:SimpleGBDT — 拟合残差的直觉
class SimpleGBDT:
def fit(self, X, y):
F = np.full(len(y), np.mean(y)) # 初始: 全部预测均值
for m in range(self.n_estimators):
residuals = y - F # MSE 的负梯度 = 残差
tree.fit(X, residuals) # 训练树拟合残差
F += self.learning_rate * tree.predict(X) # 更新GBDT 使用平方损失时的直观理解:
初始化:
——最朴素的预测 每轮迭代:
- 计算残差
- 训练一棵树来预测这些残差:
- 更新:
- 计算残差
学习率
(shrinkage):每棵树贡献的一部分(通常 )。小的学习率需要更多的树,但泛化效果更好。
当
第5步:对比实验 — 树桩 vs AdaBoost vs 随机森林
models = {
'Decision Stump': DecisionStump(),
'AdaBoost (50 stumps)': AdaBoost(n_estimators=50),
'Random Forest (50 trees)': RandomForestClassifier(n_estimators=50),
}这个对比展示了三种模型的决策边界差异:
- 决策树桩:一条直线分割——最简单的分类器
- AdaBoost:50 个树桩的加权组合——尽管每个树桩只是一条直线,但它们的加权累加产生了复杂而平滑的边界
- 随机森林:50 棵树投票——边界也平滑但形成机制不同(平均 vs 加权累加)
AdaBoost 的边界对噪声敏感——因为错误样本的权重会不断增大,一个异常值可能获得极大的权重。这是 AdaBoost 的一个已知缺点。
关键概念速查表
| 概念 | 公式 | 代码位置 | 关键说明 |
|---|---|---|---|
| 决策树桩 | depth=1 的决策树 | DecisionStump | AdaBoost 的弱学习器 |
| 加权错误率 | AdaBoost.fit() | 考虑了样本重要性 | |
| Alpha | compute_alpha | 学习器的"话语权" | |
| 权重更新 | update_weights | 错误样本权重放大 | |
| 指数损失 | 理论 | AdaBoost 的理论损失函数 | |
| 伪残差 | SimpleGBDT.fit() | 在函数空间中的梯度 | |
| MSE 残差 | residuals = y - F | 平方损失的负梯度 | |
| Shrinkage | self.learning_rate | 缩小每棵树的贡献 |
源码位置
clone 后打开(相对仓库根目录):
docs/ml/advanced/boosting/code/demo.py