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

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

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

Здесь нет универсального подхода. Нам не нужно постоянно подгонять традиционные методы временных рядов, такие как ARIMA (я говорю по опыту!). Будут проекты, такие как прогнозирование спроса или прогнозирование кликов, когда вам нужно будет полагаться на алгоритмы контролируемого обучения.

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

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

Оглавление

  1. Краткое введение в временные ряды
  2. Настройка постановки задачи для данных временных рядов
  3. Функции, связанные с датой
  4. Функции, связанные со временем
  5. Особенности отставания
  6. Подвижное окно
  7. Расширяющееся окно
  8. Зависит от домена

Краткое введение в временные ряды

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

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

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

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

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

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

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

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

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

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

Загрузим набор данных в нашу записную книжку:

import pandas as pd                       
data = pd.read_csv('Train_SU63ISt.csv')                       data.dtypes

У нас есть два столбца, так что это однозначно одномерный временной ряд. Кроме того, тип данных переменной даты воспринимается как объект, т.е. он обрабатывается как категориальная переменная. Следовательно, нам нужно будет преобразовать это в переменную DateTime. Мы можем сделать это, используя функцию datetime с соответствующим названием в pandas:

import pandas as pd                       
data = pd.read_csv('Train_SU63ISt.csv')                       data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')                       
data.dtypes

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

ПРИМЕЧАНИЕ. Я взял простую задачу временных рядов, чтобы продемонстрировать в этой статье различные методы разработки функций. Вы можете использовать их в любом наборе данных, если присутствует столбец даты и времени.

Разработка функций для временных рядов # 1: функции, связанные с датой

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

Вернемся к нашему проекту JetRail.

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

Извлечь эти функции в Python очень просто:

import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')

data['year']=data['Datetime'].dt.year 
data['month']=data['Datetime'].dt.month 
data['day']=data['Datetime'].dt.day

data['dayofweek_num']=data['Datetime'].dt.dayofweek  
data['dayofweek_name']=data['Datetime'].dt.weekday_name

data.head()

Разработка функций для временных рядов # 2: функции, основанные на времени

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

Если нам удастся извлечь «час» из отметки времени, мы сможем сделать более глубокие выводы о данных. Мы могли узнать, выше ли посещаемость JetRail утром, днем ​​или вечером. Или мы могли бы использовать это значение для определения среднего почасового трафика в течение недели, то есть количества людей, которые использовали JetRail между 9–10 утра, 10–11 утра и так далее (в течение недели).

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

import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')

data['Hour'] = data['Datetime'].dt.hour 
data['minute'] = data['Datetime'].dt.minute 

data.head()

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

Разработка функций для временных рядов № 3: функции с запаздыванием

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

Учтите это - вы прогнозируете курс акций компании. Итак, для прогнозов важна цена акций предыдущего дня, верно? Другими словами, значение в момент времени t сильно зависит от значения в момент времени t-1. Прошлые значения называются лагами, поэтому t-1 - это задержка 1, t-2 - задержка 2 и т. Д.

import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')

data['lag_1'] = data['Count'].shift(1)
data = data[['Datetime', 'lag_1', 'Count']]
data.head()

Здесь мы смогли создать одну функцию задержки для нашей серии. Но почему отстают? Почему не пять или семь? Это хороший вопрос.

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

Если у ряда есть недельный тренд, что означает, что значение в прошлый понедельник можно использовать для прогнозирования значения для этого понедельника, вам следует создать характеристики лага на семь дней. Уловили дрейф?

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

import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')

data['lag_1'] = data['Count'].shift(1)
data['lag_2'] = data['Count'].shift(2)
data['lag_3'] = data['Count'].shift(3)
data['lag_4'] = data['Count'].shift(4)
data['lag_5'] = data['Count'].shift(5)
data['lag_6'] = data['Count'].shift(6)
data['lag_7'] = data['Count'].shift(7)

data = data[['Datetime', 'lag_1', 'lag_2', 'lag_3', 'lag_4', 'lag_5', 'lag_6', 'lag_7', 'Count']]
data.head(10)

Существует несколько способов определения задержки, при которой корреляция значима. Например, мы можем использовать графики ACF (функция автокорреляции) и PACF (функция частичной автокорреляции).

  • ACF: график ACF - это мера корреляции между временным рядом и самой лаговой версией.
  • PACF: график PACF - это мера корреляции между временными рядами с запаздывающей версией самого себя, но после устранения вариаций, уже объясненных промежуточными сравнениями.

Для нашего конкретного примера, вот графики ACF и PACF:

from statsmodels.graphics.tsaplots import plot_acf plot_acf(data['Count'], lags=10) plot_pacf(data['Count'], lags=10)

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

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

Разработка функций для временных рядов # 4: функция скользящего окна

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

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

Вот потрясающая гифка, которая удивительно интуитивно объясняет эту идею:

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

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

import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')

data['rolling_mean'] = data['Count'].rolling(window=7).mean()
data = data[['Datetime', 'rolling_mean', 'Count']]
data.head(10)

Точно так же вы можете рассматривать сумму, минимальное, максимальное значение и т. Д. (Для выбранного окна) как функцию и опробовать ее на своем собственном компьютере.

Давность в важном факторе временного ряда. Значения, близкие к текущей дате, содержат больше информации.

Таким образом, мы можем использовать средневзвешенное, чтобы самым последним наблюдениям присваивались более высокие веса. Математически средневзвешенное значение в время t для последних 7 значений будет:

w_avg = w1 * (t-1) + w2 * (t-2) +. . . . + w7 * (т-7)

где, w1 ›w2› w3 ›. . . . ›W7.

Разработка функций для временных рядов # 5: функция расширения окна

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

Идея функции расширения окна заключается в том, что она учитывает все прошлые значения.

Вот гифка, которая объясняет, как работает наша функция раскрытия окна:

Как видите, с каждым шагом размер окна увеличивается на единицу, поскольку он учитывает каждое новое значение в ряду. Это можно легко реализовать в Python с помощью функции expanding (). Давайте запрограммируем это, используя те же данные:

import pandas as pd
data = pd.read_csv('Train_SU63ISt.csv')
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M')

data['expanding_mean'] = data['Count'].expanding(2).mean()
data = data[['Datetime','Count', 'expanding_mean']]
data.head(10)

Разработка функций для временных рядов # 6: особенности, специфичные для предметной области

В этом суть разработки функций!

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

Хотите погрузиться в это подробнее? Возьмем пример.

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

Но подожди. Позвольте мне задать вам вопрос - будет ли это правильным способом построения функций задержки от lag (1) до lag (7) во всех данных?

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

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

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

Методика проверки временных рядов

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

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

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

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

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

import pandas as pd 
data = pd.read_csv('Train_SU63ISt.csv') 
data['Datetime'] = pd.to_datetime(data['Datetime'],format='%d-%m-%Y %H:%M') 
data['Datetime'].min(), data['Datetime'].max(), (data['Datetime'].max() -data['Datetime'].min())
(Timestamp('2012-08-25 00:00:00'), Timestamp('2014-09-25 23:00:00'), Timedelta('761 days 23:00:00'))

У нас есть данные за почти 25 месяцев. Давайте сэкономим три месяца на валидацию и используем оставшиеся для обучения:

data.index = data.Datetime Train=data.loc['2012-08-25':'2014-06-24'] valid=data.loc['2014-06-25':'2014-09-25'] 
Train.shape, valid.shape
((16056, 3), (2232, 3))

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

Конечные заметки

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

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

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

А если вы новичок в мире временных рядов, вот отличный (и бесплатный) курс, который поможет вам начать: Создание прогноза временных рядов с использованием Python.

Первоначально опубликовано на https://www.analyticsvidhya.com 9 декабря 2019 г.