Ответ
Для временных рядов стандартная случайная разбивка данных недопустима, так как нарушает временную зависимость. Необходимо использовать методы, сохраняющие порядок наблюдений.
1. Разделение по времени (Time-based Hold-out) Самый простой метод — выделить последний отрезок ряда в качестве тестовой выборки.
split_index = int(len(series) * 0.8) # 80% на обучение, 20% на тест
train, test = series[:split_index], series[split_index:]
2. Перекрестная проверка с расширяющимся окном (Expanding Window CV)
Обучающая выборка постоянно увеличивается, тестовое окно сдвигается вперед. Реализуется через TimeSeriesSplit в scikit-learn.
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(series):
X_train, X_test = series.iloc[train_index], series.iloc[test_index]
# Обучить модель на X_train, оценить на X_test
3. Перекрестная проверка со скользящим окном (Sliding Window CV) Размер обучающего окна фиксирован, окно "скользит" по ряду. Полезно для моделирования, где актуальна только недавняя история.
def sliding_window_cv(series, train_size, test_size, step=1):
n_splits = (len(series) - train_size - test_size) // step + 1
for i in range(0, n_splits * step, step):
train_end = i + train_size
test_end = train_end + test_size
yield series.iloc[i:train_end], series.iloc[train_end:test_end]
# Пример: окно обучения = 100 точек, окно теста = 20 точек
for train, test in sliding_window_cv(series, train_size=100, test_size=20, step=20):
# ... обучение и оценка
Ключевые принципы:
- Сохранение порядка: Данные для обучения всегда должны предшествовать данным для тестирования.
- Учет сезонности: При разбиении границы фолдов должны проходить между сезонами, а не разрезать их.
- Многократное тестирование: Использование нескольких фолдов дает более надежную оценку устойчивости модели к разным временным периодам.