Главная
#Математика и ML #Data Science #Overfitting

Что такое overfitting в Data Science?

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

Содержание
  1. Почти каждый новичок в машинном обучении хотя бы раз переживает один и тот же обманчивый момент
  2. Почему переобучение возникает не из-за одной ошибки, а из-за перекоса между гибкостью модели и объемом сигнала в данных
  3. Почему регуляризация так часто появляется в разговоре об overfitting
  4. Как распознать переобучение в реальной задаче, а не в учебной формулировке
  5. Какие шаги реально снижают риск переобучения
  6. Ниже маленький Python-пример, который показывает типичную логику борьбы с overfitting
  7. Overfitting — это не частная техническая неприятность, а центральный критерий зрелости модели

Почти каждый новичок в машинном обучении хотя бы раз переживает один и тот же обманчивый момент

В этом и состоит главный интеллектуальный поворот. В машинном обучении недостаточно добиться низкой ошибки на тех данных, которые уже лежат перед нами. Цель состоит не в том, чтобы идеально пересказать прошлое, а в том, чтобы устойчиво работать на новых наблюдениях. Если держать в голове именно эту цель, overfitting перестает быть пугающим словом и превращается в понятную инженерную и математическую проблему. Рядом с этой темой почти всегда стоит читать и про L1-регуляризацию, потому что именно она даёт один из самых наглядных способов ограничивать избыточную гибкость модели.

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

Почему переобучение возникает не из-за одной ошибки, а из-за перекоса между гибкостью модели и объемом сигнала в данных

Когда мы обучаем модель, она пытается согласовать параметры с наблюдениями. Если модель слишком простая, ей может не хватить выразительности, чтобы уловить зависимость. Тогда возникает underfitting: и train, и test работают плохо. Но если модель слишком гибкая, она начинает подстраиваться не только под закономерность, но и под шум, редкие случайности, выбросы, особенности именно этой выборки. Тогда и появляется overfitting.

Здесь важно заметить тонкую вещь. Переобучение не означает, что модель «слишком умная». Наоборот, оно часто означает, что модель не умеет отличать устойчивый сигнал от случайных колебаний. Она слишком охотно верит каждому наблюдению и слишком старательно пытается объяснить даже то, что объяснять не нужно. Поэтому борьба с overfitting не сводится к запрету сложных алгоритмов. Это вопрос баланса: сколько свободы мы дали модели, сколько данных у нас есть, насколько шумна задача и насколько честно мы измеряем качество.

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

Формула: раздел математики — математическая статистика и теория машинного обучения
(\mathcal{L}_{\mathrm{train}} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2)
Что означает эта формула

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

Численный пример: пусть (y = (10, 14, 18)), а (\hat{y} = (11, 13, 18)). Тогда ошибки равны ((10 - 11, 14 - 13, 18 - 18) = (-1, 1, 0)), квадраты ошибок равны (((-1)^2, 1^2, 0^2) = (1, 1, 0)), а итоговая ошибка равна (\mathcal{L}_{\mathrm{train}} = \frac{1 + 1 + 0}{3} = \frac{2}{3}).

Что означает каждый символ
  • (\mathcal{L}_{\mathrm{train}}) — значение функции потерь на обучающей выборке
  • (n) — число объектов в train-выборке
  • (y_i) — реальное значение целевой переменной для объекта (i)
  • (\hat{y}_i) — предсказание модели для того же объекта
  • (\sum) — суммирование по всем объектам выборки

Именно здесь возникает важная связь с машинным обучением. Алгоритм оптимизации минимизирует некоторую функцию потерь. Но реальная цель Data Science шире: получить модель, которая сохранит качество вне обучающего набора. Поэтому недостаточно следить только за train-loss. Нужна отдельная проверка на validation или test, иначе модель может выучить частный шум и остаться формально «успешной» только на знакомых данных. Когда хочется понять, почему одного split часто недостаточно, рядом особенно полезно читать и про кросс-валидацию, потому что именно она делает разговор о переобучении прикладным, а не декларативным.

Почему регуляризация так часто появляется в разговоре об overfitting

Если переобучение связано с избыточной гибкостью модели, естественно возникает вопрос: можно ли математически наказать модель за чрезмерно сложное поведение? Именно так и появляется регуляризация. Она добавляет к основной функции потерь дополнительный штраф, который ограничивает свободу параметров. Идея очень практичная: мы говорим модели, что точность на train важна, но бесконтрольный рост коэффициентов тоже имеет цену.

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

Формула: раздел математики — оптимизация и линейная алгебра
(\mathcal{L}_{\mathrm{reg}} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 + \lambda \sum_{j=1}^{p} w_j^2)
Что означает эта формула

Это функция потерь с L2-регуляризацией. Первая часть измеряет ошибку модели на данных, а вторая штрафует большие значения коэффициентов. В линейных моделях и не только такая конструкция помогает снизить риск переобучения, потому что модель теряет стимул чрезмерно раздувать веса ради идеальной подгонки под train.

Численный пример: пусть средняя квадратичная ошибка на train равна (0.8), коэффициенты модели равны (w_1 = 2, w_2 = -1, w_3 = 3), а параметр регуляризации равен (\lambda = 0.1). Тогда штраф равен (\lambda (w_1^2 + w_2^2 + w_3^2) = 0.1 \cdot (4 + 1 + 9) = 1.4), а итоговая функция потерь равна (\mathcal{L}_{\mathrm{reg}} = 0.8 + 1.4 = 2.2).

Что означает каждый символ
  • (\mathcal{L}_{\mathrm{reg}}) — функция потерь с регуляризацией
  • (\lambda) — коэффициент силы штрафа за сложность модели
  • (w_j) — вес (j)-го признака
  • (p) — число признаков в модели
  • (\sum_{j=1}^{p} w_j^2) — сумма квадратов коэффициентов, задающая штраф за их величину

Геометрический смысл регуляризации особенно красив. Если обычная подгонка стремится просто найти минимум ошибки, то регуляризация сужает пространство допустимых решений. Она буквально меняет форму поверхности оптимизации. Поэтому связь с overfitting здесь не декоративная, а вычислительная: мы перестраиваем саму задачу обучения так, чтобы модель меньше стремилась к чрезмерной сложности. Если хочется отдельно разобрать именно этот механизм штрафа, логично перейти и к материалу про L2-регуляризацию, где акцент уже сделан не на симптоме, а на самом инструменте контроля гибкости.

Как распознать переобучение в реальной задаче, а не в учебной формулировке

На практике overfitting редко выглядит как драматическое событие. Чаще это тихий разрыв между тем, что показывает train, и тем, что показывает validation. На обучающей части качество становится все лучше. На проверочной части после некоторого момента рост останавливается или сменяется ухудшением. Это очень важный сигнал. Он говорит не о том, что модель «сломалась», а о том, что она перестала учиться общему правилу и начала адаптироваться к деталям конкретной выборки.

Именно поэтому в хорошей практике так важны разбиение данных, кросс-валидация, мониторинг метрик на независимой части, early stopping и аккуратный подбор гиперпараметров. Все эти шаги существуют не ради ритуала. Они защищают нас от самой человеческой ошибки в ML: поверить красивому результату слишком рано.

В Data Science это особенно опасно, потому что метрика на train почти всегда выглядит убедительнее, чем реальная способность модели к обобщению. Но бизнес, продукт, медицина, финансы и любые прикладные системы сталкиваются не с обучающей выборкой. Они сталкиваются с новыми данными. Поэтому борьба с overfitting — это на самом деле борьба за честность оценки качества.

Какие шаги реально снижают риск переобучения

Полезно различать симптом и лекарство. Сам симптом — разрыв между train и validation. А работать нужно с причинами. Иногда помогает уменьшить сложность модели. Иногда — увеличить объем данных. Иногда — удалить утечку. Иногда — сократить число признаков. Иногда — добавить регуляризацию. Иногда — изменить способ валидации, если задача временная и случайный split вообще не отражает реальный сценарий. Нет одной универсальной кнопки. Но почти всегда есть системный путь диагностики.

Здесь полезна практическая логика. Если модель сложная, начните с сильного baseline. Если признаков слишком много, проверьте их устойчивость. Если train слишком хорош, а validation резко хуже, ищите утечку или переизбыток гибкости. Если данных мало, не ждите, что агрессивная модель внезапно научится обобщать. Такая дисциплина выглядит менее эффектно, чем подбор «мощного» алгоритма, но именно она делает результаты надежными. Поэтому рядом очень к месту и материал о baseline-модели, и разбор того, какие признаки реально влияют на модель: один помогает не обманываться красивой сложностью, второй не путать полезный сигнал с шумом в признаках.

Ниже маленький Python-пример, который показывает типичную логику борьбы с overfitting

Пример намеренно простой. Его задача не впечатлить сложностью, а показать маршрут: разделить данные, обучить модель, посмотреть train и validation, затем усилить регуляризацию и сравнить поведение. Именно так и возникает практическое понимание переобучения: через сопоставление качества на разных частях данных, а не через запоминание определения.

import numpy as np  # подключаем NumPy для генерации числовых данных
from sklearn.model_selection import train_test_split  # импортируем разбиение на train и validation
from sklearn.pipeline import Pipeline  # берем Pipeline, чтобы связать преобразование и модель
from sklearn.preprocessing import PolynomialFeatures  # добавляем полиномиальные признаки, увеличивая гибкость модели
from sklearn.linear_model import Ridge  # используем Ridge-регрессию с L2-регуляризацией
from sklearn.metrics import mean_squared_error  # подключаем MSE для оценки качества

rng = np.random.RandomState(42)  # фиксируем генератор случайных чисел для воспроизводимости
x = np.linspace(0, 10, 80)  # создаем 80 точек на отрезке от 0 до 10
y = 2 * x + 3 + rng.normal(scale=3.0, size=x.shape)  # задаем линейную зависимость и добавляем шум
X = x.reshape(-1, 1)  # превращаем одномерный массив в матрицу признаков формата sklearn

X_train, X_valid, y_train, y_valid = train_test_split(  # делим данные на обучающую и проверочную части
    X, y, test_size=0.25, random_state=42
)  # оставляем часть наблюдений для честной проверки обобщающей способности

weak_reg = Pipeline([  # собираем модель с высокой гибкостью и слабой регуляризацией
    ('poly', PolynomialFeatures(degree=8, include_bias=False)),  # строим полиномиальные признаки высокой степени
    ('model', Ridge(alpha=0.01)),  # ставим очень слабую регуляризацию
])  # закрываем описание первого пайплайна

strong_reg = Pipeline([  # собираем вторую модель с той же гибкостью, но более сильным штрафом
    ('poly', PolynomialFeatures(degree=8, include_bias=False)),  # оставляем тот же набор полиномиальных признаков
    ('model', Ridge(alpha=10.0)),  # усиливаем регуляризацию, чтобы уменьшить риск переобучения
])  # закрываем описание второго пайплайна

weak_reg.fit(X_train, y_train)  # обучаем первую модель на train-части
strong_reg.fit(X_train, y_train)  # обучаем вторую модель на той же train-части

weak_train_pred = weak_reg.predict(X_train)  # получаем прогнозы первой модели на train
weak_valid_pred = weak_reg.predict(X_valid)  # получаем прогнозы первой модели на validation
strong_train_pred = strong_reg.predict(X_train)  # получаем прогнозы второй модели на train
strong_valid_pred = strong_reg.predict(X_valid)  # получаем прогнозы второй модели на validation

weak_train_mse = mean_squared_error(y_train, weak_train_pred)  # считаем train-MSE для слабой регуляризации
weak_valid_mse = mean_squared_error(y_valid, weak_valid_pred)  # считаем validation-MSE для слабой регуляризации
strong_train_mse = mean_squared_error(y_train, strong_train_pred)  # считаем train-MSE для сильной регуляризации
strong_valid_mse = mean_squared_error(y_valid, strong_valid_pred)  # считаем validation-MSE для сильной регуляризации

print({  # выводим обе пары метрик, чтобы сравнить риск переобучения
    'weak_reg_train_mse': round(float(weak_train_mse), 3),  # ошибка на train для слабой регуляризации
    'weak_reg_valid_mse': round(float(weak_valid_mse), 3),  # ошибка на validation для слабой регуляризации
    'strong_reg_train_mse': round(float(strong_train_mse), 3),  # ошибка на train для сильной регуляризации
    'strong_reg_valid_mse': round(float(strong_valid_mse), 3),  # ошибка на validation для сильной регуляризации
})  # по разнице между train и validation видно, где модель переобучается сильнее

В этом коде важен не конкретный алгоритм, а сама логика эксперимента. Мы сознательно берем гибкую модель, а затем меняем силу регуляризации. После этого сравниваем, как ведут себя train и validation. Именно такие короткие контролируемые эксперименты учат понимать overfitting намного лучше, чем любые абстрактные определения. А когда становится ясно, что проблема упирается уже не только в штраф, но и в выбор самой конфигурации модели, естественным продолжением становится и подбор гиперпараметров без хаоса.

Overfitting — это не частная техническая неприятность, а центральный критерий зрелости модели

Когда человек только начинает изучать Data Science, ему легко кажется, что качество модели измеряется одной цифрой. Но зрелое мышление начинается в тот момент, когда он спрашивает: на каких данных получена эта цифра, насколько честно построена проверка, не запомнила ли модель лишнее, не скрывается ли за красивым train ложное чувство надежности. В этом смысле overfitting — одна из самых важных тем во всем машинном обучении. Через нее становится видно, что ML — это не соревнование за минимальную ошибку на знакомом наборе, а дисциплина обобщения.

Именно поэтому понимание переобучения так ценно на раннем этапе. Оно заставляет думать не только о моделях, но и о данных, разбиении, признаках, метриках и честности эксперимента. А значит, формирует правильную профессиональную оптику. Если сформулировать совсем коротко, overfitting — это ситуация, в которой модель слишком хорошо помнит частные обстоятельства обучения и недостаточно хорошо понимает общую структуру задачи. И задача специалиста состоит не в том, чтобы этого «никогда не было», а в том, чтобы вовремя это замечать, измерять и контролировать.

Kaggle Notebook по теме статьи: https://www.kaggle.com/code/yogeshthecaptain/exercise-underfitting-and-overfitting

Что читать дальше

Связанные статьи по этой теме

Инструменты Python в 2026 году: современный стек для профессиональной разработки Что должен знать Junior Data Scientist в 2026 году? Как собрать GitHub-портфолио для Data Science
Вернуться в блог