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

В мире машинного обучения данные — это топливо, которое приводит в движение каждую модель. Однако то, насколько правильно вы используете это топливо, определяет, станет ли ваша модель умным двигателем, способным точно предсказывать будущее, или попугаем, который умеет лишь заучивать наизусть.

Сегодня мы глубоко погрузимся в важнейшую и основополагающую концепцию машинного обучения:разделение на обучающую и тестовую выборки. Это первый шаг в построении любой надёжной модели и ключ к оценке истинных возможностей модели.

Проще говоря, разделение на обучающую и тестовую выборки похоже на учёбу и сдачу экзаменов в школьные годы:

  • Обучающая выборка— это учебники и практические задачи учащегося; модель использует её, чтобы изучить правила и закономерности в данных.
  • Тестовая выборка— это итоговый экзамен; модель использует его, чтобы проверить, действительно ли она освоила знания, а не просто запомнила ответы к тренировочным задачам (обучающей выборке).

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

Представьте студента, который повторял только пробные вопросы, данные преподавателем, а экзаменационные вопросы оказались точно такими же пробными вопросами. Он получил высший балл. Доказывает ли это, что он действительно понял предмет? Очевидно, нет. Возможно, он просто запомнил ответы.

В машинном обучении, если мы обучаем модель навсех данных, а затем используемте же данныедля оценки её производительности, мы совершаем ту же ошибку. Модель будет выглядеть исключительно хорошо, потому что она «видела» и «запомнила» каждую деталь данных, включая шум и случайные совпадения. Это явление называетсяпереобучение。

Переобученная модель похожа на студента, который умеет только заучивать примеры вопросов; как только она сталкивается с новыми, невиданными вопросами (новыми данными), она показывает очень плохие результаты. Её «способность к обобщению» очень слаба.

Поэтому мы должны разделить данные на две части:

  1. Обучающая выборка: используется дляобучениятренировки модели, позволяя ей учиться.
  2. Тестовая выборка: используется, чтобыпроверятьоценивать модель и определять, как она справляется сновыми данными, которых никогда не видела.

Тестовая выборка должна быть полностью изолирована от обучающей выборки инедолжна быть видна модели в течение всего процесса обучения. Только так результаты оценки на тестовой выборке смогут объективно отразить истинную способность модели к обобщению.


Как разделять: распространённые методы и стратегии

Разделение данных звучит просто, но здесь есть много нюансов. Разные стратегии разделения подходят для разных сценариев.

1. Простое случайное разделение

Это самый базовый и распространенный метод. Случайно перемешайте весь набор данных, затем разделите его на две части в соответствии с определенным соотношением.

Пример

# Пример: используйте библиотеку scikit-learn в Python для случайного разделения
from sklearn.model_selection import train_test_split

# Предположим, X — это признаковые данные, а y — данные меток
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

print(f"Количество образцов в обучающей выборке: {len(X_train)}")
print(f"Количество образцов в тестовой выборке: {len(X_test)}")

Пояснение кода:

  • train_test_split: Это основная функция в scikit-learn для разделения данных.
  • X, y: Входные признаковые данные и соответствующие метки.
  • test_size=0.2: Указывает, что доля тестовой выборки составляет 20% (т.е. обучающая выборка — 80%). Вы также можете использоватьtrain_size=0.8, чтобы указать это.
  • random_state=42: Установите начальное значение генератора случайных чисел. Это гарантирует, что результат разделения будет в точности одинаковым при каждом запуске кода, что критически важно для воспроизводимости экспериментов. Вы можете задать любое целое число.

2. Стратифицированное разделение выборки

В задачах классификации, если распределение классов в наборе данных несбалансировано (например, 90% класс A, 10% класс B), простое случайное разделение может привести к тому, что пропорции классов в обучающей и тестовой выборках будут сильно различаться, что влияет на объективность оценки.

Стратифицированная выборкаобеспечивает, что пропорции каждого класса в обучающем и тестовом наборах остаются согласованными с исходным набором данных.

Пример

# Пример: использование стратифицированной выборки в задаче классификации
from sklearn.model_selection import train_test_split

# Предположим, y — это метки классификации
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)

# Проверить распределение классов после разделения
from collections import Counter
print("Распределение классов в исходных данных:", Counter(y))
print("Распределение классов в обучающем наборе:", Counter(y_train))
print("Распределение классов в тестовом наборе:", Counter(y_test))

Пояснение кода:

  • stratify=y: Это ключевой параметр. Он указывает функции стратифицировать в соответствии сyраспределением классов меток при выполнении стратифицированной выборки.

3. Разделение данных временных рядов

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

Обычная практика — разбивать в хронологическом порядке:Используйте первые 80% данных по времени в качестве обучающей выборки, а последние 20% — в качестве тестовой.。

Пример

# Пример: последовательное разбиение данных временного ряда
split_index = int(len(X) * 0.8) # Вычислить индекс в позиции 80%

X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]

print(f"Временной диапазон обучающей выборки: первые {split_index} примеров")
print(f"Временной диапазон тестовой выборки: последние {len(X) - split_index} примеров")

Как выбрать пропорцию разбиения?

Это частый вопрос, но универсального ответа нет. Распространённые соотношения включают:

Соотношение (обучающая выборка:тестовая выборка) Сценарий применения Преимущества Недостатки
70:30 Классический выбор для малых и средних наборов данных (от тысяч до десятков тысяч примеров) Балансирует размер обучающих данных и надёжность оценки Для чрезвычайно малых наборов данных тестовая выборка размером 30% может содержать слишком мало примеров, что делает оценку нестабильной
80:20 В настоящее время более популярный выбор по умолчанию, особенно подходящий для глубокого обучения Обеспечивает модели больше данных для обучения Тестовая выборка относительно мала, поэтому дисперсия оценки может быть немного больше
90:10 или 95:5 Когда объём данных очень ограничен Максимизирует использование ограниченных данных для обучения Тестовая выборка слишком мала, поэтому результаты оценки могут быть ненадёжными и иметь низкую достоверность

Основные принципы:

  1. Убедитесь, что обучающая выборка достаточно велика: модели нужно достаточно данных, чтобы изучить эффективные закономерности.
  2. Убедитесь, что тестовая выборка достаточно велика: тестовая выборка должна обеспечивать статистически надёжную оценку производительности. Обычно тестовая выборка должна содержать как минимум несколько сотен примеров для стабильных результатов оценки.
  3. Чем больше объём данных,тем относительноменьшуюдолю можно выделить для тестовой выборки, потому что даже очень небольшая доля может представлять большое количество примеров.

Продвинутые концепции: валидационная выборка и кросс-валидация

В реальных проектах нам нужно не только оценивать итоговую модель, но и настраиватьгиперпараметрымодели (такие как скорость обучения, глубина дерева и т. д.) во время обучения. Если мы напрямую используем тестовую выборку для настройки параметров, тестовая выборка снова становится «загрязнённой», теряя свою беспристрастность в роли «финального экзаменатора».

Для этого мы вводимвалидационную выборку。

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

  1. Обучающая выборка: используется для изучения параметров модели.
  2. Валидационная выборка: используется для настройки гиперпараметров, выбора моделей или ранней остановки во время обучения. Она эквивалентна «пробному экзамену».
  3. Тестовая выборка: используется для финальной, однократной оценки производительности после того, как определены и модель, и гиперпараметры. Это «финальный экзамен».

Пример

# Пример: сначала отделяем обучающую+валидационную выборку и тестовую выборку, затем отделяем валидационную выборку от обучающей+валидационной выборки
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.15, random_state=42) # Сначала откладываем 15% в качестве финальной тестовой выборки
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.176, random_state=42) # Затем из оставшихся 85% откладываем около 15% в качестве валидационной выборки

# Вычислите соотношение: 0.85 * 0.176 ≈ 0.15, итоговое соотношение примерно 70:15:15
print(f"Обучающая выборка: {len(X_train)}, Валидационная выборка: {len(X_val)}, Тестовая выборка: {len(X_test)}")

K-кратная кросс-валидация

Когда объём данных невелик, выделение отдельной валидационной выборки ещё больше сокращает обучающие данные.K-кратная кросс-валидацияявляется более мощным решением.

Её процесс выглядит следующим образом, и она позволяет эффективно использовать ограниченные данные:

Пример

flowchart TD
A[Исходный набор данных] --> B[Случайно перемешать и равномерно разделить на K частей]
B --> C{Повторить для K раундов}
C --> D[Раунд i: использовать i-ю часть как валидационную выборку]
D --> E[Объединить оставшиеся K-1 частей в обучающую выборку]
E --> F[Обучить модель на обучающей выборке для этого раунда]
F --> G[Оценить показатель Si на валидационной выборке для этого раунда]
    G --> C
C -- После завершения K раундов --> H[Вычислить среднее значение K оценок в качестве итоговой оценки]

Пример

# Пример: оценка модели с помощью 5-кратной кросс-валидации
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
scores = cross_val_score(model, X, y, cv=5) # cv=5 означает 5-кратную кросс-валидацию

print(f"Оценки для каждого фолда: {scores}")
print(f"Средняя оценка: {scores.mean():.4f} (+/- {scores.std()*2:.4f})") # Вывести среднее значение и стандартное отклонение

Преимущества кросс-валидации:

  • Полностью использует все данные для обучения и валидации.
  • Результаты оценки более стабильны и надёжны (потому что они являются средним значением нескольких оценок).
  • Это золотой стандарт для выбора модели и настройки гиперпараметров на малых и средних наборах данных.

Практическое упражнение: самостоятельно выполните разделение данных

Теперь давайте попрактикуемся на простом наборе данных.

Пример

# 1. Импорт необходимых библиотек
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# 2. Загрузите набор данных Iris
iris = load_iris()
X, y = iris.data, iris.target
print(f"Форма набора данных: признаки {X.shape}, метки {y.shape}")

# 3. Простое случайное разделение (80% на обучение, 20% на тестирование)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Случайное разделение -> Обучающая выборка: {X_train.shape}, Тестовая выборка: {X_test.shape}")

# 4. Стратифицированное случайное разделение
X_train_s, X_test_s, y_train_s, y_test_s = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
print(f"Стратифицированное разделение -> Обучающая выборка: {X_train_s.shape}, Тестовая выборка: {X_test_s.shape}")

# 5. Проверка эффекта стратификации
print("\n"Распределение классов в исходных данных:", np.bincount(y))
print("Распределение тестовой выборки после случайного разделения:", np.bincount(y_test)) # Может быть несбалансированным
print("Распределение тестовой выборки после стратифицированного разделения:", np.bincount(y_test_s)) # Должно быть пропорционально исходному распределению

Ваша задача:

  1. Запустите приведённый выше код и посмотрите на результаты вывода.
  2. Попробуйте изменитьtest_sizeна 0.3 и посмотрите, как изменятся размеры обучающей и тестовой выборок.
  3. Попробуйте изменитьrandom_stateна другое число (например, 7), запустите снова и посмотрите, изменятся ли результаты разбиения.
  4. (Сложное задание) Не задавайтеrandom_stateпараметр, запустите код несколько раз и посмотрите, одинаковы ли результаты разбиения каждый раз.

Итоги и ключевые моменты

  • Основная цель: разделение обучающей и тестовой выборок необходимо дляоценки способности модели к обобщению, предотвращения переобучения и обеспечения того, чтобы модель могла работать с новыми данными.
  • Золотое правило:Тестовая выборка должна сохраняться в полной тайне на протяжении всего процесса обучения, и использоваться только для финальной оценки.
  • Методы разбиения:
    • Случайное разбиение: наиболее часто используемое.
    • Стратифицированное разбиение: Подходит для несбалансированных данных в задачах классификации.
    • Последовательное разбиение: Подходит для данных временных рядов.
  • Пропорция разбиения: Не существует абсолютного стандарта; необходим компромисс между "достаточным обучением" и "надёжной оценкой". 80:20 или 70:30 — обычные начальные значения.
  • Продвинутые инструменты:
    • Валидационная выборка: Используется для настройки модели, защищая чистоту тестовой выборки.
    • K-кратная кросс-валидация: Мощный инструмент для оценки и настройки на малых и средних наборах данных, дающий более устойчивые результаты.
Другие расширения