0Pricing
Machine Learning Academy · 课时

提升方法直觉:顺序误差修正

您将手动在一个小型数据集上模拟三轮梯度提升,让每棵新树拟合当前集成模型的残差

提升方法直觉:顺序误差修正 是 CoddyKit 上的免费 Machine Learning Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Machine Learning Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Machine Learning Academy 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Boosting vs Bagging: A Key Distinction

Bagging trains many models in parallel on random subsets of data and combines them, reducing variance. Boosting trains models sequentially: each new model focuses on correcting the mistakes made by the previous ensemble. While bagging reduces variance, boosting primarily reduces bias — it can turn many weak, underfitting models into a powerful learner. This sequential error-correction strategy is the foundation of gradient boosting, AdaBoost, and XGBoost.

The Idea of Sequential Error Correction

Imagine you are predicting house prices. Your first model predicts everything around the mean and makes large errors. Instead of discarding it, you train a second model specifically on the residuals (the errors: actual − predicted) of the first model. The second model learns the patterns the first missed. A third model then corrects what the second still got wrong. Each new model makes a small improvement on the accumulated ensemble's current error. The final prediction is the sum of all models' predictions.

Boosting by Hand: Three Rounds

Consider a tiny regression dataset with 5 examples. Start with a model that predicts the mean. Compute residuals. Train a tree on residuals. Add a fraction of its predictions (the learning rate) to the current ensemble. Compute new residuals. Repeat. Each round, the residuals should shrink if the trees capture some pattern. After enough rounds, the residuals approach zero for the training set. This is the exact algorithm gradient boosting implements for regression with mean squared error loss.

import numpy as np
# Tiny example: manual 3-round gradient boosting for regression
y = np.array([3.0, 5.0, 2.0, 8.0, 1.0])
pred = np.full(5, y.mean())  # Round 0: predict the mean
print('Round 0 pred:', pred, 'Residuals:', y - pred)
# Round 1: suppose our tree predicts half the residual
residuals_1 = y - pred
pred += 0.5 * residuals_1  # learning_rate=0.5
print('Round 1 pred:', pred, 'Residuals:', np.round(y - pred, 2))
# Round 2
residuals_2 = y - pred
pred += 0.5 * residuals_2
print('Round 2 pred:', np.round(pred, 2), 'Residuals:', np.round(y - pred, 3))

The Learning Rate (Shrinkage)

The learning rate (often called shrinkage) scales down each tree's contribution before adding it to the ensemble. Instead of fully correcting the residual in one step (learning rate = 1.0), boosting takes a small step (e.g., 0.1) and lets subsequent trees correct what remains. A smaller learning rate requires more trees to achieve the same fit but generalises better because no single tree dominates. The trade-off: very small learning rates need very large n_estimators, increasing training time.

Gradient Descent in Function Space

Gradient boosting is named after the connection to gradient descent. In standard gradient descent, we update parameters by moving in the direction that reduces the loss. In gradient boosting, we update the prediction function by fitting a new tree to the negative gradient of the loss with respect to the current predictions. For mean squared error loss, the negative gradient is simply the residual (actual − predicted). For other losses (log-loss, absolute error), it computes the appropriate pseudo-residuals.

GradientBoostingClassifier in scikit-learn

scikit-learn provides GradientBoostingClassifier which implements the original Friedman gradient boosting algorithm. Key parameters: n_estimators (number of trees), learning_rate (shrinkage), max_depth (depth of each tree — shallow trees are preferred, typically 3-5), and subsample (fraction of training data for each tree, adding stochastic element that improves generalisation). The combination of small learning rate, many shallow trees, and subsampling is the standard recipe.

from sklearn.ensemble import GradientBoostingClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score

X, y = load_breast_cancer(return_X_y=True)
gb = GradientBoostingClassifier(
    n_estimators=200,
    learning_rate=0.1,
    max_depth=3,
    subsample=0.8,
    random_state=42
)
scores = cross_val_score(gb, X, y, cv=5)
print('GradientBoosting CV:', round(scores.mean(), 4))

Overfitting in Boosting

Unlike bagging, boosting can overfit with enough estimators, especially at a high learning rate. As you add more rounds, the training loss keeps decreasing but the validation loss eventually rises. The solution is: (1) use early stopping — monitor validation loss and stop when it stops improving; (2) use a small learning rate (0.01-0.1) with many trees rather than a large rate with few; (3) regularise individual trees with shallow depth and minimum samples per leaf. These techniques are all exposed in XGBoost and LightGBM's rich hyperparameter sets.

AdaBoost: The Original Boosting Algorithm

AdaBoost (Adaptive Boosting) was the first practical boosting algorithm. Instead of fitting trees on residuals, it assigns sample weights: misclassified examples get higher weight in the next round, so subsequent trees focus on the hard cases. Each tree's contribution to the final vote is also weighted by its accuracy — better trees get more say. AdaBoost is implemented in scikit-learn as AdaBoostClassifier and is historically important, but gradient boosting (and XGBoost) has largely superseded it in practice.

from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score

X, y = load_breast_cancer(return_X_y=True)
ada = AdaBoostClassifier(
    estimator=DecisionTreeClassifier(max_depth=1),  # stumps
    n_estimators=200,
    learning_rate=0.5,
    random_state=42
)
print('AdaBoost CV:', round(cross_val_score(ada, X, y, cv=5).mean(), 4))

Stochastic Gradient Boosting

Setting subsample < 1.0 in gradient boosting introduces randomness: each tree is trained on a random subset of the training data (without replacement). This stochastic element reduces correlation between trees and often improves generalisation — much like the dropout idea in neural networks. A typical value is subsample=0.8. When subsample is less than 1, scikit-learn also computes an out-of-bag estimate of the improvement at each round, accessible via oob_improvement_.

When Boosting Beats Random Forest

Boosting typically outperforms random forests on clean tabular data where the signal-to-noise ratio is high and there are complex feature interactions. The sequential error-correction mechanism lets boosting squeeze out almost all predictable signal. However, boosting is more sensitive to noisy data and outliers — since each round focuses on hard examples, noise can pull the model in wrong directions. Random forests are more robust to label noise. For noisy, messy real-world data, the choice depends on the specific dataset.

from sklearn.ensemble import GradientBoostingClassifier, RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score

X, y = load_breast_cancer(return_X_y=True)
gb = GradientBoostingClassifier(n_estimators=200, learning_rate=0.1, max_depth=3, random_state=42)
rf = RandomForestClassifier(n_estimators=200, random_state=42)
print('Gradient Boosting:', round(cross_val_score(gb, X, y, cv=5).mean(), 4))
print('Random Forest:    ', round(cross_val_score(rf, X, y, cv=5).mean(), 4))

Boosting for Regression Tasks

Gradient boosting is equally powerful for regression. GradientBoostingRegressor minimises a regression loss by default (squared error), but also supports absolute error (loss='absolute_error', robust to outliers) and Huber loss (loss='huber', combining squared for small errors and absolute for large ones). For house price prediction, energy forecasting, and similar tasks, gradient boosting consistently outperforms linear regression and often matches or beats neural networks on tabular data without the need for GPU hardware.

from sklearn.ensemble import GradientBoostingRegressor
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import cross_val_score
import numpy as np

X, y = fetch_california_housing(return_X_y=True)
gbr = GradientBoostingRegressor(n_estimators=200, learning_rate=0.1, max_depth=4,
                                  subsample=0.8, random_state=42)
rmse = np.sqrt(-cross_val_score(gbr, X, y, scoring='neg_mean_squared_error', cv=3).mean())
print('GBR Regression RMSE:', round(rmse, 4))

Quick Check

Test your understanding of Boosting and Sequential Error Correction from this lesson.

Lesson Recap

In this lesson you learned: boosting trains models sequentially, each correcting the residual errors of the previous ensemble, the learning rate scales each tree's contribution and controls overfitting, and gradient boosting minimises a differentiable loss by fitting trees to the negative gradient. Next up we explore XGBoost's regularisation and early stopping features.

常见问题解答

「提升方法直觉:顺序误差修正」课时是免费的吗?

是的 — 「提升方法直觉:顺序误差修正」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Machine Learning Academy 课程的其余内容,请升级到 CoddyKit PRO。 Machine Learning Academy 课程共包含 4 节课。

「提升方法直觉:顺序误差修正」这节课中我会学到什么?

您将手动在一个小型数据集上模拟三轮梯度提升,让每棵新树拟合当前集成模型的残差 你通过在浏览器中直接运行的动手代码来练习 Machine Learning Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Machine Learning Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Machine Learning Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「提升方法直觉:顺序误差修正」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Machine Learning Academy 课中编写并运行代码吗?

能。每节 Machine Learning Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 提升方法直觉:顺序误差修正
  2. XGBoost:正则化、提前停止与特征重要性
  3. LightGBM:按叶节点生长与速度优势
  4. 关键超参数:学习率、n_estimators 与 max_depth
← 返回 Machine Learning Academy