Введение

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

В этом блоге мы увидим три разных способа:
- Наивный подход
- Подход Машинное обучение
- Глубокое обучение

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

Вы можете проверить весь код в этом github:
https://github.com/Hugodeladriere/BIKE-DEMAND-PROCASTING---TIME-SERIES

Давайте посмотрим, что происходит с нашими данными

Скачать все файлы можно здесь. (https://www.dropbox.com/s/ic8m0b3mf5wxk4r/challenge.zip?dl=0)

У нас есть 3 набора данных:

  • Станция
  • Погода
  • Координация

Набор данных станции представляет целевую переменную (здесь велосипеды):

На графике выше видно, что в среднем на станции доступно около 5 велосипедов. Наиболее частый спрос возникает утром и днем.

Набор данных о погоде:

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

Посмотрим, что внутри:

На графике выше видно, чтопри температуре от 10 до 20 градусов спрос на велосипеды очень важен. И чем больше ветра, тем меньше спрос.

Очистка данных

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

def clean_data(df):
  df=df.set_index(‘datetime’)
  df = df.resample(‘30min’).mean()
  df = df.reset_index()
  return df

Особенности инжиниринга

Особенности отставания от цели:

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

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

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

Если ряд имеет недельный тренд, что означает, что значение в прошлый понедельник можно использовать для прогнозирования значения на этот понедельник, вам следует создать признаки задержки на семь дней.
Хорошо, поэтому в конце мы хотим узнать велосипедный спрос непосредственно перед (лаг_1) и недельный спрос (лаг_7).

def create_lag(df):
  df[‘lag_30m’]= df[‘bikes’].shift(1)
  df[‘lag_7j’]=df[‘bikes’].shift(2*24*7)
  return df

Тот факт, что DataFrame выбирается из фиксированного времени, очень легко создавать задержки. Но есть еще кое-какая работа, мы должны заполнить все значения NaN.
Это очень просто, просто fiilna() с предыдущим значением, если оно есть, если нет, fillna() с следующее значение.

Особенности по погоде:

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

Окончательный кадр данных

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

Матрица корреляции:

Матрица корреляции показывает нам корреляцию между двумя переменными.

Через матрицу мы видим, что переменные «lag_nuageux» и «lag_pluie» коррелируют, и это может вводить в заблуждение и снижать оценку нашей модели.

Метрика MAE и MAPE для сравнения наших моделей

Средняя абсолютная ошибка (MAE) — это мера ошибок между парными наблюдениями, отражающими одно и то же явление.
Средняя абсолютная ошибка в процентах (MAPE) является производным от MAE, но измеряет ошибку процентного расхода между двумя парами.

Наивный подход

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

Оценка рассчитывается по 168 значениям:
- MAE составляет ошибку 1,3
- MAPE составляет ошибку 11,2%

Машинное обучение

Подход LightGBM:

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

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

Гиперпараметры, которые мы используем в этой модели:
- "объективный": "tweedie"
- "показатель": "mae
- "sub_feature": 0.5,
- 'num_leaves': 262,
- 'min_data': 64,
- 'num_iterations': 2500,
- 'max_depth': 8

После 2500 итераций и ранней_остановки мы можем предсказать спрос на наш велосипед:

Оценка рассчитывается на основе 5000 значений:
- MAE – ошибка 1,6 
 – MAPE – ошибка 2,4 %

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

Подход Арима:

Arima означает авторегрессионное интегрированное скользящее среднее (AR-I-MA). Это модель, которая легко понимает данные временных рядов и дает достойные результаты без каких-либо особенностей.

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

В этом методе учитываются три переменные (p, d, q), связанные с (AR-I-MA):
- p: период задержки. Если P = 1, он будет использовать 1 предыдущее значение нашего временного ряда для измерения авторегрессионной части расчета.
- d : при преобразовании данных в стационарный временной ряд с использованием разности (Zt = A_t+1 - A_t, где Zt — стационарный ряд, At — нестационарный ряд). D относится к числу разностных преобразований, необходимых временным рядам для получения стационарного состояния
- q : переменная позволяет алгоритму понять ошибки запаздывания, которые не объясняются тенденцией или сезонностью.

Когда вы поймете все переменные и стационарную теорию, вы сможете построить свою модель ARIMA.

Модель ARIMA с сезонностью и экзогенной переменной, SARIMAX:
SARIMAX – это более совершенная версия ARIMA, включающая параметр для сезонности и позволяющая использовать данные о признаках в модели. Это модель, которую мы используем для прогнозирования спроса на велосипеды.

Результаты (3 часа вычислений)

Оценка рассчитывается по 5000 значений:
- Оценка MAE составляет 1,7
- Оценка MAPE составляет 2,5%

подход CNN

Спасибо этому веб-сайту за современный подход к CNN временных рядов от Jason Brownlee.

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

Для классификации изображений были разработаны модели Сверточной нейронной сети (CNN), в которых модель принимает двумерные входные данные, представляющие пиксели изображения и цветовые каналы [(x,y), (R,G,B)].
Этот же процесс можно применить к одномерным последовательностям данных. Модель извлекает признаки из данных последовательностей и отображает внутренние признаки последовательности. 1D CNN очень эффективна для получения признаков из сегмента фиксированной длины всего набора данных, где не так важно, где находится признак в сегменте.

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

Мы можем определить модель 1D CNN для одномерного прогнозирования временных рядов следующим образом.

model_cnn = Sequential()
model_cnn.add(Conv1D(filters=64, kernel_size=2, activation=’relu’, input_shape=(X_train_series.shape[1], X_train_series.shape[2])))
model_cnn.add(MaxPooling1D(pool_size=2))
model_cnn.add(Flatten())
model_cnn.add(Dense(50, activation=’relu’))
model_cnn.add(Dense(1))
model_cnn.compile(loss=’mae’, optimizer=’adam’)
model_cnn.summary()

Поймите все слои:

  1. Слой Conv1D: здесь учится CNN. Волшебство случается
  2. MaxPooling. Слой пула часто используется после слоя CNN, чтобы уменьшить сложность вывода и предотвратить переобучение данных. В нашем примере мы выбрали размер 2. Это означает, что размер выходной матрицы этого слоя составляет только половину входной матрицы.
  3. Сведение. Сведение — это преобразование данных в одномерный массив для ввода их на следующий слой. Мы сглаживаем выходные данные сверточных слоев, чтобы создать один длинный вектор признаков.

Краткое резюме:

Понимание параметров:

  1. Filters/kernel_size: фильтр — это матрица весов, которую мы измеряем с помощью входных данных.Фильтр свертки обеспечивает меру того, насколько фрагмент входных данных похож на объект. .
  2. активация: помощь в расчете весов для каждого нейрона.
  3. оптимизатор, Адам: Адам является самым популярным оптимизатором глубокого обучения, поскольку он добился отличных результатов по сравнению с классическим алгоритмом стохастического градиентного спуска.

Результаты (модель 10 эпох с размером пакета 100)

Оценка рассчитывается по 5000 значений:
- Оценка MAE составляет 0,5
- Оценка MAPE составляет 0,06%

Углубитесь с моделью CNN

model_cnn = Sequential()
model_cnn.add(Conv1D(filters=64, kernel_size=2, activation=’relu’, input_shape=(X_train_series.shape[1], X_train_series.shape[2])))
model_cnn.add(BatchNormalization())
model_cnn.add(MaxPooling1D(pool_size=2))
model_cnn.add(Flatten())
model_cnn.add(Dense(32, activation=’tanh’))
model_cnn.add(Dropout(0.2))
model_cnn.add(Dense(16, activation=’tanh’))
model_cnn.add(Dropout(0.2))
model_cnn.add(Dense(8, activation=’relu’))
model_cnn.add(Dense(1))
model_cnn.compile(loss=’mae’, optimizer=’adam’)
model_cnn.summary()

Разберитесь с добавленными слоями:

  1. Пакетная нормализация. Прежде чем объяснять, что это такое, нам нужно определить, какую проблему мы пытаемся решить.
    Обычно для обучения нейронной сети мы выполняем некоторую предварительную обработку к входным данным. Например, мы могли бы нормализовать все данные, чтобы они напоминали нормальное распределение.
    Но проблема возникает на промежуточных слоях, потому что распределение активаций постоянно меняетсяg во время тренировки. Это замедляет процесс обучения, поскольку каждый слой должен научиться адаптироваться к новому распределению на каждом этапе обучения.
    Таким образом, с помощью Пакетной_нормализации мы заставляем нормализовать и масштабировать все входные данные. каждого слоя.
  2. Отсев. Слой отсева случайным образом присваивает 0 весовых коэффициентов нейронам в сети. Поскольку мы выбрали коэффициент 0,2, 20% нейронов получат нулевой вес. Благодаря этой операции сеть становится менее чувствительной к небольшим изменениям данных.

Результаты (модель 10 эпох с размером пакета 100)

Оценка рассчитывается по 5000 значений:
- Оценка MAE составляет 1,37
- Оценка MAPE составляет 4,38%

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

Попробуйте что-нибудь другое, другую архитектуру:

model_cnn = Sequential()
model_cnn.add(Conv1D(filters=64, kernel_size=2, activation=’relu’, input_shape=(X_train_series.shape[1], X_train_series.shape[2])))
model_cnn.add(BatchNormalization())
model_cnn.add(Conv1D(filters=64, kernel_size=2, activation=’relu’))
model_cnn.add(Conv1D(filters=32, kernel_size=2, activation=’relu’))
model_cnn.add(MaxPooling1D(pool_size=2))
model_cnn.add(Dropout(0.2))
model_cnn.add(Flatten())
model_cnn.add(Dense(1))
model_cnn.compile(loss=’mae’, optimizer=’adam’)
model_cnn.summary()

Результаты (модель 10 эпох с размером пакета 100)

Оценка рассчитывается по 5000 значений:
- Оценка MAE составляет 0,8
- Оценка MAPE составляет 0,09%

Результаты слишком хороши, чтобы быть правдой?

Действительно, процент ошибок, который у нас может быть, слишком велик, чтобы быть правдой. Но это можно объяснить теми данными, которые мы даем на вход наших моделей. Переменная «Lag_30m», которая представляет собой количество доступных велосипедов за последние 30 минут, коррелирует с прогнозируемой нами целью (см. матрицу корреляции). Это нормально, так как в большинстве случаев количество велосипедов не меняется с одинарного на двухместное в течение 30 минут. Таким образом, алгоритм сильно индуцируется этой переменной.

Давайте посмотрим на результат, если мы удалим эту переменную из наших моделей:

  • Для LGBm у нас есть оценка MAPE 11%, что в 5 раз выше, чем у модели, включающей переменную «lag_30m». Уже можно сказать, что эта переменная оказывает огромное влияние на оценку.
  • Для модели 1DCnn показатель MAPE равен 1,5%. Мы заметили очень явное ухудшение оценки, которая составила 0,02% (с моделью, включающей переменную «lag_30m».

Можем ли мы считать это читерством, если переменная так сильно влияет на нашу модель, что почти дает решение?

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

Давайте попробуем использовать lag_1h30 в нашей модели 1DCnn:

С нашей моделью и переменной «lag_1h30» мы получили показатель MAPE, равный 1,5 %.

Пути для дальнейшего развития:

Для машинного обучения:
— перекрестная проверка
— выбор функций

Для глубокого обучения:
- Добавить данные
- Гиперпараметры более адаптированы к реальности.

Вывод

В этой статье мы сравнили различные подходы с точки зрения машинного обучения. Статистические подходы (наивный, LGB, Sarimax) и подходы глубокого обучения (одномерные сверточные сети). Наши результаты находятся на уровне используемых алгоритмов.
Для статистических моделей у нас есть результаты для наиболее эффективных моделей с ошибкой около 5%. Эти модели не являются лучшими с точки зрения оценки. Однако они не очень требовательны к ресурсам (GPus, память), а прогностические переменные и параметры (гиперпараметры) просты для понимания и управления ими.
Для так называемых моделей глубокого обучения результаты более точны. У нас процент ошибок около 0,05%. Этот процент ошибки невелик, но мы теряем контроль над прогнозирующими переменными. Переменные преобразуются во входные данные для нейронов, и по мере их распространения (вперед и назад) веса модифицируют нейроны. Таким образом, в конце модели у нас больше нет информации о прогностических переменных.