Ответ
Отложенная тестовая выборка (hold-out test set) — это часть данных, которая изолируется на самом начале и не используется ни для обучения, ни для настройки гиперпараметров. Её единственная цель — финальная оценка качества уже обученной модели. Стандартный инструмент — train_test_split из sklearn.model_selection.
Базовый пример:
from sklearn.model_selection import train_test_split
# Исходные данные и целевая переменная
X, y = load_data()
# Разделение: 80% на обучение/валидацию, 20% на финальный тест
X_train_val, X_test, y_train_val, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42, # Для воспроизводимости результата
shuffle=True # Перемешивать данные перед разбиением
)
Критически важные практики:
-
Разделение до любых преобразований: Тестовая выборка должна имизировать "новые, невиданные" данные. Любая утечка информации из теста в train (например, через масштабирование) исказит оценку.
# НЕПРАВИЛЬНО: Сначала масштабировать всю выборку, потом делить. # ПРАВИЛЬНО: X_train_val, X_test, y_train_val, y_test = train_test_split(X, y, test_size=0.2) scaler = StandardScaler().fit(X_train_val) # Обучаем scaler ТОЛЬКО на train X_train_val_scaled = scaler.transform(X_train_val) X_test_scaled = scaler.transform(X_test) # Трансформируем тест тем же scaler'ом -
Стратификация (для классификации): Если классы несбалансированы, используйте
stratify=y. Это сохранит пропорции классов в train и test наборах.X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y # Ключевой параметр для классификации ) -
Для временных рядов: Простое случайное разбиение неприменимо, так как нарушает временной порядок. Тестовой выборкой должны быть последние наблюдения.
split_index = int(len(X) * 0.8) X_train, X_test = X[:split_index], X[split_index:] y_train, y_test = y[:split_index], y[split_index:]
Итог: Отложенная выборка — это "священный грааль" для финальной проверки. Все этапы обучения и валидации (включая кросс-валидацию) должны происходить только на X_train_val/y_train_val. К X_test/y_test обращаемся один раз в самом конце.
Ответ 18+ 🔞
Давай разберём эту тему про отложенную выборку, а то тут, бля, народ часто наступает на одни и те же грабли, ебать мои старые костыли.
Представь себе: ты готовишься к экзамену. У тебя есть учебник (это твои тренировочные данные) и есть тайный список вопросов от преподова (это твоя тестовая выборка). Так вот, если ты заранее подсмотришь в этот список, то на экзамене ты, конечно, блеснёшь, но знаний-то нихуя не прибавится. И когда в реальной жизни тебе зададут похожий, но другой вопрос — ты охуеешь. Вот так же и с моделями.
Отложенная тестовая выборка — это как раз тот самый запечатанный конверт с вопросами. Ты его откладываешь в самый дальний ящик в начале проекта и не трогаешь, пока не закончишь всю свою возню с обучением и настройкой. Её единственная цель — дать тебе честный, непредвзятый ответ на вопрос: "Ну и насколько твоя модель, сука, реально умная?"
Стандартный инструмент для этого дела — train_test_split из sklearn. Выглядит просто, но тут, ёпта, дьявол в деталях.
Базовый пример, с него и начнём:
from sklearn.model_selection import train_test_split
# Допустим, у тебя уже есть данные и таргеты
X, y = load_data()
# Делим: 80% оставляем себе для всех экспериментов, 20% — священный тест
X_train_val, X_test, y_train_val, y_test = train_test_split(
X, y,
test_size=0.2, # 20% в тест — классика жанра
random_state=42, # Чтобы при каждом запуске делилось одинаково, а не как бог на душу положит
shuffle=True # Перемешиваем данные перед делением, чтобы не было перекоса
)
Вот, вроде бы, всё просто. Но теперь слушай сюда, потому что большинство косяков происходит на следующем этапе.
Критически важные практики, или как не облажаться
-
Разделение до любых преобразований — это закон! Твоя тестовая выборка должна быть как инопланетянин, который только что с корабля сошёл. Она не должна ничего знать о твоих тренировочных данных. Если ты сначала отмасштабируешь ВСЕ данные, а потом их поделишь — это пиздец, утечка информации. Ты уже дал тестовым данным знание о распределении всего датасета.
# НЕПРАВИЛЬНО (так делать — себя не уважать): # scaler = StandardScaler().fit(X) # Обучаем на ВСЕХ данных # X_scaled = scaler.transform(X) # Трансформируем ВСЁ # # А теперь делим... Поздно, брат. Ты уже всё испортил. # ПРАВИЛЬНО (делай так и будет тебе счастье): X_train_val, X_test, y_train_val, y_test = train_test_split(X, y, test_size=0.2) scaler = StandardScaler().fit(X_train_val) # Обучаем скалер ТОЛЬКО на тренировочной части! X_train_val_scaled = scaler.transform(X_train_val) X_test_scaled = scaler.transform(X_test) # А тест трансформируем тем же самым, уже обученным скалером. Никакого нового `.fit()`! -
Стратификация (особенно для классификации). Если у тебя в данных, например, 90% котов и 10% собак, и ты сделаешь просто случайное разбиение, то может так выйти, что в тест попадут одни коты. Модель, которую ты учил на котах и собаках, будет оцениваться только на котах — результат будет, мягко говоря, необъективный, доверия ебать ноль. Чтобы этого не было, используй
stratify=y. Он сохранит пропорции классов.X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y # Вот эта волшебная штука заставит разделиться честно ) -
Для временных рядов — забудь про случайность. С временными рядами вообще отдельная история. Там нельзя просто взять и перемешать данные, потому что в них есть порядок. Тестом должны быть последние наблюдения, как будто ты предсказываешь будущее.
split_index = int(len(X) * 0.8) # 80% на обучение, 20% на тест X_train, X_test = X[:split_index], X[split_index:] y_train, y_test = y[:split_index], y[split_index:] # Никакого shuffle, никакого random_state. Всё по порядку.
Итог, чтобы запомнить раз и навсегда:
Отложенная выборка — это твой неприкосновенный запас, святой грааль финальной проверки. Всё, что ты делаешь: подбор гиперпараметров, кросс-валидацию, выбор фич — делай ТОЛЬКО на X_train_val и y_train_val. К X_test и y_test ты прикасаешься ОДИН РАЗ, в самом конце, когда модель уже полностью готова и ты хочешь узнать её реальную силу. Если будешь на ней что-то подбирать — считай, что обманул сам себя, и твоя оценка качества будет пиздопроебибной, то есть ни на что не годной.