Диагностика Mock-интервью
Главная · Основы машинного обучения

Кросс-валидация и подбор гиперпараметров

Один сплит train/test даёт шумную оценку, а подбор гиперпараметров по тесту тихо завышает качество. Кросс-валидация, вложенная валидация, grid против random search и байесовская оптимизация — как честно выбрать модель и не обмануть себя.

Интуиция: почему одного сплита мало

Ты отложил 20% данных в тест, обучился на остальных, померил метрику — 0.83. Пересыпал данные с другим случайным зерном (random seed) — стало 0.79. Ещё раз — 0.86. Проблема в том, что при малой выборке сам результат зависит от того, какие именно точки попали в тест: оценка качества сама по себе шумит. Одно число без разброса вокруг него — это иллюзия точности.

Кросс-валидация (cross-validation) убирает случайность выбора, прогоняя проверку много раз по разным разбиениям и усредняя. Мы получаем не одно число, а среднее ± разброс — и второе не менее важно, чем первое.

k-fold кросс-валидация

Делим данные на k равных частей (folds). Затем k раз повторяем: обучаемся на k−1 частях, проверяемся на оставшейся. Каждая точка ровно один раз побывает в роли валидации. Итог — среднее метрик и их стандартное отклонение (standard deviation):

CV = (1/k) · Σi metrici   ±   std(metric1 … metrick)

Типичный выбор — k = 5 или k = 10: компромисс между устойчивостью оценки и стоимостью (обучать приходится k раз). Крайний случай — leave-one-out (LOO), где k равно числу объектов: почти несмещённо, но дорого и с большим разбросом. Для несбалансированных классов берут стратификацию (stratified k-fold) — доля классов в каждом фолде сохраняется, иначе редкий класс может целиком провалиться в один фолд.

💡 Ключевая мысль Кросс-валидация оценивает не одну обученную модель, а рецепт обучения (алгоритм + гиперпараметры). Финальную модель обычно переобучают на всех данных, а CV-оценка говорит, насколько этому рецепту можно доверять.

Прогони CV в честном режиме: перебор степеней выберет что-то умеренное (d ≈ 3–5), а RMSE на отложенном «проде» окажется близко к CV-оценке — оценке можно верить. Теперь переключи на «подбираю по тесту» и снова прогони: алгоритм подстроит степень прямо под «прод», оценка станет красиво низкой — но это та же выборка, по которой отчитываемся. Разрыв между приукрашенной оценкой и честным качеством подсвечен красным: так утечка обманывает.

Главная ловушка: подбор гиперпараметров по тесту

Как только вы выбираете степень полинома, глубину дерева или λ «потому что на тесте вышло лучше», тест перестаёт быть честной оценкой — вы к нему подстроились. Это утечка (data leakage): по многократному подглядыванию в тест просачивается оптимизм. Правило: тест трогают ровно один раз, в самом конце. Для подбора нужен отдельный валидационный набор (validation set) или кросс-валидация внутри обучающей части.

Но и это не всё: если вы кросс-валидацией и подбираете гиперпараметры, и той же CV-оценкой отчитываетесь о качестве — оценка снова завышена, ведь выбор лучшего из многих вариантов сам по себе оптимистичен. Честный способ — вложенная кросс-валидация (nested CV): внешний цикл даёт непредвзятую оценку, а внутренний цикл на каждой его итерации подбирает гиперпараметры отдельно. Дорого (перемножаются два цикла), но это единственный корректный ответ на вопрос «сколько будет стоить весь пайплайн подбора».

Как перебирать гиперпараметры

⚠️ Подводный камень Обычная k-fold с перемешиванием запрещена для временных рядов: случайный фолд поставит будущее в обучение, а прошлое — в валидацию, и модель «подсмотрит вперёд». Оценка выйдет красивой, а в проде — провал. Для рядов только forward-chaining (расширяющееся окно): обучаемся на прошлом, проверяемся на будущем, границу сдвигаем вперёд. То же касается любой утечки при подготовке: масштабирование и отбор признаков считайте внутри фолда, а не по всем данным до разбиения.
🎤 На собеседовании
  • «Зачем нужна валидация, если есть тест?» — тест трогают один раз для честной итоговой оценки; подбор по тесту = утечка и завышенное качество. Гиперпараметры выбирают по валидации/CV.
  • «Что такое nested CV и когда он нужен?» — внешний цикл честно оценивает пайплайн, внутренний подбирает гиперпараметры; нужен, чтобы оценка не была завышена самим фактом выбора лучшего варианта.
  • «Grid search или random search?» — при малой размерности и дискретных значениях — grid; в многомерном пространстве, где важны лишь пара параметров, эффективнее random (Бергстра) или байесовская оптимизация.
  • «Как кросс-валидировать временной ряд?» — только forward-chaining/walk-forward; случайные фолды дают утечку из будущего.