Статья Автор: Деникина Н.В., Деникин А.В.

Разделение данных на обучающую и тестовую выборки

Зачем разделять данные?

Основная проблема: переобучение (overfitting)

Представьте, что вы готовитесь к экзамену и заучиваете наизусть все задачи из учебника. На экзамене попадаются те же самые задачи — вы получаете 100%. Но если попадутся новые задачи — вы не справитесь, потому что не понимаете принципы, а просто запомнили ответы.

То же самое происходит с моделями машинного обучения!

Проблема без разделения:

# ❌ НЕПРАВИЛЬНО: обучаем и тестируем на одних данных
model.fit(X, y)
predictions = model.predict(X)  # Те же самые данные!
score = model.score(X, y)  # R² = 1.0 (идеально!)

# Но на новых данных модель работает плохо!

Почему плохо?

  • Модель "запомнила" обучающие данные, включая шум и случайные выбросы
  • Метрики качества завышены и не отражают реальную производительность
  • На новых данных модель работает гораздо хуже

Решение: разделение данных

# ✅ ПРАВИЛЬНО: разделяем данные
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)

# Обучаем только на train
model.fit(X_train, y_train)

# Тестируем на данных, которые модель НЕ ВИДЕЛА
predictions = model.predict(X_test)
score = model.score(X_test, y_test)  # Честная оценка!

Концепция разделения

Визуальное представление:

Полный датасет (100%)
├── Train (80%) ────────────────────► Обучение модели
└── Test (20%)  ────────────────────► Проверка качества

Назначение каждой выборки:


 
Выборка Назначение Использование
Train Обучение модели model.fit(X_train, y_train)
Test Оценка качества model.predict(X_test)

Золотое правило: Модель никогда не должна видеть тестовые данные во время обучения!


Функция train_test_split в sklearn

Базовый синтаксис:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y)

Что возвращает функция?

Функция возвращает 4 объекта в следующем порядке:

  1. X_train — признаки для обучения
  2. X_test — признаки для тестирования
  3. y_train — целевая переменная для обучения
  4. y_test — целевая переменная для тестирования
# Визуализация разделения
print(f"X_train shape: {X_train.shape}")  # (400, 5) — 400 объектов, 5 признаков
print(f"X_test shape: {X_test.shape}")    # (100, 5) — 100 объектов, 5 признаков
print(f"y_train shape: {y_train.shape}")  # (400,) — 400 значений
print(f"y_test shape: {y_test.shape}")    # (100,) — 100 значений

Параметры train_test_split

1. test_size — размер тестовой выборки

Типы значений:

# Вариант 1: Доля от 0.0 до 1.0 (наиболее популярно)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 20% данных в test, 80% в train

# Вариант 2: Абсолютное количество объектов
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=100)
# Ровно 100 объектов в test

# Вариант 3: По умолчанию (если не указан)
X_train, X_test, y_train, y_test = train_test_split(X, y)
# test_size=0.25 (25% по умолчанию)

Типичные значения:


 
test_size Описание Когда использовать
0.2 (20%) Стандартный вариант Для большинства задач
0.3 (30%) Больше данных для теста Когда данных много (>10000)
0.1 (10%) Меньше данных для теста Когда данных мало (<500)

2. train_size — размер обучающей выборки

# Можно указать train_size вместо test_size
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)
# 80% в train, 20% в test (то же, что test_size=0.2)

# Или оба параметра (должны в сумме давать 1.0 или общее число)
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, test_size=0.3)

3. random_state — контроль случайности

Самый важный параметр для воспроизводимости!

# Без random_state — каждый раз разное разделение
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Запуск 1: объекты [0,1,2,3,4] попали в test
# Запуск 2: объекты [5,7,9,11,15] попали в test

# С random_state — всегда одинаковое разделение
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Запуск 1: объекты [0,1,2,3,4] попали в test
# Запуск 2: объекты [0,1,2,3,4] попали в test (те же!)

Зачем это нужно?

  • ✅ Воспроизводимость результатов
  • ✅ Возможность сравнить разные модели на одних и тех же данных
  • ✅ Отладка кода
  • ✅ Научные исследования (другие смогут повторить ваши результаты)

Какое значение выбрать?

  • Любое целое число: 0, 1, 42, 123, 999, ...
  • 42 — самое популярное (отсылка к "Автостопом по галактике")
  • Главное — использовать одно и то же значение во всем проекте

4. shuffle — перемешивание данных

# shuffle=True (по умолчанию) — данные перемешиваются перед разделением
X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle=True)

# shuffle=False — данные НЕ перемешиваются
X_train, X_test, y_train, y_test = train_test_split(X, y, shuffle=False)
# Train: первые 80% строк
# Test: последние 20% строк

Когда использовать shuffle=False?

  • Временные ряды (данные упорядочены по времени)
  • Когда порядок данных важен

В большинстве случаев используйте shuffle=True (по умолчанию)!

Печать