Какой процент от датасета брать на валидацию?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Оптимальный процент валидационного датасета
Выбор размера валидационного сета зависит от нескольких факторов, и нет универсального ответа. Стандартный подход — split данные на train/val/test в соотношении 70-80% / 10-15% / 10-15% или 80% / 10% / 10%, но это требует уточнения.
Основные рекомендации по размеру
1. Классический подход
train : val : test = 80 : 10 : 10
Это проверенный вариант на большинстве задач:
from sklearn.model_selection import train_test_split
# Первый split: 80% train, 20% временный
X_train, X_temp, y_train, y_temp = train_test_split(
X, y, test_size=0.20, random_state=42
)
# Второй split: разделяем временный на 50% val и 50% test
X_val, X_test, y_val, y_test = train_test_split(
X_temp, y_temp, test_size=0.50, random_state=42
)
print(f"Train: {len(X_train) / len(X)}")
print(f"Val: {len(X_val) / len(X)}")
print(f"Test: {len(X_test) / len(X)}")
Итог: Train 80%, Val 10%, Test 10%
2. Когда валидация < 10%
Когда данных много (> 1 млн примеров):
- Val может быть 5% или даже меньше
- Статистическая значимость сохраняется
- Больше данных для обучения
# Для больших датасетов
X_train, X_temp, y_train, y_temp = train_test_split(
X, y, test_size=0.10, random_state=42 # 90% train, 10% temp
)
X_val, X_test, y_val, y_test = train_test_split(
X_temp, y_temp, test_size=0.50, random_state=42 # 5% val, 5% test
)
3. Когда валидация > 15%
Когда данных мало (< 10k примеров):
- Используй 70-80% train, 15-20% val
- Или применяй K-Fold кросс-валидацию вместо простого split
from sklearn.model_selection import StratifiedKFold
# K-Fold валидация для малых датасетов
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
for fold, (train_idx, val_idx) in enumerate(kfold.split(X, y)):
X_train, X_val = X[train_idx], X[val_idx]
y_train, y_val = y[train_idx], y[val_idx]
print(f"Fold {fold}: train {len(train_idx)}, val {len(val_idx)}")
Специальные случаи
Time Series (временные ряды)
Нельзя случайно перемешивать — нужна временная последовательность:
# Неправильно
X_train, X_val = train_test_split(X_time_series, test_size=0.2)
# Правильно
train_size = int(len(X_time_series) * 0.8)
X_train = X_time_series[:train_size]
X_val = X_time_series[train_size:]
Рекомендация: 80% train, 20% val (или даже 90/10 для длинных рядов)
Дисбалансированные классы
Используй stratified split:
from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
# Проверка сохранения пропорций
print(f"Train pos rate: {y_train.sum() / len(y_train):.2%}")
print(f"Val pos rate: {y_val.sum() / len(y_val):.2%}")
Глубокое обучение (Deep Learning)
- Больше train данных — модель требует много примеров
- Val может быть 5-10% (для ускорения обучения)
- Используй early stopping на валидации
from tensorflow.keras.callbacks import EarlyStopping
early_stop = EarlyStopping(
monitor=val_loss,
patience=5,
restore_best_weights=True
)
model.fit(
X_train, y_train,
validation_data=(X_val, y_val),
callbacks=[early_stop],
epochs=100
)
Практические рекомендации
| Размер датасета | Train | Val | Test | Метод |
|---|---|---|---|---|
| < 1k | 60-70% | 15-20% | 15-20% | Stratified K-Fold (5-10) |
| 1k - 100k | 70-80% | 10-15% | 10-15% | Random split |
| > 100k | 80-90% | 5-10% | 5-10% | Random split |
| Time Series | 80-90% | 10-20% | - | Временной split |
Контроль качества
# Проверка репрезентативности
assert abs(y_train.mean() - y_val.mean()) < 0.05
assert abs(y_train.mean() - y_test.mean()) < 0.05
# Проверка независимости
assert len(set(X_train) & set(X_val)) == 0
assert len(set(X_val) & set(X_test)) == 0
Итог
Стандарт: 80-10-10 — это золотой стандарт на большинстве задач. Но адаптируй под свой датасет:
- Много данных → меньше валидации (5%)
- Мало данных → больше валидации (15-20%) или K-Fold
- Временной ряд → только временной split
- Дисбаланс → stratified split
Главное — валидационный сет должен быть достаточно большим для статистической значимости, но не настолько, чтобы уменьшить обучающие данные ниже критического уровня.