Примечание
Перейти к концу, чтобы загрузить полный пример кода. или запустить этот пример в браузере через JupyterLite или Binder
Сравнение одиночного оценщика и бэггинга: разложение смещения и дисперсии
Этот пример демонстрирует и сравнивает разложение смещения и дисперсии ожидаемой среднеквадратичной ошибки для одиночного оценщика по сравнению с ансамблем бэггинга.
В регрессии ожидаемая среднеквадратичная ошибка оценщика может быть разложена на составляющие смещения, дисперсии и шума. В среднем по наборам данных задачи регрессии, член смещения измеряет среднее отклонение предсказаний оценщика от предсказаний наилучшего возможного оценщика для задачи (т. е. модели Байеса). Член дисперсии измеряет изменчивость предсказаний оценщика при подгонке к различным случайным выборкам той же задачи. Каждая выборка задачи обозначена «LS» (от «Learning Sample») в дальнейшем. Наконец, шум измеряет неистребимую часть ошибки, обусловленную изменчивостью данных.
На верхней левой фигуре показаны предсказания (темно-красным цветом) одного дерева решений, обученного на случайном наборе данных LS (синие точки) задачи регрессии с 1-мерным входным признаком. Также показаны предсказания (светло-красным цветом) других деревьев решений, обученных на других (и различных) случайных выборках задачи LS. Интуитивно, член дисперсии здесь соответствует ширине луча предсказаний (светло-красным) отдельных оценщиков. Чем больше дисперсия, тем сильнее предсказания x реагируют на небольшие изменения в обучающей выборке. Член смещения соответствует разнице между средним предсказанием оценщика (голубовато-циан) и лучшей возможной моделью (тёмно-синяя). В этой задаче мы можем наблюдать, что смещение довольно низкое (и синяя, и голубовато-циан кривые близки друг к другу), а дисперсия большая (красный луч довольно широкий).
На нижней левой фигуре показано точечное разложение ожидаемой среднеквадратичной ошибки одного дерева решений. Оно подтверждает, что член смещения (синий) невелик, а дисперсия (зелёный) большая. Также показана шумовая часть ошибки, которая, как ожидалось, постоянна и находится около 0.01.
Правые фигуры соответствуют тем же графикам, но с использованием вместо этого ансамбля деревьев решений бэггинга. На обеих фигурах можно наблюдать, что член смещения больше, чем в предыдущем случае. На верхней правой фигуре разница между средним предсказанием (голубовато-циан) и лучшей возможной моделью больше (например, обратите внимание на смещение около x=2). На нижней правой фигуре кривая смещения также немного выше, чем на нижней левой фигуре. Однако в плане дисперсии луч предсказаний уже, что предполагает более низкую дисперсию. Действительно, как подтверждает нижняя правая фигура, член дисперсии (зелёный) ниже, чем у одиночного дерева решений. Таким образом, разложение смещения и дисперсии больше не является таким же. Компромисс лучше для бэггинга: усреднение нескольких деревьев решений, обученных на бутстрап-копиях набора данных, незначительно увеличивает член смещения, но позволяет больше уменьшить дисперсию, что приводит к более низкой общей среднеквадратичной ошибке (сравните красные кривые на нижних фигурах). Выход скрипта также подтверждает эту интуицию. Общая ошибка ансамбля бэггинга ниже, чем общая ошибка одного дерева решений, и эта разница действительно в основном обусловлена уменьшенной дисперсией.
Для более подробной информации о разложении смещения и дисперсии см. раздел 7.3 [1].
Ссылки

Tree: 0.0255 (error) = 0.0003 (bias^2) + 0.0152 (var) + 0.0098 (noise) Bagging(Tree): 0.0196 (error) = 0.0004 (bias^2) + 0.0092 (var) + 0.0098 (noise)
# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause
import matplotlib.pyplot as plt
import numpy as np
from sklearn.ensemble import BaggingRegressor
from sklearn.tree import DecisionTreeRegressor
# Settings
n_repeat = 50 # Number of iterations for computing expectations
n_train = 50 # Size of the training set
n_test = 1000 # Size of the test set
noise = 0.1 # Standard deviation of the noise
np.random.seed(0)
# Change this for exploring the bias-variance decomposition of other
# estimators. This should work well for estimators with high variance (e.g.,
# decision trees or KNN), but poorly for estimators with low variance (e.g.,
# linear models).
estimators = [
("Tree", DecisionTreeRegressor()),
("Bagging(Tree)", BaggingRegressor(DecisionTreeRegressor())),
]
n_estimators = len(estimators)
# Generate data
def f(x):
x = x.ravel()
return np.exp(-(x**2)) + 1.5 * np.exp(-((x - 2) ** 2))
def generate(n_samples, noise, n_repeat=1):
X = np.random.rand(n_samples) * 10 - 5
X = np.sort(X)
if n_repeat == 1:
y = f(X) + np.random.normal(0.0, noise, n_samples)
else:
y = np.zeros((n_samples, n_repeat))
for i in range(n_repeat):
y[:, i] = f(X) + np.random.normal(0.0, noise, n_samples)
X = X.reshape((n_samples, 1))
return X, y
X_train = []
y_train = []
for i in range(n_repeat):
X, y = generate(n_samples=n_train, noise=noise)
X_train.append(X)
y_train.append(y)
X_test, y_test = generate(n_samples=n_test, noise=noise, n_repeat=n_repeat)
plt.figure(figsize=(10, 8))
# Loop over estimators to compare
for n, (name, estimator) in enumerate(estimators):
# Compute predictions
y_predict = np.zeros((n_test, n_repeat))
for i in range(n_repeat):
estimator.fit(X_train[i], y_train[i])
y_predict[:, i] = estimator.predict(X_test)
# Bias^2 + Variance + Noise decomposition of the mean squared error
y_error = np.zeros(n_test)
for i in range(n_repeat):
for j in range(n_repeat):
y_error += (y_test[:, j] - y_predict[:, i]) ** 2
y_error /= n_repeat * n_repeat
y_noise = np.var(y_test, axis=1)
y_bias = (f(X_test) - np.mean(y_predict, axis=1)) ** 2
y_var = np.var(y_predict, axis=1)
print(
"{0}: {1:.4f} (error) = {2:.4f} (bias^2) "
" + {3:.4f} (var) + {4:.4f} (noise)".format(
name, np.mean(y_error), np.mean(y_bias), np.mean(y_var), np.mean(y_noise)
)
)
# Plot figures
plt.subplot(2, n_estimators, n + 1)
plt.plot(X_test, f(X_test), "b", label="$f(x)$")
plt.plot(X_train[0], y_train[0], ".b", label="LS ~ $y = f(x)+noise$")
for i in range(n_repeat):
if i == 0:
plt.plot(X_test, y_predict[:, i], "r", label=r"$\^y(x)$")
else:
plt.plot(X_test, y_predict[:, i], "r", alpha=0.05)
plt.plot(X_test, np.mean(y_predict, axis=1), "c", label=r"$\mathbb{E}_{LS} \^y(x)$")
plt.xlim([-5, 5])
plt.title(name)
if n == n_estimators - 1:
plt.legend(loc=(1.1, 0.5))
plt.subplot(2, n_estimators, n_estimators + n + 1)
plt.plot(X_test, y_error, "r", label="$error(x)$")
plt.plot(X_test, y_bias, "b", label="$bias^2(x)$"),
plt.plot(X_test, y_var, "g", label="$variance(x)$"),
plt.plot(X_test, y_noise, "c", label="$noise(x)$")
plt.xlim([-5, 5])
plt.ylim([0, 0.1])
if n == n_estimators - 1:
plt.legend(loc=(1.1, 0.5))
plt.subplots_adjust(right=0.75)
plt.show()
Общее время выполнения скрипта: (0 минут 1,256 секунды)
Связанные примеры
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/ensemble/plot_bias_variance.html