Краткое введение, за которым следует реализация

Источник: freestockcharts.com

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

Теория

Один из лучших способов познакомиться с моделью — понять, почему мы ее используем, особенно когда существуют другие эффективные модели регрессии, такие как линейная регрессия или многомерная регрессия. Почему для прогнозирования временных рядов мы предпочитаем модель ARIMA? Большинство данных временных рядов, доступных в Интернете, сосредоточены на зависимой переменной и на том, как зависимая переменная изменяется со временем. Для таких моделей, как линейная регрессия, нам нужны независимые переменные, чтобы отображать функцию от зависимых переменных к зависимым переменным для прогнозирования. Однако это не всегда возможно, потому что:

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

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

Чтобы лучше понять эту модель, давайте разобьем ее на 2 части, а затем объединим эти 2 части в конце.

AR или модель авторегрессии

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

Yₜ = α + β₁Yₜ − 1 + β₂Yₜ − 2 + ⋯ + βₚYₜ − p + ϵ₁

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

Модель скользящего среднего

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

Yₜ = α + ϵₜ + ϕ₁ ϵₜ ₋ ₁ + ϕ₂ ϵₜ ₋ ₂ + ⋯ + ϕᵩ ϵₜ ₋ ᵩ

Но что означает ϵ? Проще говоря, это ошибка или разница между фактическим значением и прогнозируемым значением.

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

Теперь, когда вы поняли модель авторегрессии и модель скользящих средних, пришло время узнать о ARIMA. Когда условия авторегрессии и условия скользящего среднего объединяются вместе с разницей, чтобы сделать временной ряд стационарным (подробнее об этом позже), мы получаем модель ARIMA! Поскольку уравнение является регрессивным по своей природе, мы можем найти соответствующие веса слагаемых в уравнении, используя методы регрессии.

Yₜ = α + β₁Yₜ ₋ ₁ + β₂Yₜ ₋ ₂ + ⋯ + βₚYₜ ₋ ₚ + ϕ₁ ϵₜ ₋ ₁ + ϕ₂ ϵₜ ₋ ₂ + ⋯ + ϕᵩ ϵₜ ₋ ᵩ

На данный момент мы поняли основную интуицию, лежащую в основе модели ARIMA. Давайте копнем немного глубже и разберемся с параметрами модели ARIMA.

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

[ 1 , 3 , 5 , 4 ]

Теперь, когда мы различаем список, мы вычитаем значение nᵗʰ ряда из (n-1)ᵗʰ значения ряда. Для лучшего понимания:

После первой разности:

[ 3 – 1 , 5 – 3 , 4 – 5 ]= [ 2 , 2 , −1 ]

После второй разности:

[ 2 – 2 , −1 – 2 ] = [ 0, −3 ][ 2 – 2 , −1 – 2 ] = [ 0 , −3 ]

Причина, по которой мы различаем временные ряды, состоит в том, чтобы сделать временные ряды стационарными, т. е. среднее значение и дисперсия временных рядов остаются постоянными/стабильными во времени, что позволяет нам уменьшить такие компоненты, как тренд и сезонность (показано ниже). Это важно, потому что ARIMA ожидает, что временной ряд будет стационарным. Таким образом, мы продолжаем различать временной ряд, пока он не станет стационарным.

Теперь, когда мы поняли все основные концепции, которые будем использовать, давайте узнаем, как найти эти параметры и погрузимся прямо в код!

Для начала давайте начнем с некоторых основных импортов.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as smplt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
plt.rcParams['text.color'] = 'k'from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
% matplotlib inline

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

aus1 = pd.read_csv( "a.us.txt" , sep = ',' , index_col = 0, parse_dates = True, squeeze = True )aus1.head()

Источник: Автор

aus1.describe()

Источник: Автор

aus1.indexDatetimeIndex(['1999-11-18','1999-11-19','1999-11-22','1999-11-23',
               '1999-11-24','1999-11-26','1999-11-29','1999-11-30',
               '1999-12-01','1999-12-02',
               ...
               '2017-10-30','2017-10-31','2017-11-01','2017-11-02',
               '2017-11-03','2017-11-06','2017-11-07','2017-11-08',
               '2017-11-09','2017-11-10'], 
     dtype = 'datetime64[ns]', name='Date', length=4521, freq=None )

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

y1 = aus1['Open'].resample('MS').mean()
y2 = aus1['Close'].resample('MS').mean()
y1.index
DatetimeIndex(['1999-11-01','1999-12-01','2000-01-01','2000-02-01',
               '2000-03-01','2000-04-01','2000-05-01','2000-06-01',
               '2000-07-01', '2000-08-01',
               ...
               '2017-02-01','2017-03-01','2017-04-01', '2017-05-01',
               '2017-06-01','2017-07-01','2017-08-01','2017-09-01',
               '2017-10-01','2017-11-01'],
        dtype='datetime64[ns]', name='Date', length=217, freq='MS' )

Пока все хорошо! Давайте построим временной ряд и посмотрим, как он выглядит!

y1.plot(figsize=(15, 6))
plt.show()

Источник: Автор

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

from pylab import rcParams
rcParams[‘figure.figsize’] = 18, 8
decomposition = sm.tsa.seasonal_decompose(y1, model=’additive’)
fig = decomposition.plot()
plt.show()

Источник: Автор

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

Если вы помните, мы обсуждали три параметра модели ARIMA. Чтобы определить эти 3 параметра и найти наилучшую комбинацию этих 3 параметров для получения наилучших результатов, мы будем использовать комбинацию статистических инструментов и итерации (испытывая различные модели, чтобы проверить, какая из них дает наилучшие результаты).

Начнем с определения d. Как мы упоминали ранее, мы будем различать временные ряды, пока они не станут стационарными. Давайте попробуем разность его один раз и используем расширенный тест Дики-Фуллера, чтобы определить, является ли он стационарным или нет.

from statsmodels.tsa.stattools import adfuller
from numpy import log
y1_d = y1.diff()
y1_d = y1_d.dropna()
result = adfuller(y1_d)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])ADF Statistic: -2.955284
p-value: 0.039287

Поскольку мы видим, что полученное значение p меньше 0,05, мы можем отвергнуть нулевую гипотезу и сказать, что ряд является стационарным. Мы также можем видеть, что серия стала более стационарной по сравнению с графиком выше. Таким образом, получение значенияppменее 0,05 с использованием ADF является хорошим показателем того, что наш временной ряд стал стационарным.

y1_d.plot(figsize=(15, 6))
plt.show()

Источник: Автор

Чтобы определить p, нам нужно сначала понять, что такое график ACF. График функции автокорреляции или график ACF показывает, насколько переменная коррелирует с ее предыдущими временными шагами. Например, прогнозируя цены акций, график ACF пытается показать, насколько цены акций в марте коррелируют с ценами акций в феврале, насколько вероятно, что цены акций в марте будут следовать за поведением цен акций в феврале. Чтобы лучше понять это, давайте построим это.

from statsmodels.graphics.tsaplots import plot_acf,plot_pacfplot_acf(y1_d,lags=10)

Источник: Автор

Источник: Автор

Мы видим, что автокорреляция сильна в течение первых двух лагов, а затем затухает и колеблется в синей области.

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

Давайте попробуем определить q сейчас. Процесс определения q очень похож на процесс определения p. Вместо ACF теперь мы будем использовать PACF или функции частичной автокорреляции. График PACF показывает, насколько переменная коррелирует сама с собой на предыдущем временном шаге, игнорируя все линейные зависимости, которые она имеет на временных шагах, лежащих между временным шагом, относительно которого должна быть найдена корреляция, и текущий временной шаг. Также называемая функция условной корреляции, PACF предназначена для поиска корреляции между двумя временными шагами независимо от всех других временных шагов между ними. Давайте лучше разберемся с сюжетом.

plot_pacf(y1_d,lags=10)

Источник: Автор

Источник: Автор

Из графика видно, что график обрывается до нуля при второй задержке, поэтому мы можем оценить, что значение q будет меньше 2.
Таким образом, мы можем сказать, что значение q должно лежать в диапазоне от 0 до 1.

Вы наконец-то изучили необходимые строительные блоки, необходимые для создания модели ARIMA для прогнозирования временных рядов! Давайте сразу приступим!

Мы разделяем наши временные рамки на тренировочный и тестовый набор, чтобы позже мы могли оценить, насколько хорошо работает наша модель. Обучающие данные составляют 70 % исходных данных временных рядов, а данные тестирования — 30 % исходных данных временных рядов.

size = int(len(y1) * 0.7)
train, test = y1[0:size], y1[size:len(y1)]
series = [y1 for y1 in train]
predictions = []

Хорошо, теперь давайте начнем обучение модели! Давайте попробуем использовать значения (p,d,q)равно (2,1,1) и посмотрим, как работает модель!

for y in range(len(test)):
    arima_model = ARIMA(series, order=(2,1,1))
    model_fit = arima_model.fit(disp=0)
    preds = model_fit.forecast()
    pred = preds[0]
    predictions.append(pred)
    actual_val = test[y]
    series.append(actual_val)
error = mean_squared_error(test, predictions)
print('Test error is {}'.format(error))
plt.plot(predictions,'r')
plt.plot(np.array(test))

Выполнение кода:

Test error is 3.273019781729989
[<matplotlib.lines.Line2D at 0x1d39598f668>]

Источник: Автор

Мы видим, что модель изучила природу и поведение временных рядов и довольно хорошо работает на тестовом наборе!

Давайте попробуем новые значения (p,d,q). Давайте на этот раз попробуем (1,1,1) и посмотрим, сможем ли мы добиться лучших результатов.

size = int(len(y1) * 0.7)
train, test = y1[0:size], y1[size:len(y1)]
series = [y1 for y1 in train]
predictions = []for y in range(len(test)):
    arima_model = ARIMA(series, order=(1,1,1)) 
    model_fit = arima_model.fit(disp=0)
    preds = model_fit.forecast()
    pred = preds[0]
    predictions.append(pred)
    actual_val = test[y]
    series.append(actual_val)
error = mean_squared_error(test, predictions)
print('Test error is {}'.format(error))
plt.plot(predictions,'r')
plt.plot(np.array(test))

Выполнение кода:

Test error is 2.355571525013936
[<matplotlib.lines.Line2D at 0x1d3959f32b0>]

Отлично, мы получили лучшие результаты, изменив параметры модели! Используя описанные выше статистические методы и пробуя разные значения, вы можете добиться отличных результатов на разных временных рядах.

Надеюсь, теперь вы знакомы с различными концепциями прогнозирования временных рядов и модели ARIMA!

Вы можете получить блокнот jupyter, соответствующий этому блогу, здесь.

Джинит Сангхви — усердный и любознательный человек, он изучает компьютерную инженерию в Инженерном колледже Пуны.

Проявив интерес к таким областям, как машинное обучение, наука о данных и глубокое обучение, еще на первом курсе, с тех пор он прошел стажировку в известных институтах и ​​компаниях, таких как Национальный университет Сингапура, Hewlett Packard Enterprises, AISeon Healthcare Technologies и т. д. Он также имеет опыт работы разработчиком и совсем недавно прошел стажировку в Goldman Sachs, где после выпуска он присоединится к нам в качестве штатного аналитика. Наряду с этим, он также является опытным участником парламентских дебатов и страстным гитаристом.

Свяжитесь с ним здесь: [email protected]