Train/test split: проверяем честно

Главное правило честной оценки: не проверяй модель на том, на чём она училась.

Train/test split — разбиение данных на обучающую часть (train), на которой модель учится, и тестовую (test), на которой проверяют её качество.

Почему нельзя проверять на обучающих данных

Представьте студента, которому дали экзамен ровно с теми же задачами, что были в учебнике с ответами. Он получит пятёрку, даже если просто всё зазубрил, — но это ничего не говорит о том, решит ли он новую задачу. С моделью так же: если оценивать её на тех же примерах, что она видела при обучении, оценка будет завышенной и обманчивой. Модель могла просто «запомнить» обучающие примеры.

Нас интересует обобщающая способность — как модель работает на новых, ранее не виденных данных. Чтобы её измерить, часть данных откладывают и не показывают модели при обучении. На них и проверяют.

Как делят

Обычное соотношение — 70–80% на обучение, 20–30% на тест. Важно перемешать данные перед делением (чтобы тест не оказался, например, только из последних по времени записей), а в классификации — сохранить пропорции классов.

# Простое разбиение 80/20
data = list(range(1, 11))   # 10 объектов
split = int(len(data) * 0.8)

train = data[:split]
test = data[split:]

print("Все данные:", data)
print("Train (80%):", train)
print("Test (20%): ", test)
print("Размеры -> train:", len(train), "| test:", len(test))

Вывод:

Все данные: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Train (80%): [1, 2, 3, 4, 5, 6, 7, 8]
Test (20%):  [9, 10]
Размеры -> train: 8 | test: 2

Золотое правило

Тестовые данные модель не должна видеть до самой финальной проверки. Ни при обучении, ни при нормализации (помните: min/max считаем по train), ни при подборе настроек. Иначе оценка перестаёт быть честной — это называют «подглядыванием» (data leakage).

Где здесь обучающая, валидационная и тестовая

Часто данных делят не на две, а на три части:

ЧастьЗачем
TrainУчим модель
ValidationПодбираем настройки (например, k в kNN)
TestФинальная честная оценка, один раз

Валидация нужна, чтобы подбор настроек не «съел» тест. А чтобы не отдавать под валидацию слишком много данных, используют кросс-валидацию — о ней следующий урок.

На практике

# Иллюстрация (scikit-learn в браузере не запустится)
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
print(len(X_train), len(X_test))

Итог

  • Качество измеряют на тестовых данных, которых модель не видела при обучении.
  • Типичное деление: 70–80% train, 20–30% test, с перемешиванием.
  • Тест нельзя использовать ни для обучения, ни для подготовки, ни для подбора настроек.
  • Для подбора настроек выделяют отдельную валидационную часть.
Проверьте себя
1. Почему нельзя оценивать модель на тех же данных, на которых она обучалась?
AЭто слишком медленно
BОценка будет завышенной: модель могла запомнить примеры, а нас интересует работа на новых данных
CОбучающие данные нельзя читать дважды
DМожно, разницы нет
2. Что такое обобщающая способность модели?
AСкорость обучения
BСпособность хорошо работать на новых, ранее не виденных данных
CЧисло признаков в датасете
DРазмер обучающей выборки
3. Что нельзя делать с тестовыми данными до финальной проверки?
AИспользовать их для обучения, подготовки или подбора настроек
BХранить их в отдельной переменной
CПодсчитывать их количество
DПеремешивать данные перед делением
Поддержать проект