Машинное обучение — это область исследований, которая занимается разработкой алгоритмов, которые могут учиться на данных и делать прогнозы или решения без явного программирования. Одной из ключевых задач машинного обучения является поиск компромисса между предвзятостью и дисперсией. В этой статье мы рассмотрим, что такое предвзятость и дисперсия, почему они важны и как с ними бороться.

Что такое смещение и дисперсия?

Предвзятость в машинном обучении относится к тенденции модели постоянно делать неверные прогнозы или решения из-за чрезмерного упрощения базовой взаимосвязи между входными функциями и выходной переменной. В терминах машинного обучения смещение – это ошибка прогнозирования входных данных обучения (ошибка обучения).

Вариантность в машинном обучении относится к тенденции модели делать противоречивые прогнозы или решения из-за того, что она слишком чувствительна к небольшим колебаниям обучающих данных. В терминах машинного обучения смещение – это ошибка прогнозирования входных данных тестирования (ошибка тестирования).

Каково значение смещения и дисперсии?

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

Модель машинного обучения с высоким смещением (что означает высокую ошибку обучения) и низкой дисперсией (что означает низкую ошибку тестирования) называется неподходящей моделью. Это означает, что модель не смогла хорошо уловить взаимосвязь между входными данными обучения и результатами обучения. Отсюда и высокая ошибка обучения. И поскольку эта модель имеет тенденцию быть обобщенной/упрощенной, она имеет меньшую ошибку тестирования. Эти модели имеют низкую сложность.

Модель машинного обучения с низким смещением (что означает низкую ошибку обучения) и высокой дисперсией (что означает высокую ошибку тестирования) называется моделью переобучения. Это означает, что модель слишком хорошо уловила взаимосвязь между входными данными обучения и результатами обучения. Отсюда и низкая ошибка обучения. Но это идеальное соответствие данным обучения делает эту модель очень неточной при столкновении с данными тестирования. Следовательно, более высокая ошибка тестирования. Эти модели, как правило, отличаются высокой сложностью.

На рисунке ниже показана связь между смещением, дисперсией и сложностью модели. В идеале нам нужна модель с низким смещением, низкой дисперсией и умеренной сложностью.

Понимание смещения и дисперсии на простом примере

Чтобы лучше понять эту концепцию, давайте поработаем с образцом набора данных и проверим смещение и дисперсию для разных моделей. Я буду прикреплять фрагменты кода и выводить сюда. Если вы хотите получить доступ ко всему коду, вы можете найти его в моем репозитории GitHub здесь.

  1. Создание образца набора данных
import numpy as np

# create a sample dataset
X = np.array(range(1,30)).reshape(-1, 1)
y = np.array([2,5,8,6,16,20,21,22,23,24,35,36,38,40,43,20,22,25,26,27,40,41,42,45,36,35,34,33,33])
plt.scatter(X,y)

2. Разделение набора данных с помощью sklearn train_test_split()

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.4,shuffle=True, random_state=20)

plt.scatter(X_train,y_train,c="red",label="Train")
plt.scatter(X_test,y_test,c="green", label="Test")
plt.legend()

3. Подгонка обучающих данных к простой модели недостаточного соответствия (линейная регрессия)

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train, y_train)

plt.scatter(X_train, y_train, c="red", label="Train")
plt.scatter(X_test, y_test, c="green", label="Test")
plt.plot(X_train, lr.predict(X_train), label="Linear regression plot")
plt.legend()

4. Подгонка обучающих данных к сложной модели наложения (полиномиальная регрессия с 11 коэффициентами)

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

# Fit a polynomial regression model
poly_reg = make_pipeline(PolynomialFeatures(11), LinearRegression())
poly_reg.fit(X_train, y_train)
# Plot the model predictions
plt.scatter(X_train, y_train, c="red", label="Train")
plt.scatter(X_test, y_test, c="green", label="Test")
plt.plot(np.sort(X_train.reshape(1,-1)).reshape(-1,1),
         poly_reg.predict(np.sort(X_train.reshape(1,-1)).reshape(-1,1)),
         label="Poly Regression plot")
plt.legend()
plt.show()

5. Проверка смещения и дисперсии для двух моделей

from sklearn.metrics import mean_squared_error

print("Linear Regression")
print(f"Training error (Bias): {mean_squared_error(y_train,lr.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,lr.predict(X_test))}")
print("------------------------------------------------------------------------")
print("Polynomial Regression")
print(f"Training error (Bias): {mean_squared_error(y_train,poly_reg.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,poly_reg.predict(X_test))}")
print("------------------------------------------------------------------------")

Как видно из приведенного выше вывода, простая модель недостаточного соответствия дает нам высокое смещение и низкую дисперсию. Высокое смещение указывает на то, что модель не уловила лежащую в основе взаимосвязь между X и y. Низкая дисперсия указывает на то, что он может делать достойные прогнозы для тестовых данных. Это связано с тем, что модель очень обобщена.

С другой стороны, сложная модель переобучения дает нам низкое смещение и высокую дисперсию. Низкое смещение указывает на то, что модель хорошо уловила основную взаимосвязь между X и y. Высокая дисперсия указывает на то, что модель очень плохо делает точные прогнозы для тестовых данных. Наша модель настолько хорошо соответствует обучающим данным, что не может делать точные прогнозы для любых других данных.

Как найти баланс между смещением и дисперсией?

К настоящему времени вы должны были понять, что в идеале нам нужна модель с низким смещением и низкой дисперсией. Но как найти это оптимальное решение? Вот несколько способов сделать это:

  1. Перекрестная проверка. Один из способов оценить погрешность и дисперсию модели – использовать перекрестную проверку. Перекрестная проверка включает в себя разделение данных на несколько подмножеств, обучение модели на каждом подмножестве и тестирование модели на оставшихся данных. Этот метод может помочь вам понять, насколько хорошо модель обобщает новые данные, и определить компромисс между смещением и дисперсией.
  2. Регуляризация. Регуляризация — это метод, используемый для предотвращения переобучения, которое возникает, когда модель слишком сложна и слишком хорошо соответствует обучающим данным. Регуляризация добавляет штрафной член к целевой функции, побуждая модель иметь меньшие веса. Это может уменьшить дисперсию модели и повысить эффективность ее обобщения.
  3. Методы ансамбля. Методы ансамбля объединяют несколько моделей, чтобы уменьшить дисперсию общей модели. Двумя популярными ансамблевыми методами являются бэггинг и бустинг. Бэггинг включает в себя обучение нескольких моделей на разных подмножествах данных и усреднение их прогнозов. Повышение включает в себя последовательное обучение моделей, при этом каждая модель фокусируется на примерах, с которыми боролась предыдущая модель.
  4. Выбор функций. Еще один способ уменьшить сложность модели — выбрать подмножество функций, наиболее релевантных задаче. Выбор признаков может уменьшить дисперсию модели и улучшить ее эффективность обобщения.
  5. Увеличение данных: увеличение данных – это метод, используемый для увеличения размера обучающей выборки путем создания новых примеров из существующих. Увеличение данных может уменьшить предвзятость модели, предоставляя модели более разнообразные примеры, на которых она может учиться.

Решение, которое вы выберете, будет зависеть от различных факторов, таких как тип имеющихся у вас данных, тип модели, которую вы хотите построить, и тип проблемы, которую вы хотите решить. Следовательно, разные методы работают для разных приложений, и вам придется поэкспериментировать с несколькими методами, чтобы найти лучший для вас.

Поиск оптимальной модели для нашего примера

  1. Уменьшение количества коэффициентов в полиномиальной регрессии

Если вы посмотрите на график данных, которые мы использовали в приведенном выше примере, вы заметите, что мы можем получить лучшую модель, подгоняя данные к кривой вместо подгонки данных к линии. Хотя мы не хотим использовать большое количество коэффициентов для нашей кривой, потому что тогда это приводит к модели переобучения. Итак, в приведенном ниже фрагменте кода мы пытаемся уменьшить количество коэффициентов в полиномиальной регрессии с 11 до 4. (Обратите внимание, что в нашем примере я выбрал количество коэффициентов произвольно, но вы можете использовать поиск по сетке с Перекрестная проверка для поиска оптимального количества коэффициентов)

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

# Fit a polynomial regression model
upd_poly_reg = make_pipeline(PolynomialFeatures(4), LinearRegression())
upd_poly_reg.fit(X_train, y_train)
# Plot the model predictions
plt.scatter(X_train, y_train, c="red", label="Train")
plt.scatter(X_test, y_test, c="green", label="Test")
plt.plot(np.sort(X_train.reshape(1,-1)).reshape(-1,1),
         upd_poly_reg.predict(np.sort(X_train.reshape(1,-1)).reshape(-1,1)),
         label="Poly reg plot")
plt.legend()
plt.show()

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

from sklearn.metrics import mean_squared_error

print("Linear Regression (simple underfit model)")
print(f"Training error (Bias): {mean_squared_error(y_train,lr.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,lr.predict(X_test))}")
print("------------------------------------------------------------------------")
print("Polynomial Regression (complex overfit model)")
print(f"Training error (Bias): {mean_squared_error(y_train,poly_reg.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,poly_reg.predict(X_test))}")
print("------------------------------------------------------------------------")
print("Updated Polynomial Regression (optimal model)")
print(f"Training error (Bias): {mean_squared_error(y_train,upd_poly_reg.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,upd_poly_reg.predict(X_test))}")
print("------------------------------------------------------------------------")

2. Использование ансамблевой модели (RandomForestRegressor)

Опять же, если вы посмотрите на точечную диаграмму данных, которые мы использовали в нашем примере, вы заметите, что точки данных могут быть разделены на разные группы. Следовательно, метод ансамбля может пригодиться для создания оптимальной модели.

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

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import GridSearchCV
# Create a random forest regressor
rf = RandomForestRegressor(random_state=42)
# Define the parameter grid to search over
param_grid = {'n_estimators': [50, 100, 150],
              'max_depth': [2, 4, 6, 8, None],
              'min_samples_split': [2, 5, 10],
              'min_samples_leaf': [1, 2, 4]}
# Create the GridSearchCV object
grid_search = GridSearchCV(estimator=rf, param_grid=param_grid, cv=5)
# Fit the GridSearchCV object to the training data
grid_search.fit(X_train, y_train)
from sklearn.metrics import mean_squared_error

print("Linear Regression (simple underfit model)")
print(f"Training error (Bias): {mean_squared_error(y_train,lr.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,lr.predict(X_test))}")
print("------------------------------------------------------------------------")
print("Polynomial Regression (complex overfit model)")
print(f"Training error (Bias): {mean_squared_error(y_train,poly_reg.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,poly_reg.predict(X_test))}")
print("------------------------------------------------------------------------")
print("Random Forest Regression (optimal model)")
print(f"Training Error (Bias): {mean_squared_error(y_train,grid_search.best_estimator_.predict(X_train))}")
print(f"Testing error (Variance): {mean_squared_error(y_test,grid_search.best_estimator_.predict(X_test))}")

Как вы можете видеть из выходного фрагмента выше, модель регрессии случайного леса дает гораздо меньшее смещение, чем простая модель, и гораздо меньшую дисперсию, чем сложная модель, что делает ее оптимальной моделью для нашего набора данных.

Заключение

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