рекомендации

воскресенье, 28 июня 2020 г.

Введение в обработку нестационарных временных рядов в Python


Введение

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

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


Но временные ряды - сложная тема с несколькими аспектами в игре одновременно.

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

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

1. Введение в стационарность

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

Позвольте нам пояснить это на интуитивном примере. Рассмотрим три графика, показанные ниже:



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

Три примера, показанные выше, представляют нестационарные временные ряды. Теперь посмотрим на четвертый график:


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

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

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

2. Загрузка данных

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

Прежде чем мы продолжим анализировать наш набор данных, давайте сначала загрузим и предварительно обработаем данные.
#загрузка необходимых библиотек
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

#чтение набора данных
train = pd.read_csv('AirPassengers.csv')

#препроцессинг
train.timestamp = pd.to_datetime(train.Month , format = '%Y-%m')
train.index = train.timestamp
train.drop('Month',axis = 1, inplace = True)

#посмотрим на несколько первых строк
#train.head()
#Passengers    Month
1949-01-01 112
1949-02-01 118
1949-03-01 132
1949-04-01 129
1949-05-01 121

Похоже, мы готовы двигаться дальше!

3. Методы проверки стационарности

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

Визуальный тест

Рассмотрим графики, которые мы использовали в предыдущем разделе. Мы смогли определить ряд, в котором среднее значение и дисперсия менялись со временем, просто взглянув на каждый график. Точно так же мы можем построить график для наших данных и определить, изменяются ли свойства ряда со временем или нет.
train['#Passengers'].plot()


Хотя совершенно очевидно, что у нас есть тренд (различное среднее) в вышеприведенных рядах, этот визуальный подход не всегда дает точные результаты. Лучше подтвердить наблюдения, используя некоторые статистические тесты.

Статистический тест

Вместо того, чтобы проводить визуальный тест, мы можем использовать статистические тесты, такие как тесты на единичные корни (Unit root test). Единичный корень указывает на то, что статистические свойства данного ряда не постоянны во времени, что является условием для стационарных временных рядов. Вот математическое объяснение:

Предположим, у нас есть временной ряд:


где yt - значение в момент времени t, а ε t - член ошибки. Чтобы вычислить yt, нам нужно значение yt-1, а именно:


Если мы сделаем это для всех наблюдений, значение yt будет:


Если значение a в приведенном выше уравнении равно 1 (единице) , то прогнозы будут равны yt-n и сумме всех ошибок от t-n до t, что означает, что дисперсия будет увеличиваться со временем. Эта концепция известна как единичный корень во временном ряду. Мы знаем, что для стационарного временного ряда дисперсия не должна быть функцией времени. Тесты на единичный корень проверяют наличие единичного корня в ряду, проверяя, имеет ли a значение a = 1. Ниже приведены два наиболее часто используемых теста на единичные корни:

Расширенный тест Дики — Фуллера ADF (Augmented Dickey Fuller)

Тест Дики Фуллера - один из самых популярных статистических тестов. Его можно использовать для определения наличия единичного корня в ряду и, следовательно, помочь нам понять, является ли ряд стационарным или нет. Нулевой и альтернативной гипотезой этого теста являются:

Нулевая гипотеза: ряд имеет единичный корень (значение a = 1)

Альтернативная гипотеза: ряд не имеет единичного корня.

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

Код Python:
# Определяем функцию для теста ADF
from statsmodels.tsa.stattools import adfuller
def adf_test(timeseries):
    # Выполняем тест Дики-Фуллера:
    print ('Results of Dickey-Fuller Test:')
    dftest = adfuller(timeseries, autolag='AIC')
    dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
    for key,value in dftest[4].items():
       dfoutput['Critical Value (%s)'%key] = value
    print (dfoutput)

# применяем к ряду тест adf 
adf_test(train['#Passengers'])
Результаты теста ADF: тесты ADF выводят следующие результаты - статистика теста, значение p и критическое значение с доверительными интервалами 1%, 5% и 10%. Результаты нашего теста для этого конкретного ряда:
Results of Dickey-Fuller Test:
Test Statistic                   0.815369
p-value                          0.991880
#Lags Used                      13.000000
Number of Observations Used    130.000000
Critical Value (1%)             -3.481682
Critical Value (5%)             -2.884042
Critical Value (10%)            -2.578770
dtype: float64
Тест на стационарность: если тестовая статистика меньше критического значения, мы можем отвергнуть нулевую гипотезу (то есть ряд является стационарным). Когда статистика теста больше критического значения, мы не можем отклонить нулевую гипотезу (что означает, что ряд не является стационарным).

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

2 . Тест KPSS (Kwiatkowski-Phillips-Schmidt-Shin) 

KPSS - это еще один тест для проверки стационарности временного ряда (чуть менее популярный, чем тест Дики Фуллера). Нулевая и альтернативная гипотеза для теста KPSS противоположны гипотезе ADF, что часто создает путаницу.

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

Нулевая гипотеза: стационарный процесс тренда.

Альтернативная гипотеза: ряд имеет единичный корень (ряд не является стационарным).

Код Python:
# определяем функцию для теста kpss
from statsmodels.tsa.stattools import kpss
# определяем KPSS
def kpss_test(timeseries):
    print ('Results of KPSS Test:')
    kpsstest = kpss(timeseries, regression='c')
    kpss_output = pd.Series(kpsstest[0:3], index=['Test Statistic','p-value','Lags Used'])
    for key,value in kpsstest[3].items():
    kpss_output['Critical Value (%s)'%key] = value
print (kpss_output)
Результаты теста KPSS: ниже приведены результаты теста KPSS - статистика теста, p-value и критическое значение с доверительными интервалами 1%, 2,5%, 5% и 10%. Для набора данных passengers получены следующие результаты:
Results of KPSS Test:
Test Statistic            1.052175
p-value                   0.010000
Lags Used                14.000000
Critical Value (10%)      0.347000
Critical Value (5%)       0.463000
Critical Value (2.5%)     0.574000
Critical Value (1%)       0.739000
dtype: float64
Тест на стационарность: если статистика теста больше критического значения, мы отвергаем нулевую гипотезу (ряд не является стационарным). Если статистика теста меньше критического значения, не удастся отклонить нулевую гипотезу (ряд является стационарным). Что касается данных air passenger, значение тестовой статистики превышает критическое значение во всех доверительных интервалах, и, следовательно, мы можем сказать, что ряд не является стационарным.

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

Итак, в целом, тест ADF имеет альтернативную гипотезу линейной или разностной стационарности, в то время как тест KPSS идентифицирует стационарность по тренду в ряду.

3. Типы стационарности

Давайте разберемся с различными типами стационарности и как интерпретировать результаты вышеупомянутых тестов.
  • Строго стационарный: строгий стационарный ряд удовлетворяет математическому определению стационарного процесса. Для строгого стационарного ряда среднее значение, дисперсия и ковариация не являются функцией времени. Цель состоит в том, чтобы преобразовать нестационарный ряд в строгий стационарный ряд для прогнозирования.
  • Стационарный тренд: ряд, который не имеет единичного корня, но демонстрирует тренд, называется стационарным рядом тренда. После удаления трендовой составляющей, результирующий ряд будет строго стационарным. Тест KPSS классифицирует ряд как стационарный при отсутствии единичного корня. Это означает, что ряд может быть строго стационарным или стационарным по тренду.
  • Разностно-стационарный: временной ряд, который можно сделать строгим стационарным с помощью разностей, попадает в категорию разностно-стационарных. Тест ADF также известен как тест разностной стационарности.

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

Случай 1: Оба теста показывают, что ряд не является стационарным -> ряд не является стационарным.
Случай 2: Оба теста показывают, что ряд является стационарным -> ряд является стационарным
Случай 3: KPSS = стационарный и ADF = не стационарный -> стационарный тред, удалить тренд, чтобы сделать ряд строго стационарным.
Случай 4: KPSS = не стационарный и ADF = стационарный -> разностно-стационарный, используйте разности, чтобы сделать ряд стационарным.

4. Преобразование временного ряда в стационарный

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

Разности

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


где yt - значение в момент времени t

Применение разностей в нашем ряду и отображение результатов:
train['#Passengers_diff'] = train['#Passengers'] - train['#Passengers'].shift(1)
train['#Passengers_diff'].dropna().plot()


Сезонные разности

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


train['#Passengers_diff'] = train['#Passengers'] - train['#Passengers'].shift(1)
train['#Passengers_diff'].dropna().plot()

Преобразование

Преобразования используются для стабилизации непостоянной дисперсии ряда. Общие методы преобразования включают степенное преобразование, квадратный корень и логарифмическое преобразование. Давайте сделаем быстрое логарифмическое преобразование и разность в нашем наборе данных air passenger:
train['#Passengers_log'] = np.log(train['#Passengers'])
train['#Passengers_log_diff'] = train['#Passengers_log'] - train['#Passengers_log'].shift(1)
train['#Passengers_log_diff'].dropna().plot()

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

Заключение

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

Комментариев нет:

Отправить комментарий