Ответ
Я выбираю стратегию разбиения, исходя из размера данных, стабильности оценки и типа задачи.
Мои практические правила:
| Размер датасета | Типовая схема | Обоснование и пример |
|---|---|---|
| Очень маленький (< 1k samples) | 60/20/20 или даже 70/15/15 | Максимизирую обучающую выборку, использую кросс-валидацию для валидации. |
| Средний (1k - 100k samples) | 70/15/15 или 80/10/10 | Стандартный баланс между обучением и надёжной оценкой. |
| Крупный (> 100k samples) | 98/1/1 или 99/0.5/0.5 | Даже 1% от большого датасета даёт точную оценку, основная часть идёт в обучение. |
Код для стандартного случая:
from sklearn.model_selection import train_test_split
# Первое разбиение: на тренировочный и временный (test + val) наборы
X_train, X_temp, y_train, y_temp = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
# Второе разбиение: отделяем валидацию от теста
X_val, X_test, y_val, y_test = train_test_split(
X_temp, y_temp, test_size=0.5, random_state=42, stratify=y_temp
)
# Итог: 70/15/15
print(f"Train: {X_train.shape[0]}, Val: {X_val.shape[0]}, Test: {X_test.shape[0]}")
Критические нюансы, которые я проверяю:
- Стратификация. Для классификации всегда использую
stratify=y, чтобы распределение целевого класса сохранялось во всех подвыборках. - Временные ряды. Здесь разбиение должно быть хронологическим. Я использовал
TimeSeriesSplitиз sklearn или просто задавал граничную дату: всё, что до неё — train, после — test. - Стабильность оценки. Я делаю несколько случайных разбиений (с разными
random_state) и смотрю, сильно ли колеблется метрика на тесте. Если колебания велики (например,AUCменяется на ±0.03), значит, тестовая выборка слишком мала или данные неоднородны — нужно увеличить её размер.