Разве не прекрасно быть программистом? Вы можете иметь возможность знать будущее или, по крайней мере, быть как можно ближе к его знанию.

Введение

В предыдущей части этого курса мы заложили хорошую основу для построения модели, которая может прогнозировать для нас некоторые будущие ценности. И это именно то, что мы будем делать в этой части.

Первое, что нам нужно, — это некоторые данные временных рядов, которые будут использоваться для нашего прогноза. Есть много мест, таких как Kaggle или Datahub.io, где вы можете найти свой набор данных, однако для этого курса я решил сгенерировать свои собственные данные.

Генерация временных рядов:

Создание набора данных временных рядов — наш первый шаг. Для иллюстрации я решил смоделировать данные о продажах мороженого. Как и ожидалось, продажи имеют тенденцию расти летом и снижаться в другие сезоны из-за особенностей продукта.

Итак, вот как выглядят наши данные (рис. 1.0), а также код, сгенерировавший эти данные:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Set random seed for reproducibility
np.random.seed(14)

# Define the number of data points
num_years = 5
num_months = 12
num_points = num_years * num_months

# Generate time values (months)
time = pd.date_range(start='2017-01-01', periods=num_points, freq='M')

# Create a base trend with some noise
trend = np.linspace(50, 150, num_points) + np.random.normal(0, 20, num_points)

# Generate seasonality values
seasonality_first_last = np.random.uniform(0, 0.5, size=4)
seasonality_middle = np.random.uniform(2, 3, size=num_months - 8)
seasonality = np.concatenate((seasonality_first_last, seasonality_middle, seasonality_first_last))

# Repeat the seasonality pattern for each year
seasonality = np.tile(seasonality, num_years)

# Combine trend, seasonality, and noise to get the final data
ice_cream_sales = trend * seasonality + np.random.normal(0, 20, num_points)


data = pd.DataFrame({'Date': time, 'IceCreamSales': ice_cream_sales})

Сезонность играет большую роль в построении этих данных, как вы можете видеть выше, я установил коэффициенты сезонности для первых 4 и последних 4 месяцев низкими и высокими для летних месяцев.

Вот еще один пример того, что такое сезонность (рис. 1.1), на случай, если вы читали предыдущую часть с закрытыми глазами.

Модели прогнозирования временных рядов

Сначала я собираюсь объяснить вам две отдельные модели прогнозирования. Затем, как только мы справимся с этим, мы объединим их, чтобы сделать что-то более интересное.

AR (авторегрессивная) модель

Так что же такое авторегрессионная модель? Ну, в его названии есть регрессия, поэтому мы можем рассчитывать на предсказание чего-то на основе чего-то. Но модели авторегрессии основаны на том принципе, что текущие ценности каким-то образом находятся под влиянием прошлых ценностей.

Мы назовем нашу модель AR(p), где p — это порядок или количество отметок времени, которые мы хотим перенести в прошлое. Итак, AR(1) прогнозирует на основе одной отметки времени в прошлом, AR(2) — на основе 2 и так далее…

Итак, модель AR(p) определяется как:

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

И как нам определить, какие данные следует использовать, а какие нет? В первой части мы узнали о PACF, это поможет нам определить, какие данные следует использовать.

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
pacf_plot = plot_pacf(data['IceCreamSales'], lags=13)

Итак, взглянув на рисунок 1.2, мы видим, что значения за первые 3 месяца, а также за 6, 7, 9 и 12 месяцы имеют некоторую корреляцию с текущим значением.

Подгонка модели

Давайте сначала взглянем на AR(3) и посмотрим, какой прогноз мы получим.

import statsmodels.api as sm
model = sm.tsa.arima.ARIMA(train_data, order=(3,0,0))
fit_model = model.fit()

Если вам интересно, почему функция называется ARIMA и почему порядок второго аргумента = (3, 0, 0), я бы посоветовал не беспокоиться об этом прямо сейчас. Об этом мы поговорим в одной из будущих частей.

Теперь, когда наша модель соответствует нашим данным, мы можем проверить сводку.

print(fit_model.summary())

На рисунке 1.3 в красном поле мы видим столбец P › |z|, который сообщает нам о влиянии задержки (зеленый прямоугольник) на наше текущее значение. Чем ближе это значение к 0 (‹0,05), тем лучше.

Получаем наши прогнозы:

pred_start_date = test_data.index[0]
pred_end_date = test_data.index[-1]
predictions = fit_model.predict(start=pred_start_date, end=pred_end_date)
residuals = test_data - predictions

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

Теперь вы можете спросить, как нам найти модель, которая лучше всего соответствует нашим данным. Существуют методы, которые можно использовать для "оценки" нашей модели. Так что теперь будем увеличивать количество лагов и посмотрим, что получится.

На рисунке выше мы можем видеть, как прогнозы нашей модели меняются с увеличением лагов.

Для измерения производительности каждой модели мы используем AIC (информационный критерий Акаике). Чем ниже AIC, тем лучше модель.

На рисунке 1.6 мы видим, что порядок 9 имеет самый низкий AIC, что означает, что модель AR (9) лучше всего соответствует нашим данным.

Мы также можем использовать RMSE (среднеквадратическую ошибку), чтобы увидеть, насколько мы ошиблись в наших прогнозах.

Этот график RMSE также показывает нам, что модель AR (9) была наименее ошибочной при прогнозировании.

Заключение

В этой части нашего путешествия по прогнозированию временных рядов мы углубились в увлекательный мир моделей авторегрессии (AR). Мы научились генерировать данные временных рядов, включая важную роль, которую сезонность играет в формировании наших наборов данных. Мы также изучили основы моделей AR, понимая, что они используют влияние прошлых ценностей для прогнозирования будущего.

Итак, следите за обновлениями для следующей части, где мы обсудим модель MA. Если вас интересует код, используемый для целей этого блога, нажмите здесь.

Спасибо за чтение, и я с нетерпением жду возможности поделиться с вами новыми знаниями в следующих публикациях.