Группировка по выборкам для временных рядов в sklearn
Единственная сила, способная умерять индивидуальный эгоизм, — это сила группы (Эмиль Дюркгейм). Создание выборок для временных рядов имеет свои особенности, связанные с тем, что в реальности предсказания по времени происходят позже обучения. Этот принцип надо соблюдать и при валидации моделей. Создадим демонстрационный набор данных:
import pandas as pd df = pd.DataFrame({'val':[23, 44, 21, 221, 2, 21, 22, 123, 32], 'month':pd.period_range(start='2022-01', end='2022-09', freq='M'), }, index = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']) df['target'] = df['val']**2 df.head(2)
Простым способом создания выборок является отсечение по времени либо использование train_test_split. При этом следует помнить, что перед этим ряд следует упорядочить по времени и параметр shuffle установить в False:
from sklearn.model_selection import train_test_split X_tr, X_ts = train_test_split(df, test_size=0.2, shuffle=False) X_tr
Еще в scikit-learn есть класс TimeSeriesSplit для проведения кросс-валидации. Он проходит n_splits раз по данным с расширяющимся окном так, чтобы в тестовую выборку попадали более поздние точки. Каждая новая тренировочная выборка является расширением старой с добавлением новых точек, а размер тестовой не меняется просто захватываются более "свежие" точки. По умолчанию размер тренировочной выборки на cплите i (всего n_splits): i * n_samples // (n_splits + 1) + n_samples % (n_splits + 1), а тестовой: n_samples//(n_splits + 1):
from sklearn.model_selection import TimeSeriesSplit sp = TimeSeriesSplit(n_splits=3) for tr_idx, val_idx in sp.split(df): display(tr_idx) display(val_idx) print('------------')
Также можно увеличить разрыв между тренировочной и тестовой выборкой, используя параметр gap (убирает из тренировочной выборки gap последних наблюдений):
sp = TimeSeriesSplit(n_splits=3, gap=2) for tr_idx, val_idx in sp.split(df): display(tr_idx) display(val_idx) print('------------')