Ответ
В зависимости от структуры данных и задачи я выбираю разные стратегии кросс-валидации (CV), чтобы получить надежную оценку обобщающей способности модели.
Основные стратегии и их применение:
-
K-Fold Cross-Validation Стандартный выбор для большинства задач с независимыми и одинаково распределенными (IID) данными. Данные случайно перемешиваются и разбиваются на K равных частей (фолдов).
from sklearn.model_selection import KFold import numpy as np X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]) y = np.array([1, 2, 3, 4, 5]) kf = KFold(n_splits=5, shuffle=True, random_state=42) for train_index, val_index in kf.split(X): X_train, X_val = X[train_index], X[val_index] y_train, y_val = y[train_index], y[val_index] # Обучение и оценка модели -
Stratified K-Fold Когда применяю: Для задач классификации с несбалансированными классами. Эта стратегия сохраняет процентное соотношение классов в каждом фолде, что дает более стабильную оценку метрик (например, F1-score для миноритарного класса).
from sklearn.model_selection import StratifiedKFold skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) # Используется аналогично KFold, но передается и y для стратификации for train_index, val_index in skf.split(X, y): ... -
Time Series Split (или TimeSeriesCV) Когда применяю: Для данных, имеющих временную зависимость (финансовые котировки, сенсорные данные). Важно не допустить "утечки будущего в прошлое". Каждый последующий тренировочный набор является надмножеством предыдущего.
from sklearn.model_selection import TimeSeriesSplit tscv = TimeSeriesSplit(n_splits=5) for train_index, val_index in tscv.split(X): # train_index всегда предшествует val_index по времени -
Leave-One-Out (LOO) Частный случай K-Fold, где
K = N(число объектов). Каждый объект по очереди становится валидационным. Применяю очень редко из-за высокой вычислительной стоимости, только для очень маленьких датасетов (десятки образцов). -
Group K-Fold Когда применяю: Когда в данных есть группы, и нужно убедиться, что объекты из одной группы не попадут одновременно в train и test. Например, данные от нескольких пациентов в медицинском датасете или несколько снимков одного объекта.
from sklearn.model_selection import GroupKFold groups = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5] # ID группы для каждого образца gkf = GroupKFold(n_splits=5) for train_index, val_index in gkf.split(X, y, groups=groups): # Объекты с одинаковым group_id не будут разбиты между фолдами
В 90% случаев для табличных данных я начинаю с Stratified K-Fold (shuffle=True) для классификации и обычного K-Fold для регрессии, если нет явной временной или групповой структуры.
Ответ 18+ 🔞
Ну вот, сидишь ты такой, выбираешь, как модель проверить, чтобы потом не охуеть от результатов на реальных данных. Тут, блядь, целая наука, но если по-простому, то есть несколько проверенных способов, и каждый — под свою задачу. Слушай сюда.
Как я обычно кросс-валидацию кручу, чтобы не облажаться:
-
Обычный K-Fold (K-кратная) Это как стандартный инструмент в ящике. Берёшь, если данные обычные, независимые, и все объекты друг на друга не влияют. Просто мешаешь их как карты и режешь на K одинаковых стопок (фолдов).
from sklearn.model_selection import KFold import numpy as np X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]) y = np.array([1, 2, 3, 4, 5]) kf = KFold(n_splits=5, shuffle=True, random_state=42) for train_index, val_index in kf.split(X): X_train, X_val = X[train_index], X[val_index] y_train, y_val = y[train_index], y[val_index] # Тут модель учишь и смотришь, не говно ли она -
Stratified K-Fold (Стратифицированная) Включаю, когда делаю классификацию, а классы в данных разной численности — один овердохуища, а другой — кот наплакал. Эта штука следит, чтобы в каждом фолде пропорции классов были как в исходнике, иначе оценка метрик будет пиздец какая нестабильная.
from sklearn.model_selection import StratifiedKFold skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) # Тут важно y передать, чтобы он знал, как стратифицировать for train_index, val_index in skf.split(X, y): ... -
Time Series Split (Для временных рядов) Беру на вооружение, если данные идут по времени — продажи, показания датчиков, курс биткоина. Тут главное — не налажать с утечкой из будущего в прошлое, это моветон. Поэтому тренировочные данные всегда хронологически идут ДО валидационных.
from sklearn.model_selection import TimeSeriesSplit tscv = TimeSeriesSplit(n_splits=5) for train_index, val_index in tscv.split(X): # train_index всегда в прошлом относительно val_index -
Leave-One-Out (LOO) Это когда каждый объект по очереди становится тестовым. Использую раз в пятилетку, только если датасет микроскопический, человек на двадцать. Потому что считать это — ебать мои старые костыли, комп взвоет.
-
Group K-Fold (Групповая) Выручает, когда в данных есть скрытые группы. Например, снимки от одних и тех же пациентов или замеры с одного прибора. Важно, чтобы объекты из одной группы не разбрелись по train и test одновременно, иначе модель сжульничает и оценка будет хуйня.
from sklearn.model_selection import GroupKFold groups = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5] # Кто с кем в одной группе gkf = GroupKFold(n_splits=5) for train_index, val_index in gkf.split(X, y, groups=groups): # Группы не будут разорваны между фолдами
Если в двух словах, то в 90% случаев для табличных данных я стартую с Stratified K-Fold (с перемешиванием) для классификации и с обычного K-Fold для регрессии. Но если чувствую подвох — временную зависимость или группы — сразу переключаюсь на специализированные методы. Иначе потом сам от себя охуеешь, когда модель в продакшене накроется медным тазом.