Использование ARIMA для прогнозирования средней дневной ставки
Средние дневные ставки (далее именуемые ADR) представляют собой средние дневные ставки, оплачиваемые постоянным клиентом в отеле.
Это важный показатель для отеля, поскольку он отражает общую прибыльность каждого клиента.
В этом примере средние дневные ставки для каждого клиента усредняются за неделю, а затем прогнозируются с использованием модели ARIMA.
Приведенный ниже анализ основан на данных Antonio, Almeida and Nunes (2019): Наборы данных о спросе на бронирование отелей.
Манипуляция данными
В этом конкретном наборе данных год и номер недели для каждого клиента (вместе с зарегистрированным значением ADR каждого клиента) указываются отдельно.
Вот столбцы даты:
Вот столбец ADR:
Во-первых, номер года и недели объединяется в одну строку:
df1 = df['ArrivalDateYear'].map(str) + df['ArrivalDateWeekNumber'].map(str) print (df1) df1=pd.DataFrame(df1)
Затем новый столбец объединяется со столбцом ADR с помощью панд:
df2 = DataFrame(c, columns= ['ADR']) df2 df3=pd.concat([df1, df2], axis = 1) df3 df3.columns = ['FullDate', 'ADR']
Затем эти значения сортируются по дате:
df3 df3.sort_values(['FullDate','ADR'], ascending=True)
Следующим шагом будет получение среднего значения ADR за неделю, например для записи 201527 (27-я неделя 2015 г.) все значения ADR усредняются, и так далее для каждой последующей недели.
df4 = df3.groupby('FullDate').agg("mean") df4 df4.sort_values(['FullDate'], ascending=True)
ARIMA
Используя этот недавно сформированный временной ряд, модель ARIMA теперь может использоваться для прогнозирования ADR.
В этой модели первые 100 недель данных используются в качестве обучающих данных, а последние 15 недель используются как тестовые данные для сравнения с прогнозами, сделанными моделью. .
Вот график вновь сформированного временного ряда:
С первого взгляда на график кажется, что сезонность присутствует. Однако для проверки этого на обучающих данных генерируется функция автокорреляции.
plot_acf(train_df, lags=60, zero=False);
Мы можем видеть, что корреляции (после падения примерно между 10 и 45 неделями) автокорреляция снова достигает пика на лаге 52, что подразумевает годовую сезонность. По сути, это означает, что существует сильная корреляция между значениями ADR, регистрируемыми каждые 52 недели.
Используя эту информацию, m = 52 устанавливается как сезонный компонент в модели ARIMA, а pmdarima используется для автоматического выбора параметров p, d, q для модель.
>>> Arima_model=pm.auto_arima(train_df, start_p=0, start_q=0, max_p=10, max_q=10, start_P=0, start_Q=0, max_P=10, max_Q=10, m=52, stepwise=True, seasonal=True, information_criterion='aic', trace=True, d=1, D=1, error_action='warn', suppress_warnings=True, random_state = 20, n_fits=30) Performing stepwise search to minimize aic ARIMA(0,1,0)(0,1,0)[52] : AIC=422.399, Time=0.32 sec ARIMA(1,1,0)(1,1,0)[52] : AIC=inf, Time=21.87 sec ARIMA(0,1,1)(0,1,1)[52] : AIC=inf, Time=48.20 sec ARIMA(0,1,0)(1,1,0)[52] : AIC=inf, Time=40.99 sec ARIMA(0,1,0)(0,1,1)[52] : AIC=inf, Time=38.19 sec ARIMA(0,1,0)(1,1,1)[52] : AIC=inf, Time=39.33 sec ARIMA(1,1,0)(0,1,0)[52] : AIC=414.708, Time=0.95 sec ARIMA(1,1,0)(0,1,1)[52] : AIC=inf, Time=47.51 sec ARIMA(1,1,0)(1,1,1)[52] : AIC=inf, Time=59.30 sec ARIMA(2,1,0)(0,1,0)[52] : AIC=413.878, Time=1.86 sec ARIMA(2,1,0)(1,1,0)[52] : AIC=inf, Time=59.96 sec ARIMA(2,1,0)(0,1,1)[52] : AIC=inf, Time=60.34 sec ARIMA(2,1,0)(1,1,1)[52] : AIC=inf, Time=77.60 sec ARIMA(3,1,0)(0,1,0)[52] : AIC=414.514, Time=2.05 sec ARIMA(2,1,1)(0,1,0)[52] : AIC=415.165, Time=3.74 sec ARIMA(1,1,1)(0,1,0)[52] : AIC=413.365, Time=1.91 sec ARIMA(1,1,1)(1,1,0)[52] : AIC=415.351, Time=66.38 sec ARIMA(1,1,1)(0,1,1)[52] : AIC=inf, Time=57.54 sec ARIMA(1,1,1)(1,1,1)[52] : AIC=inf, Time=76.00 sec ARIMA(0,1,1)(0,1,0)[52] : AIC=411.433, Time=1.08 sec ARIMA(0,1,1)(1,1,0)[52] : AIC=413.422, Time=29.17 sec ARIMA(0,1,1)(1,1,1)[52] : AIC=inf, Time=67.32 sec ARIMA(0,1,2)(0,1,0)[52] : AIC=413.343, Time=1.76 sec ARIMA(1,1,2)(0,1,0)[52] : AIC=415.196, Time=3.69 sec ARIMA(0,1,1)(0,1,0)[52] intercept : AIC=413.377, Time=2.05 sec Best model: ARIMA(0,1,1)(0,1,0)[52] Total fit time: 809.281 seconds
Конфигурация модели ARIMA ARIMA (0, 1, 1) (0, 1, 0) [52] указана как модель наилучшего соответствия согласно наименьшему значению AIC.
Теперь с помощью модели можно делать прогнозы на следующие 15 недель, сравнивая эти прогнозы с набором тестов:
predictions=pd.DataFrame(Arima_model.predict(n_periods=15), index=test_df) predictions=np.array(predictions)
Перед сравнением прогнозов со значениями из тестового набора прогнозы изменяют форму, чтобы они были в том же формате, что и тестовый набор:
>>> predictions=predictions.reshape(15,-1) >>> predictions array([[ 88.0971519 ], [103.18056307], [117.93678827], [121.38546969], [112.9812769 ], [120.69309927], [144.4014371 ], [166.36546077], [181.69684755], [190.12507961], [204.36831063], [218.85150166], [216.59090879], [197.74194692], [156.98273524]])
Теперь тестовые значения можно сравнить с прогнозами на основе среднеквадратичной ошибки (RMSE) - меньшее значение указывает на меньшую ошибку.
>>> mse = mean_squared_error(test_df, predictions) >>> rmse = math.sqrt(mse) >>> print('RMSE: %f' % rmse) RMSE: 10.093574 >>> np.mean(test_df) 160.492142162915
Получено среднеквадратичное значение 10 по сравнению со средним значением 160. Это представляет ошибку чуть более 6% от среднего, что указывает на то, что модель предсказывает тенденции ADR с довольно высокой точностью.
Вот график прогнозируемых и фактических значений.
Вывод
Большое спасибо за ваше время, и мы будем благодарны за любые вопросы или отзывы.
Вы можете найти Jupyter Notebook для этого примера здесь.
Заявление об ограничении ответственности: эта статья написана на условиях «как есть» без каких-либо гарантий. Он был написан с целью предоставить обзор концепций науки о данных и не должен интерпретироваться как какой-либо профессиональный совет. Автор не имеет отношения к третьим лицам, упомянутым в этой статье.