自助聚合(Bagging)详解
您将手动实现自助采样,在每个样本上训练分类器,并理解为什么对多样化模型取平均能够降低方差
自助聚合(Bagging)详解 是 CoddyKit 上的免费 Machine Learning Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Machine Learning Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Machine Learning Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
What Is Bootstrap Aggregation?
Bootstrap Aggregation, commonly called Bagging, is an ensemble technique that trains multiple models on different random subsets of the training data and combines their predictions. The word bootstrap comes from statistics and means sampling with replacement from your data. By averaging or voting across many diverse models, bagging dramatically reduces the variance of the final prediction without increasing bias.
Sampling With Replacement Explained
Sampling with replacement means each bootstrap sample is drawn independently from the full dataset — the same row can appear multiple times in a single sample while other rows may be excluded entirely. For a dataset of N examples, each bootstrap sample also contains N rows. On average, about 63.2% of unique examples appear in any given bootstrap sample, and the remaining ~37% form the out-of-bag set that can be used for validation.
import numpy as np
np.random.seed(42)
data = np.arange(10) # [0, 1, 2, ..., 9]
bootstrap_sample = np.random.choice(data, size=len(data), replace=True)
print('Original:', data)
print('Bootstrap sample:', bootstrap_sample)Why Diversity Reduces Variance
Suppose you have n independent models each with variance σ². If you average their predictions, the variance of the average is σ²/n — it shrinks as you add more models. In practice, models trained on bootstrap samples are correlated (they share the same training distribution), so the reduction is partial but still significant. The key insight is that averaging reduces variance without increasing bias, leading to better generalisation.
Implementing Bagging by Hand
You can implement bagging manually by training a list of estimators, each on a different bootstrap sample, then averaging their outputs. This shows exactly what BaggingClassifier does under the hood. Understanding the manual version makes it easier to diagnose problems and extend the technique to custom models.
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import numpy as np
X, y = load_iris(return_X_y=True)
n_estimators = 10
models = []
for _ in range(n_estimators):
idx = np.random.choice(len(X), size=len(X), replace=True)
X_boot, y_boot = X[idx], y[idx]
tree = DecisionTreeClassifier()
tree.fit(X_boot, y_boot)
models.append(tree)
# Predict by majority vote
predictions = np.array([m.predict(X) for m in models])
ensemble_pred = [np.bincount(col).argmax() for col in predictions.T]
print('Ensemble accuracy:', np.mean(ensemble_pred == y))scikit-learn BaggingClassifier
scikit-learn provides BaggingClassifier that wraps any base estimator and automates the bootstrap sampling and aggregation. You control n_estimators (number of models), max_samples (fraction or absolute count of training samples per model), and max_features (number of features to use). Setting oob_score=True computes a free validation score using the out-of-bag examples for each estimator.
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
bag = BaggingClassifier(
estimator=DecisionTreeClassifier(),
n_estimators=100,
oob_score=True,
random_state=42
)
bag.fit(X_train, y_train)
print('OOB score:', bag.oob_score_)
print('Test accuracy:', bag.score(X_test, y_test))Bagging for Regression
Bagging is not limited to classification. BaggingRegressor applies the same idea: train multiple regressors on bootstrap samples and average their numeric predictions. This is especially valuable when the base learner is a high-variance model like an unpruned decision tree. A single tree memorises noise; the average of many trees smooths it out, reducing the overall test RMSE significantly.
from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor
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)
single_tree = DecisionTreeRegressor(random_state=42)
bag_reg = BaggingRegressor(estimator=DecisionTreeRegressor(), n_estimators=100, random_state=42)
single_rmse = np.sqrt(-cross_val_score(single_tree, X, y, scoring='neg_mean_squared_error', cv=3).mean())
bag_rmse = np.sqrt(-cross_val_score(bag_reg, X, y, scoring='neg_mean_squared_error', cv=3).mean())
print(f'Single tree RMSE: {single_rmse:.4f}')
print(f'Bagged tree RMSE: {bag_rmse:.4f}')The Out-of-Bag Fraction
Since ~37% of training examples are excluded from each bootstrap sample, those examples can serve as a validation set for their respective estimator without any additional data split. The OOB score is computed by predicting each training point using only the estimators that did not see it during training. This gives a nearly unbiased estimate of generalisation performance, similar to leave-one-out cross-validation but far cheaper to compute.
Effect of n_estimators on Performance
Adding more estimators to a bagging ensemble almost always helps (or at worst does not hurt) test performance. Unlike neural network depth, there is no overfitting penalty for adding more trees — variance keeps decreasing while bias stays flat. In practice, performance plateaus after several hundred estimators. The main trade-off is compute time: doubling n_estimators doubles training time. Always check whether the marginal gain justifies the extra cost.
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
for n in [1, 10, 50, 200]:
bag = BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=n, random_state=42)
score = cross_val_score(bag, X, y, cv=5).mean()
print(f'n_estimators={n:4d}: CV accuracy={score:.4f}')Bagging vs a Single Complex Model
A single complex model (deep tree, high-degree polynomial) achieves low bias but high variance — it fits training data well but fluctuates wildly on unseen data. Bagging tames that variance by averaging across many such models. The combined prediction is much more stable. This is why bagging works best when the base learner is high variance and low bias. Applying bagging to a simple, already-underfitting model (like a linear regression) gives little benefit because the variance was already low.
Parallelism: Bagging Is Embarrassingly Parallel
Each estimator in a bagging ensemble is trained independently, with no data dependencies between them. This makes bagging embarrassingly parallel — all estimators can be trained simultaneously on multiple CPU cores. scikit-learn exposes this via the n_jobs=-1 parameter, which uses all available cores. This is in sharp contrast to boosting methods like XGBoost, where each model depends on the previous one and training is inherently sequential.
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
import time
X, y = load_breast_cancer(return_X_y=True)
bag_serial = BaggingClassifier(n_estimators=200, n_jobs=1, random_state=42)
bag_parallel = BaggingClassifier(n_estimators=200, n_jobs=-1, random_state=42)
start = time.time(); bag_serial.fit(X, y); print('Serial:', round(time.time()-start, 2), 's')
start = time.time(); bag_parallel.fit(X, y); print('Parallel:', round(time.time()-start, 2), 's')Limitations and When Bagging Fails
Bagging has important limitations. First, it increases compute and memory linearly with the number of estimators. Second, it offers no improvement in bias — if your base model is too simple, bagging many simple models still gives a simple ensemble. Third, bagging makes the model harder to interpret — you lose the single decision tree you could show a stakeholder. Finally, bagging alone does not decorrelate trees if all features are used at every split, which is where Random Forests add the extra trick of feature sub-sampling.
Quick Check
Test your understanding of Bootstrap Aggregation concepts from this lesson.
Lesson Recap
In this lesson you learned: bootstrap aggregation trains multiple models on random resamples with replacement, averaging predictions reduces variance without increasing bias, and the out-of-bag examples provide free validation for each estimator. Next up we explore the Random Forest trick of sub-sampling features to decorrelate trees further.
常见问题解答
「自助聚合(Bagging)详解」课时是免费的吗?
是的 — 「自助聚合(Bagging)详解」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Machine Learning Academy 课程的其余内容,请升级到 CoddyKit PRO。 Machine Learning Academy 课程共包含 4 节课。
「自助聚合(Bagging)详解」这节课中我会学到什么?
您将手动实现自助采样,在每个样本上训练分类器,并理解为什么对多样化模型取平均能够降低方差 你通过在浏览器中直接运行的动手代码来练习 Machine Learning Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Machine Learning Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Machine Learning Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「自助聚合(Bagging)详解」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Machine Learning Academy 课中编写并运行代码吗?
能。每节 Machine Learning Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 自助聚合(Bagging)详解
- 随机特征选择:随机森林技巧
- 袋外误差:森林内部的免费验证
- 投票集成:硬投票与软投票