Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.

Отдельный оценщик и бэггинг: разложение на смещение и дисперсию

В этом примере демонстрируется и сравнивается разложение ожидаемой среднеквадратичной ошибки отдельного оценщика и ансамбля бэггинга на смещение и дисперсию.

В задаче регрессии ожидаемую среднеквадратичную ошибку оценщика можно разложить на смещение, дисперсию и шум. Усреднённое по наборам данных задачи регрессии слагаемое смещения показывает, насколько в среднем предсказания оценщика отличаются от предсказаний наилучшего возможного оценщика для данной задачи (то есть байесовской модели). Слагаемое дисперсии характеризует изменчивость предсказаний оценщика при обучении на различных случайных экземплярах одной и той же задачи. Далее каждый экземпляр задачи обозначен как «LS» — «Learning Sample» (обучающая выборка). Наконец, шум отражает неустранимую часть ошибки, обусловленную изменчивостью данных.

На верхнем левом графике показаны предсказания (тёмно-красным) отдельного дерева решений, обученного на случайном наборе данных LS (синие точки) для простой одномерной задачи регрессии. Также показаны предсказания (светло-красным) других отдельных деревьев решений, обученных на других случайно выбранных экземплярах LS этой задачи. Интуитивно слагаемое дисперсии здесь соответствует ширине полосы предсказаний (светло-красным) отдельных оценщиков. Чем больше дисперсия, тем сильнее предсказания для x зависят от небольших изменений обучающей выборки. Слагаемое смещения соответствует разнице между средним предсказанием оценщика (голубым) и наилучшей возможной моделью (тёмно-синим). Таким образом, для этой задачи можно заметить, что смещение довольно мало (голубая и синяя кривые близки друг к другу), а дисперсия велика (красная полоса довольно широкая).

На нижнем левом графике показано поточечное разложение ожидаемой среднеквадратичной ошибки отдельного дерева решений. Он подтверждает, что слагаемое смещения (синим) мало, а дисперсия велика (зелёным). Также показана шумовая составляющая ошибки, которая, как и ожидалось, оказывается постоянной и составляет около 0.01.

На графиках справа показаны те же зависимости, но для ансамбля деревьев решений, использующего бэггинг. На обоих графиках видно, что слагаемое смещения больше, чем в предыдущем случае. На верхнем правом графике разница между средним предсказанием (голубым) и наилучшей возможной моделью больше (например, обратите внимание на смещение около x=2). На нижнем правом графике кривая смещения также немного выше, чем на нижнем левом. Однако с точки зрения дисперсии полоса предсказаний уже, что указывает на меньшую дисперсию. Действительно, как подтверждает нижний правый график, слагаемое дисперсии (зелёным) меньше, чем для отдельных деревьев решений. Таким образом, разложение на смещение и дисперсию в целом меняется. Компромисс для бэггинга оказывается лучше: усреднение нескольких деревьев решений, обученных на бутстрэп-копиях набора данных, немного увеличивает слагаемое смещения, но позволяет сильнее уменьшить дисперсию, что приводит к снижению общей среднеквадратичной ошибки (сравните красные кривые на нижних графиках). Результат работы скрипта также подтверждает это. Общая ошибка ансамбля бэггинга меньше общей ошибки отдельного дерева решений, и это различие действительно в основном обусловлено снижением дисперсии.

Подробнее о разложении на смещение и дисперсию см. в разделе 7.3 книги [1].

Ссылки

[1]

T. Hastie, R. Tibshirani and J. Friedman, «Элементы статистического обучения», Springer, 2009.

Tree, Bagging(Tree)
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.196 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_bias_variance.ipynb

Download Python source code: plot_bias_variance.py

Download zipped: plot_bias_variance.zip

Похожие примеры

Метод наименьших квадратов и регрессия Риджа

Сравнение калибровки классификаторов

Регрессия с помощью дерева решений

Объединение предикторов с помощью стекинга

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/ensemble/plot_bias_variance.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API