Нельзя просто так взять и расставить электросамокаты в городе. Надо, чтобы они находились в нужное время, в нужном месте и в нужном количестве, чтобы выполнять свою транспортную задачу. Спрос на поездки в разных локациях неодинаковый, поэтому если поставить самокаты ровным слоем на улицах города – будет неэффективно. Нельзя также расставить их только в местах сильного пользовательского притяжения, забыв при этом про периферию.
Нужен хоббит алгоритм, который бы рассчитал, какое количество поездок можно ожидать на определенной парковке в определенный временной промежуток.
Меня зовут Никита Зеленский, я руковожу отделом по работе с данными в Whoosh, разработчике технологических решений и операторе микромобильности. Эту статью мы написали вместе с Иваном Маричевым, дата-сайнтистом Whoosh. Он же и автор алгоритма, о котором пойдет речь.
Здесь мы расскажем, как мы реализовывали модель прогнозирования спроса на самокаты, с чем сталкивались при прототипировании, какие модели были протестированы, чем наш случай отличается от прогнозирования спроса в каршеринге, спроса для пополнения запасов в дарксторе и т.п. (Самокат, самокаты Whoosh передают привет!)
История получилась про наши подходы и грабли, которые мы в итоге собрали. Чуть-чуть про технику, чуть-чуть про бизнес – нескучно и с ветерком (как на самокате).
Whoosh!
Проблематика
Зачем менять устоявшуюся схему, разрабатывать ML-модель, если можно все сделать в Экселе?
Основная причина — текущая ребалансировка (расстановка на парковках и перемещение по локациям) самокатов покрывала не весь пользовательский спрос. Иногда пользователям, чтобы взять в аренду самокат, приходилось идти на другую парковку, что порой неудобно и отнимает время. В долгосрочной перспективе это способствует оттоку клиентов, а наша задача – сделать микромобильный транспорт доступным и регулярным.
Вопрос – почему бы просто не выставлять сильно завышенное количество техники? Представим следующую картину: в среднестатистическом городе Х имеется 350-400 парковок (если не брать в расчет города-миллионники). По каждой парковке мы собираем статистику: какое количество поездок пользователи на ней начали и закончили. Зная эти цифры, можно было бы оставлять на них количество самокатов, равное скользящему среднему от количества поездок за 7 дней + 20%? Но не все так просто:
-
Флот << прогноз. Маловероятно, что прогнозируемое таким образом количество техники будет возможно предоставить в рамках флота, доступного в городе. Даже если вы лидер отрасли и у вас большое количество самокатов в локации – это сильно неразумный способ, который замедлит интеграцию в новые регионы и районы.
-
Логистика. После появления такого количества флота на парковке, неизбежно вырастут расходы на ребалансировку, которые напрямую зависят от количества регулярно перевозимых самокатов.
-
Актуальность. Метод скользящего среднего не сможет удовлетворять пиковый спрос внутри дня. Спрос на поездки зависит от времени суток, поэтому нам важно, чтобы наши самокаты были там, где они нужны в конкретный час: когда вы утром идете на работу, спрос выше у метро и остановок общественного транспорта, а вечером — наоборот, самокаты требуются преимущественно от работы до других локаций города.
-
Урбанистика. Отдельное «спасибо» можно ожидать от горожан и властей, которые явно не одобрят загромождение городских пешеходных зон большим количеством неиспользуемой техники.
-
Неэкономично. Выставление техники на парковки с запасом неизбежно приведет к простою самокатов, когда в теории они могут быть востребованы для поездок по другим маршрутам.
И это только самые очевидные причины, почему такой подход в долгосрочной перспективе не годится. Мы не отменяем важность решений на основании дедукции и опыта людей, которые работают в операционных центрах в городах нашего присутствия – у них есть понимание специфики конкретных локаций. Но с таким потоком данных и постоянно изменяющихся бизнес-условий лучше справится машинный “мозг”.
EDA.
Ключевой этап при создание любой модели — сбор данных, а именно их чистота и репрезентативность, т.е. насколько наши данные корректны и содержат ли всю необходимую информацию (это тот случай, когда принцип GIGO актуален как никогда). Также необходимо быть готовым, что создание ML-моделей – процесс крайне итеративный, и часто при оценке метрик моделей может потребоваться произвести новую выборку признаков или обогатить исходный датасет новыми данными.
Что мы имеем на входе?
-
Нерегулярность спроса: для кикшеринга характерен нерегулярный спрос. Влияет множество факторов: погода, праздники, пробки и т.п. Наши исторические данные по поездкам агрегированы по 30 минут – и при такой форме агрегации в данных не будет ни тенденции, ни дневной сезонности.
-
Различная структура парковок: парковки могут быть “топовыми”, т.е. пользоваться высоким спросом, в том числе иметь ярко выраженную дневную сезонность, и “слабо востребованными”, где спрос на поездки по своей структуре больше спорадический. Это будет влиять непосредственно на стационарность временного ряда спроса на парковках с различной структурой.
-
Пропуски в данных. Наш бизнес имеет определенную сезонную динамику. В большинстве городов мы работаем 9 месяцев: с марта по ноябрь. А анализируя временные ряды, такие пробелы между датами (с декабря по февраль) просто так не выкинешь — их необходимо правильно обрабатывать: подсказывать модели периоды завершения сезона и его начала, что было между этими датами, а также периоды, когда локация встает на кратковременную паузу. В противном случае, мы будем иметь “кривую” линию тренда с завышенным или заниженным показателями.
Также в ходе EDA было определено, что прогнозирование на все 100% парковок для города не имеет бизнес-смысла, так как 40% “топовых” парковок генерировали 80% всех поездок города.
В качестве тестового города выступает город Сочи в связи с тем, что сезон аренды самокатов в городах южного округа продолжается круглогодично. Тем самым мы, конечно, немного проигнорируем п.3 из списка нюансов выше, но у нас другие цели для MVP:
-
Проверить работоспособность алгоритма (а это проще сделать без разрыва во временных рядах)
-
Протестировать его в реальных условиях в период межсезонья, чтобы принять решение о возможном масштабировании на все города.
Выбор модели.
С вводными разобрались, теперь приступим к выбору обучающей модели. Как упоминалось ранее, парковок, и, соответственно, рядов для прогнозирования, много — десятки тысяч. Для нас скорость обучения важна не менее (если не более), чем точность самой модели, поэтому при принятии решения какую модель (или модели) выбирать, мы основывались на показателях RMSE и среднему времени, которое мы получаем при прогнозировании данных для n-парковок. Мы протестировали модели SARIMAX, LightGBM, Prophet и NeuralProphet.
Как мы обучали модели, проводили валидацию, проверяли стационарность и сам код мы решили не писать — есть очень много подробных инструкций и примеров (например, тут); в этой части статьи расскажем про наши результаты и выводы.
-
SARIMAX — стандартная ARIMA (авторегрессионное интегрированное скользящее среднее) — наиболее популярный метод для однофакторного прогнозирования данных временных рядов. Недостатки ARIMA в том, что при построении прогноза учитываются только данные самого ряда, без внешних факторов-регрессоров. Так как наши показатели спроса напрямую зависят от множества факторов (погода, праздники, пробки и т.д.), в нашей ситуации алгоритм не будет работать.
SARIMAX же является расширением ARIMA с добавленными алгоритмами обработки сезонности и экзогенных переменных — регрессоров (используемые гиперпараметры — SARIMAX(3, 0, 2)x(2, 1, 1)).
Плюсы:
-
Высокая точность уже “из коробки”, учитывая доверительный интервал прогноза;
-
Развёрнутая документация
-
Из всех моделей прогнозирования временных рядов она является наиболее интерпретируемой, т.к. имеет четкое математическое обоснование.
Минусы:
-
долгий подбор гиперпараметров (около 10 минут на парковку).
-
LightGBM — реализация градиентного бустинга за авторством Microsoft. По опыту примения бустинговых моделей (чаще всего в регрессионных задачах, хотя и в двоичной\множественной классификации алгоритм также хорош), LightGBM — явный фаворит в связи с более высокой (x1.5 — x2) скоростью обучения при практически идентичной точности (разница на уровне погрешности ± 1%) в сравнении с XGBoost, CatBoost, etc.
Плюсы:
-
Высокая скорость обучения
-
Большой набор гиперпараметров
-
Менее ресурсоемко по сравнению с аналогами
-
Возможность параллельного и GPU — обучения
Минусы:
-
К сожалению, мы получили переобучение. Даже при автоматизированном подборе гиперпараметров, на тесте так же отсутствует предсказательная способность. Решили не закапываться и поискать возможные альтернативы.
-
Prophet — относительно молодая библиотека прогнозирования от “ЛицоКниги”. Prophet является расширением авторегрессионных моделей, которое позволяет использовать не только лаговые значения целевой переменной, но и дополнительные признаки (реализовано через применение ряда Фурье к таргету), т.е. позволяет использовать дополнительные переменные — регрессоры. Для нас это было особенно актуально, так как сами лаговые значения таргета не обеспечивают точного прогноза, и требуются дополнительные независимые переменные.
Prophet имеет ряд других полезных функций, например:
-
Высокая точность и скорость обучения “из коробки”
-
Удобно реализованы базовые функции (в частности, добавления регрессоров)
-
Отслеживание изменений тенденции
-
Функционал создания пула дат со значениями-аутлаерами (праздниками, спортивными событиями), которые исключались из построения общего тренда + сезонности.
-
Поддерживается и регулярно обновляется разработчиками
И пара минусов:
-
По умолчанию нет настроек нормализации временного ряда и сопутствующих регрессоров
-
Пропуски\аутлаеры в данных лучше обработать вручную
-
NeuralProphet — модификация базовой библиотеки Prophet с добавлением нейронного слоя. По сравнению с Prophet бэкэнд переехал со Stan на PyTorch. Идея использовать Prophet, обладающий высокими результатами (особенно после тюнинга) по функциям потери\времени, и при этом добавить однослойную нейронную сеть для теоретического улучшения точности показалась нам крайне интересной, после чего мы построили модель уже на NeuralProphet. API у библиотек практически идентичны, как и почти все ключевые функции, поэтому технически реализовать было несложно.
Результаты экспериментов с моделью NeuralProphet
Из плюсов можно выделить:
-
Хороший уровень точности “из коробки”
-
В библиотеку интегрирован слой pyTorch, благодаря которому реализован подбор параметров через градиентный спуск
-
Автоматическая предобработка данных (заполнение пропусков, нормализация и т.д.)
Минусы:
-
Низкая скорость обучения, связанная с профилированием DL-настроек (количество эпох, learning rate, etc) для каждой парковки в индивидуальности
Что получили на выходе?
|
|
Prophet |
NeuralProphet |
LightGBM |
SARIMAX |
|
RMSE |
1.3 |
2.19 |
13.23 |
1.43 |
|
total_time (min) |
5.59 |
32.20 |
2.33 |
58.20 |
Табл.1 сравнения метрики RMSE и времени выполнения алгоритмов на n-парковок.
Не трудно догадаться, что из всего зоопарка моделей нами в качестве рабочей был выбран Prophet. Связано это в первую очередь с простотой настройки модели и ее гипер-параметров, удобным добавлением регрессоров и достаточной гибкостью при работе с различными структурами временных рядов.
Разумеется, как бы хороша библиотека не была, чуда “по умолчанию” не произошло, и прежде чем Prophet начал демонстрировать приемлемые результаты предстояло решить ряд проблем. Например, данные по температуре меньше -1°C модель принимала как NaN и пришлось видоизменять датасет с погодой под этот баг. На старте прототипирования у нас были сложности с прогнозированием пиков, так как к дневной сезонности прибавлялись естественные шумы. Решить эту проблему получилось путем добавлением регрессоров с высокой корреляцией к таргету, в первую очередь, связанные с погодными метриками и пользовательской активностью.
Большие надежды также возлагались на NeuralProphet, так как библиотека позиционируется как “быстрее-выше-сильнее Prophet во всем”, однако в нашем случае это оказалось не совсем верно. Небольшую прибавку в точности (+3-5%) получалась только путем значительного увеличения количества эпох, как следствие — всего времени обучения в 2 — 2,5 раза.
В случае с топовыми и дефицитными парковками Prophet позволил умеренно-эффективно прогнозировать данные не только там, где присутствует явная структура (тренд + сезонность), но и там, где спрос не обладает устойчивой структурой.
Общая модель ребаланса.
Необходимо учитывать, что парковки обладают различной структурой не только в плане спроса (“топовые” и “слабо востребованные”), но и в плане ориентированности.
Часть парковок являются кольцевыми, то есть начало поездки и ее окончание — это одна и та же парковка. Как правило, это актуально для парковок возле парков или других крупных точек притяжения. Другая часть парковок являются однонаправленными — с парковки часто стартуют, и редко финишируют (или наоборот). Это обычная картина для парковок с большим количеством близлежащих жилых домов. Что это нам дает? Это значит, что старты на отдельной взятой парковке могут быть распределены нормально, а вот финиши — нет.
Искушенный аналитик спросит — для чего вообще рассчитывать финиши, если они, в отличие от стартов, не аккумулируют прибыль и их нет необходимости как-либо обеспечивать со стороны ребаланса?
Мы научились с минимальной погрешностью прогнозировать количество стартов на несколько тысяч парковок. Но в нашем случае это лишь подзадача в более масштабном проекте — спроектировать алгоритм ребаланса, который бы выполнял роль планировщика для сотрудников операционных центров, прямо указывая, к какому промежутку времени какое количество самокатов необходимо будет подвести, чтобы покрыть потребительский спрос. Одного верного предсказанного количества стартов в данном случае будет недостаточно, так как в конечном виде потребность в ребалансе парковки — функция из несколький переменных.
-
Берем последнее историческое наблюдение количества самокатов (scooters_last).
-
Прогнозируем количество стартов на ближайшие X-часов (starts_forecast).
-
Прогнозируем количество финишей на тоже количество X-часов (finishes_forecast).
Необходимый флот на парковку = scooters_last — starts_forecast + finishes_forecast
Соответственно, для каждой парковки у нас развернуты 2 модели: на расчет стартов и финишей, которые на выходе суммируются с предподготовлеными агрегированными по времени данными о актуальном количестве самокатов.
На выходе мы получаем таблицу такого вида:
где:
ds — время, к которому подвезти самокаты,
parking_id — номер парковки,
rebalance — фактическое значение ребаланса (положительное — профицит, отрицательное — дефицит),
class_ — тип парковки, требуется для приоритизации парковок для сервисных центров.
Вывод
В статье кратко рассказали, как мы реализовывали алгоритм расчета ребаланса, основная цель которого — оптимизировать человеко-часы и облегчить жизнь нашим сервисным командам, которые обеспечивают пользователей самокатами.
Разумеется, это далеко не весь список задач, в который у нас внедрен ML: здесь и классификации (в том числе и гео-классификации по индексу Морана), и регрессионные модели расчета целевых бизнес метрик, и многое другое.
Если статья показалась вам интересной, и вы хотите продолжения — пишите в комментариях, мы с удовольствием ответим на вопросы по теме.
Уважайте пешеходов, водите осторожно и до встречи на улицах
Whoosh!
ссылка на оригинал статьи https://habr.com/ru/company/whoosh/blog/720194/
Добавить комментарий