Прогнозирование временных рядов для прогнозирования спроса на желтые такси в одном из самых оживленных районов Нью-Йорка.

Пожалуйста, проверьте коды на Github,



Попробуйте https://nbviewer.org/, если у вас нет возможности загрузить блокнот на Github.

Оглавление

  1. Вступление
  2. Бизнес-цели и ограничения
  3. Получение данных
  4. Форматирование данных
  5. Бизнес-показатели
  6. Очистка данных
  7. Обзор данных
  8. Извлечение функций
  9. Предварительная обработка данных
  10. Обучение
    I. Линейная регрессия
    II. XGBoost Regressor
    III. LSTM (долгосрочная краткосрочная память)
  11. Генерация и предварительная обработка тестовых данных
  12. Тестирование
  13. Последние мысли
  14. использованная литература

Вступление

Комиссия по такси и лимузинам Нью-Йорка (TLC) «», созданная в 1971 году, является агентством, ответственным за лицензирование и регулирование медальонных (желтых) такси города Нью-Йорка и различных других такси. Желтые такси - самые культовые такси Нью-Йорка, широко известные и за пределами США.

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

В Нью-Йорке пять районов: Бронкс, Бруклин, Манхэттен, Куинс и Статен-Айленд. Желтые такси - единственные транспортные средства, которым разрешено реагировать на уличный вызов пассажира во всех пяти районах Нью-Йорка.

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

Бизнес-цели и ограничения

  1. Интерпретируемость не требуется.
  2. Мы хотели бы, чтобы задержка была меньше 2 секунд.
  3. Мы бы хотели, чтобы разница между фактическими и прогнозируемыми потребностями была меньше.

Получение данных

Мы собрали данные со страницы TLC официального сайта Нью-Йорка ¹. Там вы найдете данные по месяцам и типам такси за 2009 год.

Я скачал только за 2018 и 2019 годы. Теперь вы можете спросить, почему не данные за 2020 год? Это потому, что в 2020 году была пандемия коронавируса, которая все разрушила. Никакая модель машинного обучения не будет работать в такой высокой неопределенности.

Подобные события случаются очень и очень редко (например, раз в сто лет). В статистике есть термин для обозначения этого типа событий, называемый событием «Черный лебедь».

Данные на странице TLC очень хорошо детализированы. Есть много столбцов, таких как идентификатор местоположения, время посадки, время высадки, количество пассажиров, стоимость поездки, скорость и т. Д. Но для нашей проблемы нам понадобятся только идентификатор местоположения и время посадки. Поэтому вместо того, чтобы загружать все данные, которые будут огромными для моего мобильного соединения. Я использовал Google colab как среду для загрузки только соответствующих столбцов. 😎

Форматирование данных

Данные за каждый месяц были в разных CSV-файлах, поэтому я их объединил. Я использовал данные с января 2018 года по апрель 2019 года для обучения (обучение и перекрестная проверка).

За 16 месяцев у нас есть 132 757 101 пикап из 264 уникальных мест. TLC разделила весь Нью-Йорк на 266 регионов с идентификатором местоположения от 1 до 266.

С помощью карты Google я проверил продолжительность путешествия между несколькими случайными местами и их соседними местами. Что в среднем составляет около 13 минут. Поэтому я решил прогнозировать потребности каждые 15 минут. Это означает, что мы разделим день на 96 частей.

Теперь нам нужно создать обучающие данные из необработанных данных. Для каждой локации мы будем подсчитывать количество отправлений за 15-минутный интервал времени.

После форматирования обучающие данные выглядят так:

Первая отметка времени 1514782800 соответствует 00:00 01.01.2018. Вторая временная метка 1514783700 соответствует 01–01 2018 00:15 и так далее.

Посмотрим, как я подсчитал. Возьмем, к примеру, первую строку. Идентификатор местоположения равен 1, а временная метка - 1514782800. Итак, я подсчитал количество посылок из местоположения с идентификатором 1 в период с 00:00 утра 2018–01–01 до 00:14 утра 2018–01–01.
Точно так же для следующей строки я подсчитал количество отправлений из локации с идентификатором 1 в период с 00:15 до 01–01 2018 г. и 00:29 01–01 2018 г.

location и timestamp - это входные переменные, а count - выходная переменная. . Таким образом, задача состоит в том, чтобы предсказать количество перехватов за 15 минут с учетом идентификатора местоположения и времени, которые будут кратны 15 минутам.

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

Бизнес-показатели

  1. Мы будем использовать MAE (средняя абсолютная ошибка) в качестве основного показателя эффективности.
  2. С помощью MAE нам также нужно проверить среднее значение вывода. Почему? Потому что одного МАЭ недостаточно.
    Предположим, кто-то говорит, что MAE равно 10, тогда будет хорошо, если средний результат будет 100 или 500 (для конкретной задачи), но не хорошо, если средний результат будет 10.
  3. Мы также увидим MAE%, равное MAE/average(y). Какая комбинация двух вышеперечисленных.
  4. RMSE - тоже хороший показатель, который мы будем отслеживать.
  5. Я также проверил ошибку R² для проверки работоспособности.

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

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

Сглаживание

Счета очень неровные. Чтобы сделать тренировку удобной, мы должны сделать ее немного более плавной.

Для сглаживания мы использовали отсчеты 5 временных интервалов (t0, t + 1, t + 2, t-1, t-2). Мы использовали формулу x[t-2]*.05 + x[t-1]*.20 + x[t]*.50 + x[t+1]*.20 + x[t+2]*.05

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

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

Только для Манхэттена

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

Из 132 миллионов пикапов у Манхэттена 120 миллионов пикапов. В остальных четырех районах всего 12 миллионов пикапов.

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

В наших данных обучения у нас есть 68 локаций, принадлежащих Манхэттену.

Обзор данных

  • У нас есть две функции: местоположение и отметка времени.
  • Количество - это метка вывода.
  • У нас есть 3 165 536 точек данных.

  • Мы определенно можем видеть ежедневную картину.
  • Но меня удивляет, что мы не видим четкого восходящего тренда через год.
  • У нас есть пикапы 120 342 142,55. Это десятичное число, потому что мы сгладили.
  • У нас есть минимум 0 и максимум 659,9.

  • Примерно 9,50% точек данных имеют счетчики = 0 и примерно 15,55% точек данных имеют счетчики ‹1 из 3,165 мм.
  • 25% данных имеют счетчики ≤ 3,6 и только 10% данных имеют счетчики ≥102,7.
  • Эти подсчеты сильно искажены.

Извлечение функций

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

  • t-1: количество срабатываний за последний интервал времени.
  • t-2: количество срабатываний на последнем втором временном интервале.
  • t-3: количество срабатываний в третьем последнем временном интервале.
  • t-4: количество срабатываний на четвертом последнем временном интервале.
  • t-5: количество срабатываний на пятом последнем временном интервале.
  • dt0: количество отправлений учитывается в то же время в предыдущий день.
  • dt-1: количество отправлений происходит в момент времени t-1 в предыдущий день.
  • dt-2: количество посылок в момент t-2 предыдущего дня.
  • dt + 1: количество отправлений происходит в t + 1 раз в предыдущий день.
  • dt + 2: количество посылок в момент времени t + 2 в предыдущий день.
  • tdiff1: что равно [t-1]-[t-2]
  • tdiff2: что равно [t-2]-[t-3]
  • tdiff3: что равно [t-3]-[t-4]
  • tdiff4: что равно [t-4]-[t-5]
  • ty1: что равно [t-1]-[dt-1]
  • ty2: что равно [t-2]-[dt-2]
  • avg_y: что равно ([dt-2]+[dt-1]+[dt0]+[dt+1]+[dt+2])/5
  • simple_MA: что равно ([t-5] + [t-4] + [t-3] + [t-2] + [t-1]) / 5
  • взвешенная_МА: что равно (5*[t-1] + 4*[t-2] + 3*[t-3] + 2*[t-4] + 1*[t-5]) / 15
  • экспоненциальная_МА: равна alpha * { [t-1] + (1-alpha)*[t-2] + ((1-alpha)²)*x[t-3] + ((1-alpha)³)*[t-4] + ((1-alpha)⁴)*[t-5] }, где альфа = 0,333
  • week_day: от 1 до 7, где 1 - понедельник, а 7 - воскресенье.

Мы создали 21 новую функцию. Итак, теперь у нас есть всего 23 функции.

Предварительная обработка данных

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

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

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

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

Обучение

Линейная регрессия

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

Производительность:

MAPE по всем данным перекрестной проверки абсурден. Это триллионы.
Но если мы рассчитаем MAPE только для ненулевых выходных данных, это будет 0,1365. Вот почему мы не можем полагаться на MAPE, если фактические результаты - нули или очень маленькие значения.

MAE составляет 2,23, чтобы сделать вывод о том, насколько он хорош, нам нужно знать средние фактические выходы. Средний фактический выход CV составляет 34,75, что означает, что MAE является разумным. MAE% составляет 6,60%, что хорошо.

RMSE тоже неплохо выглядит. И R² очень близко к 1.

Важность функции:

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

Регрессор XGBoost

Чтобы настроить XGboost Regressor, я использовал hyperopt, который использует байесовский метод оптимизации.

После настройки я нашел лучший гиперпараметр {‘learning_rate’: 0.09, ‘max_depth’: 8, ‘n_estimators’: 100, ‘reg_lambda’: 1.0}, который снижает MAE до 2,15.

Производительность:

По производительности очень похож на предыдущую модель. Существенных улучшений нет.

Важность функции:

Это 10 основных важных функций модели XGBoost Regressor в порядке убывания.

Здесь интересно отметить, что Т-5 приобретает большее значение, чем Т-2, Т-3 и Т-4.

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

LSTM (долгосрочная краткосрочная память)

Когда дело доходит до последовательности данных, будь то текстовые данные или данные временного ряда. LSTM был выбран по умолчанию.

LSTM - это модель глубокого обучения, которая является улучшением по сравнению с традиционной RNN (рекуррентной нейронной сетью). RNN страдает от проблемы с кратковременной памятью, которая была решена в LSTM.

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

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

Структура глубокого обучения на основе LSTM выглядит так:

У нас есть два слоя LSTM, один за другим. В каждом есть 64 активационных блока ReLU. Последний слой представляет собой плотный слой с одним блоком активации ReLU.

Я использовал оптимизатор Adam, который минимизирует потери MAE.

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

По прошествии 9 эпох мы подошли к разумному значению.

Производительность:

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

Генерация и предварительная обработка тестовых данных

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

Необработанные данные тестирования - это данные за последние 8 месяцев 2019 года.

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

Тестирование

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

Среднее значение вывода avg (y_test) составляет 31,25

---- Performance of Linear Regression ----
MAE =>                    7.227731813183053
MAE% =>                   0.23128834949868637
R squared =>              0.9094240989153082
RMSE =>                   11.84154255439212

---- Performance of XGBoost Regressor ----
MAE =>                    6.574487879610602
MAE% =>                   0.21038445943729467
R squared =>              0.9225697752186679
RMSE =>                   10.948565185380145

---- Performance of LSTM ----
MAE =>                    6.34815704342306
MAE% =>                   0.2033560382199119
R squared =>              0.92908681177385
RMSE =>                   10.465103391641659

Производительность значительно хуже, чем раньше. Но на удивление LSTM работает лучше, чем две другие модели. Это означает, что модель на основе LSTM более устойчива и обобщает лучше, чем другие.

Последние мысли

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

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

Обратите внимание, что я не использовал классические модели прогнозирования временных рядов, такие как Holt-Winters или ARIMA. Потому что сами по себе они не будут работать так же хорошо, как нынешние модели. Тем не менее, мы, безусловно, можем получить от них пользу, если сделаем стекинг-ансамбль.

использованная литература

  1. Комиссия по такси и лимузинам Нью-Йорка (TLC) [https://www1.nyc.gov/site/tlc/about/tlc-trip-record-data.page]
  2. Примененные корни [https://www.appliedroots.com/]

Спасибо за чтение блога! Вы можете связаться со мной через мою учетную запись LinkedIn и просмотреть другие мои работы на моем личном веб-сайте.

Также 👏, если вам понравилось. И продолжайте читать, продолжайте учиться.