Когда студент впервые обучает модель, он почти всегда радуется одному и тому же моменту: ошибка на обучающей выборке падает, график становится красивым, предсказания выглядят убедительно. И именно здесь в машинном обучении спрятана одна из самых неприятных ловушек.
Модель может отлично выглядеть на тех данных, которые она уже видела, и одновременно быть плохой моделью.
Это звучит парадоксально только до тех пор, пока человек не понял идею overfitting. После этого почти вся тема качества модели начинает складываться в одну логичную систему: почему мы делим данные на train и test, зачем нужна валидация, почему слишком сложная модель опасна, почему регуляризация вообще имеет смысл и почему низкая ошибка на обучении ещё ничего не гарантирует.
Если говорить совсем по-человечески, overfitting — это ситуация, когда модель перестаёт учиться закономерности и начинает учиться подробностям конкретной выборки. Иногда это шум, иногда случайные колебания, иногда редкие особенности датасета, которые на новых данных не повторятся.
Почему одна и та же модель может быть и хорошей, и плохой одновременно
Представьте студента, который готовится к экзамену двумя способами.
- Первый понимает тему, умеет решать незнакомые задачи и переносить идею на новые примеры.
- Второй выучил ответы на конкретные двадцать вопросов, но ломается, если формулировку чуть поменяли.
С моделью происходит то же самое.
Если она уловила структуру данных, она будет работать и на новых объектах. Если она запомнила конкретную выборку, то при столкновении с новыми наблюдениями начнёт ошибаться.
Именно это и есть overfitting: не просто “слишком сложная модель”, а разрыв между качеством на знакомых и незнакомых данных.
Где overfitting появляется математически
В машинном обучении модель почти всегда обучается через минимизацию функции ошибки. Для задач регрессии базовым примером обычно служит среднеквадратичная ошибка.
Раздел математики: математическая статистика
Среднеквадратичная ошибка:
$$ MSE(\theta) = \frac{1}{n}\sum_{i=1}^{n}\left(y_i - \hat{y}_i\right)^2 $$Обозначения:
- \(MSE(\theta)\) — значение функции ошибки при параметрах модели \(\theta\);
- \(n\) — количество объектов в выборке, по которым считается ошибка;
- \(y_i\) — истинное значение целевой переменной для \(i\)-го объекта;
- \(\hat{y}_i\) — предсказание модели для \(i\)-го объекта;
- \(\theta\) — совокупность параметров модели, например веса и смещения;
- \(\left(y_i - \hat{y}_i\right)^2\) — квадрат ошибки на одном объекте.
Эта формула используется в регрессии, когда мы хотим измерить, насколько далеко предсказания модели находятся от реальных значений. Квадрат ошибки нужен затем, чтобы большие промахи штрафовались сильнее и не компенсировались ошибками противоположного знака.
Проблема не в самой функции \(MSE\). Проблема в том, что мы можем уменьшать её на обучающих данных настолько усердно, что модель начнёт подстраиваться не только под реальный сигнал, но и под шум.
То есть математически overfitting начинается в тот момент, когда минимизация ошибки на train перестаёт улучшать способность модели обобщать.
Почему ошибка на обучении не равна качеству модели
Это один из самых важных переходов в мышлении Data Scientist. Новичок обычно думает так: если модель минимизировала ошибку, значит она хорошая. Но опытный человек уточняет: на каких данных?
Потому что есть как минимум две ошибки:
- ошибка на обучающей выборке;
- ошибка на новых данных.
Раздел математики: математическая статистика
Ошибка на обучении и валидации:
$$ E_{\mathrm{train}} = \frac{1}{n_{\mathrm{train}}}\sum_{i=1}^{n_{\mathrm{train}}}\left(y_i - \hat{y}_i\right)^2, \qquad E_{\mathrm{valid}} = \frac{1}{n_{\mathrm{valid}}}\sum_{i=1}^{n_{\mathrm{valid}}}\left(y_i - \hat{y}_i\right)^2 $$Обозначения:
- \(E_{\mathrm{train}}\) — ошибка модели на обучающей выборке;
- \(E_{\mathrm{valid}}\) — ошибка модели на валидационной выборке;
- \(n_{\mathrm{train}}\) — количество объектов в обучающей выборке;
- \(n_{\mathrm{valid}}\) — количество объектов в валидационной выборке;
- \(y_i\) — истинные значения целевой переменной;
- \(\hat{y}_i\) — предсказания модели.
Эти две величины нужны затем, чтобы отделить способность модели запоминать обучающие данные от способности работать на новых. Именно разница между ними и даёт один из самых понятных признаков переобучения.
Если \(E_{\mathrm{train}}\) очень маленькая, а \(E_{\mathrm{valid}}\) заметно выше, это тревожный сигнал. Модель как будто говорит: “то, что я уже видела, я знаю прекрасно; а вот с новым миром у меня проблемы”.
Геометрическая интерпретация
Overfitting проще всего почувствовать геометрически. Представьте набор точек на плоскости. Вы хотите построить функцию, которая описывает общую тенденцию.
Есть три сценария:
- модель слишком простая и не умеет уловить даже основную форму зависимости;
- модель достаточно гибкая, чтобы уловить закономерность;
- модель настолько гибкая, что начинает изгибаться под каждую случайную точку.
Последний случай и есть переобучение.
Раздел математики: математический анализ и линейная алгебра
Полиномиальная модель:
$$ \hat{y} = w_0 + w_1x + w_2x^2 + \dots + w_kx^k $$Обозначения:
- \(\hat{y}\) — предсказание модели;
- \(x\) — входной признак;
- \(w_0, w_1, \dots, w_k\) — параметры модели;
- \(k\) — степень полинома, определяющая сложность модели.
Эта формула используется в полиномиальной регрессии. Чем выше степень \(k\), тем более гибкой становится модель. Это полезно, если зависимость действительно сложная, но опасно, если модель начинает подстраиваться под шум в обучающих данных.
Когда степень \(k\) слишком велика, кривая становится настолько подвижной, что проходит почти через каждую точку. На train это выглядит как успех. На новых данных — как катастрофа.
Геометрически модель перестаёт описывать поверхность тенденции и начинает повторять случайную рябь.
Как overfitting связан с оптимизацией
Очень важно понять: overfitting не противоречит оптимизации. Он часто возникает именно потому, что оптимизация работает слишком хорошо на обучающей выборке.
Например, если модель обучается через градиентный спуск, она шаг за шагом уменьшает ошибку. Это полезно, но только до тех пор, пока уменьшение train-ошибки действительно ведёт к улучшению обобщающей способности.
Раздел математики: математический анализ и оптимизация
Шаг градиентного спуска:
$$ \theta_{t+1} = \theta_t - \eta \nabla J\left(\theta_t\right) $$Обозначения:
- \(\theta_t\) — параметры модели на шаге обучения \(t\);
- \(\theta_{t+1}\) — параметры после обновления;
- \(\eta\) — скорость обучения, задающая длину шага;
- \(\nabla J\left(\theta_t\right)\) — градиент функции потерь в текущей точке;
- \(J\left(\theta_t\right)\) — значение функции потерь при текущих параметрах.
Эта формула используется во множестве моделей машинного обучения — от линейной регрессии до нейронных сетей. Она нужна затем, чтобы постепенно сдвигать параметры модели в сторону уменьшения ошибки.
Интуитивно это выглядит так: оптимизатор честно спускается вниз по поверхности ошибки. Но поверхность train-ошибки и поверхность реальной способности к обобщению — не одно и то же. Поэтому можно дойти до очень хорошего минимума на train и одновременно попасть в плохую зону по качеству на unseen data.
Отсюда появляется одна из самых зрелых мыслей в ML: обучение модели — это не просто минимизация функции потерь, а поиск баланса между подгонкой и обобщением.
Почему сложные модели переобучаются легче
Чем больше у модели свободы, тем больше способов подстроиться под данные. Это похоже на ситуацию с гибкой проволокой и жёсткой линейкой. Линейка не может повторить мелкие колебания. Проволока может. Но если задача — уловить общий контур, то избыточная гибкость становится проблемой.
В Data Science это означает простую вещь:
- модель с высокой сложностью может захватывать тонкие зависимости;
- но та же самая сложность позволяет ей запоминать шум.
Поэтому overfitting особенно часто возникает, когда:
- модель слишком мощная для объёма данных;
- данных мало;
- в признаках много шума;
- модель обучают слишком долго;
- нет регуляризации или контроля качества на валидации.
Зачем в машинном обучении делят данные на train, validation и test
Теперь становится понятно, что разделение выборки — это не бюрократия, а защита от самообмана.
Если оценивать модель только по обучающей выборке, она почти всегда будет казаться лучше, чем есть на самом деле. Поэтому нужны разные роли данных:
- train — чтобы подбирать параметры модели;
- validation — чтобы следить, не начала ли модель переобучаться;
- test — чтобы честно проверить финальное качество.
Без этой структуры Data Science очень быстро превращается в красивое рисование метрик, которые не имеют отношения к реальной работе модели.
Почему регуляризация — это разговор именно про overfitting
Когда модель слишком легко подстраивается под train, ей часто нужно искусственно ограничить свободу. Для этого и вводится регуляризация.
Раздел математики: оптимизация и математическая статистика
Регуляризованная функция потерь:
$$ J(\theta) = \frac{1}{n}\sum_{i=1}^{n}\left(y_i - \hat{y}_i\right)^2 + \lambda \|\theta\|_2^2 $$Обозначения:
- \(J(\theta)\) — итоговая функция потерь модели с регуляризацией;
- \(n\) — количество объектов в обучающей выборке;
- \(y_i\) — истинное значение для \(i\)-го объекта;
- \(\hat{y}_i\) — предсказание модели;
- \(\theta\) — параметры модели;
- \(\|\theta\|_2^2\) — сумма квадратов параметров, штрафующая слишком большие веса;
- \(\lambda\) — коэффициент регуляризации, управляющий силой штрафа.
Эта формула используется, когда нужно не просто минимизировать ошибку на обучении, а одновременно удерживать модель от избыточной сложности. Чем больше \(\lambda\), тем сильнее модель штрафуется за большие коэффициенты.
Интуитивно регуляризация говорит модели: “не будь слишком агрессивной, не пытайся объяснить всё до последней мелочи”. Это не про запрет на хорошее качество. Это про запрет на слишком нервное поведение по отношению к случайностям в данных.
Как overfitting выглядит в Python на практике
Ниже простой пример, где полиномиальная регрессия слишком высокой степени начинает подстраиваться под шум. Это хороший учебный сценарий, потому что на нём overfitting виден почти физически.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
np.random.seed(42)
X = np.linspace(0, 1, 40)
y = np.sin(2 * np.pi * X) + np.random.normal(0, 0.2, size=40)
X = X.reshape(-1, 1)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
model_small = make_pipeline(
PolynomialFeatures(degree=3),
LinearRegression()
)
model_big = make_pipeline(
PolynomialFeatures(degree=15),
LinearRegression()
)
model_small.fit(X_train, y_train)
model_big.fit(X_train, y_train)
pred_train_small = model_small.predict(X_train)
pred_test_small = model_small.predict(X_test)
pred_train_big = model_big.predict(X_train)
pred_test_big = model_big.predict(X_test)
print("Small model train MSE:", mean_squared_error(y_train, pred_train_small))
print("Small model test MSE:", mean_squared_error(y_test, pred_test_small))
print("Big model train MSE:", mean_squared_error(y_train, pred_train_big))
print("Big model test MSE:", mean_squared_error(y_test, pred_test_big))
X_plot = np.linspace(0, 1, 300).reshape(-1, 1)
plt.scatter(X_train, y_train, label="train")
plt.scatter(X_test, y_test, label="test")
plt.plot(X_plot, model_small.predict(X_plot), label="degree=3")
plt.plot(X_plot, model_big.predict(X_plot), label="degree=15")
plt.legend()
plt.show()Что здесь происходит:
- модель с маленькой степенью обычно улавливает общий тренд;
- модель с большой степенью часто сильно снижает train-ошибку;
- но её ошибка на test может оказаться заметно выше.
Это и есть рабочая картина overfitting в коде: не определение из словаря, а конкретный разрыв между “знаю старое” и “умею обобщать”.
Почему без overfitting невозможно понять качество модели
Потому что качество модели в Data Science — это не просто маленькая ошибка. Качество — это способность модели оставаться полезной за пределами обучающей выборки.
Если человек не понимает overfitting, он почти наверняка будет делать одну из двух ошибок:
- либо слепо радоваться маленькой train-ошибке;
- либо бесконечно усложнять модель, думая, что так качество всегда улучшается.
Но как только идея overfitting становится ясной, меняется весь взгляд на машинное обучение:
- валидация перестаёт быть формальностью;
- регуляризация перестаёт быть странной добавкой к функции потерь;
- простая модель иногда начинает казаться умнее сложной;
- метрика на test превращается в честный разговор с реальностью.
Именно поэтому overfitting — это не “одна из тем”. Это центральная мысль, без которой качество модели невозможно понять по-настоящему.
Главная идея, которую стоит унести
Модель в Data Science должна не помнить данные, а понимать их структуру.
Overfitting начинается в тот момент, когда память подменяет понимание. С математической стороны это выглядит как слишком сильная подгонка train-ошибки. С геометрической — как кривая, которая начинает повторять шум. С точки зрения оптимизации — как ситуация, где дальнейшее улучшение обучающей функции потерь перестаёт означать рост качества на новых данных.
Поэтому, когда вы в следующий раз увидите красивую метрику на обучении, полезно задать себе один зрелый вопрос: а умеет ли моя модель жить вне собственного датасета?
Вот именно с этого вопроса и начинается настоящее понимание качества модели в Data Science.