Хабрахабр

Как мы в хакатоне AI.HACK победили, или Когда нужно выключить искусственный интеллект и включить естественный

HACK. В марте команда наших разработчиков с гордым названием «Руки-Ауки» двое суток неусыпно сражалась на цифровых полях хакатона AI. Мы сосредоточились на задаче «Газпромнефти»: прогнозирование спроса на топливо со стороны В2В-клиентов. Всего было предложено пять задач от разных компаний. Забегая вперёд — наша команда решила эту задачу с наивысшей точностью. Нужно было по обезличенным данным — регион приобретения топлива, номер заправки, вид топлива, цена, дата и ID-клиента — научиться прогнозировать, сколько в будущем купит тот или иной клиент. И помимо основной задачи мы также построили прогноз суммарного потребления по каждому из сегментов.
Выгрузка содержала данные о покупках клиентов за период с ноября 2016 по 15 марта 2018 года (за период с 1 января 2018 по 15 марта 2018 данные НЕ включали объемы). Клиенты были разбиты на три сегмента: крупные, средние и мелкие.

Пример данных:

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

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

Старались извлечь дополнительные признаки, строили регрессионные модели (XGBoost, CatBoost и др.). Получив исходные данные, мы, как и все, начали пробовать классические методы машинного обучения, пытаясь построить подходящую модель, нащупать корреляцию каких-то признаков.

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

Корреляция признаков:

Это объяснялось вполне логично. Получалось, что количество литров практически никак не зависит от цены. У него выбор: либо он заправится на заправке, с которой сотрудничает компания, либо на какой-то другой. Водитель едет по трассе, ему нужно заправиться. Поэтому он просто сворачивает на ближайшую заправку и наполняет бак. Но водителю всё равно, сколько стоит топливо – его оплачивает организация.

Однако несмотря на все усилия и перепробованные модели, никак не удавалось достичь минимально допустимой точности прогнозирования (baseline), которая вычислялась по этой формуле (Symmetric mean absolute percentage error):

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

Пробовали брать медианные значения по группам клиентов, видам топлива, регионам, номерам АЗС. Начали думать, как улучшить результат. То есть в тестовой появились новые клиенты. Проблема была в том, что в тестовых данных отсутствовало около 30 % ID клиентов, которые были в обучающей выборке. Но решать проблему нужно было нам самим. Это было ошибкой организаторов, не проверили. И тут как раз помогло машинное обучение. Мы не знали потребления новых клиентов, и поэтому не могли построить для них прогнозы.

А потом появилась идея: почему бы не создать профили новых клиентов на основе имеющихся данных? На первом этапе заполняли недостающие данные средним или медианным значением по всей выборке. Кластеризовали существующих клиентов, составили характерные профили для разных регионов и на них обучили XGBoost, которая затем «достроила» профили новых клиентов. У нас есть срезы по регионам, сколько там покупают топлива клиенты, с какой частотой, какие виды.

До подведения итогов оставалось ещё часа три. Это позволило нам вырваться на первое место. Обрадовались и начали решать бонусную задачу — прогнозирование по сегментам на три месяца вперед.

Ошибка составляла от 3 % до 6 %. Синим показаны реальные данные, красным — прогноз. Мы тоже засуетились и решили что-нибудь предпринять на случай, если они нас догонят. Можно было посчитать ещё точнее, например, учтя сезонные пики и праздничные дни.
Пока мы этим занимались, одна команда начала нас догонять, каждые 15–20 минут улучшая свой результат.

И когда конкуренты нас обошли, мы попробовали объединить обе модели. Начали параллельно делать другую модель, которая ранжировала статистику по степени значимости, её точность была чуть ниже, чем у первой. 24671%, в результате мы вернули себе первое место и удержали его до конца. Это дало нам небольшой прирост метрики – до 37.

рублей, почет, уважение и…преисполненная чувством собственного достоинства отправилась спаааать! За победу наша команда «Руки-Ауки» получила сертификат на 100 тыс. 😉

Команда разработчиков «Инфосистемы Джет»

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть