Как спрогнозировать значения на n дней? out-of-sample

Обучил модель предсказывать данные на тестовом наборе данных. Теперь нужно сделать прогноз на n-дней от последней даты в датасете. Как это сделать?

Обучал модель так:

  1. Сгенерил новые признаки
def make_features(data, max_lag, rolling_mean_size):

    data['day'] = data.index.day
    data['weekday'] = data.index.weekday
    data['dayofyear'] = data.index.dayofyear
    for lag in range(1, max_lag+1):
        data['lag_{}'.format(lag)]= data['events'].shift(lag)
    data['rolling_mean'] = data['events'].shift().rolling(rolling_mean_size).mean()
    data['rolling_std'] = data['events'].rolling(2).std()
    return data
  1. Разбил на тестовые и тренировочные данные
def timeseries_train_test_split(X, y, test_size):
    
    # Получаем индекс, с которого начинаются тестовые данные
    test_index = int(len(X)*(1-test_size))
    
    X_train = X.iloc[:test_index]
    y_train = y.iloc[:test_index]
    X_test = X.iloc[test_index:]
    y_test = y.iloc[test_index:]
    
    return X_train, X_test, y_train, y_test

y = data_new.dropna().events
X = data_new.dropna().drop(['events'], axis=1)

X_train, X_test, y_train, y_test = timeseries_train_test_split(X, y, test_size=0.1)
  1. Обучил XGboost-ом
reg = xgb.XGBRegressor(n_estimators=1000,
                       nthread=4,
                       min_child_weight=6,
                       learning_rate=0.1,
                       subsample=0.7,
                       max_depth=11,
                       colsample_bytree=0.7,
                      )

reg.fit(X_train, y_train,
        eval_set=[(X_train, y_train), (X_test, y_test)],
        early_stopping_rounds=50, 
        verbose=False) 
X_test_pred = reg.predict(X_test)

В результате получил 2-недельное предсказание по тестовому набору данных https://skr.sh/sBimjbd3ITY?a


Ответы (1 шт):

Автор решения: CrazyElf

Если это задача на временные ряды, то предсказывать нужно пошагово:

  1. делаете фичи из имеющихся у вас данных
  2. предсказываете на день вперёд за край имеющихся данных
  3. добавляете полученное предсказание в ваши данные
  4. если ещё не все n дней предсказали, то переходите к п.1

Конечно, при таком методе предсказания степень неопределённости сильно растёт с каждым шагом. Если сначала вы опирались на реальные данные, то с каждым последующим шагом вы всё больше начинаете опираться на ваши же предсказания. Поэтому предсказание временных рядов без чёткой периодичности и без дополнительных каких-то данных - дело довольно рисковое.

Update: Как собственно предсказывать.

  • делаете новый датафрейм с индексом - следующей датой за максимальной, имеющейся в X, добавляете его через concat к собственно X в конец
  • запускаете make_features на этом обновлённом X, таким образом заполняете фичи везде, включая последнюю строку датафрейма
  • берёте последнюю строку с уже заполненными теперь фичами X_pred = X.iloc[[-1]]
  • получаете предсказание y_pred = reg.predict(X_pred)
  • дальше можете заполнить X['events'] = y_pred[0]
  • и перейти к предсказанию следующей даты
→ Ссылка