Вы когда-нибудь мечтали о том, чтобы узнать, продается ли ваш любимый аромат мороженого «Бен и Джерри» в ближайшем к вам продуктовом магазине? Команда машинного обучения Instacart создала инструменты, чтобы понять это!

Масштаб нашего рынка позволяет нам строить сложные модели прогнозирования. Наше сообщество, состоящее из более чем 100 000 покупателей, сканирует миллионы товаров в день в 20 000 физических магазинов и доставляет их покупателям. Эти магазины принадлежат нашим партнерам по розничной торговле продуктами, таким как Aldi, Costco, Kroger, Safeway и Wegmans. Каждый раз, когда покупатель сканирует товар в корзину или помечает его как «не найденный», мы получаем информацию, которая помогает нам делать точные прогнозы наличия товара в магазине. Это помогает нам установить точные ожидания в отношении товаров, которых нет в наличии, и рекомендовать соответствующие замены для товаров, которых, вероятно, нет в наличии.

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

Проблема: понимание «не основано»

Если покупатель не может найти товар в магазине, мы помечаем товар как «не найден». Не найденный товар - это плохо для всех участников нашего рынка: клиенты не получают того, что хотят, розничные партнеры теряют в доходах, покупатели тратят больше времени на их поиск, а Instacart не обеспечивает наилучшего обслуживания клиентов.

Неоснование происходит в основном по двум причинам:

  1. Доступность: Instacart не владеет логистической цепочкой поставок товаров, перечисленных на его платформе (это владеют наши розничные партнеры), поэтому нам как третьей стороне сложно узнать, есть ли в магазине товар в заданное время. Мы получаем регулярные обновления (обычно один раз в день) от наших розничных партнеров о наличии всех товаров. Но вещи могут быть распроданы быстро в течение дня. Мы поняли, что нам нужны более детализированные данные в течение дня - нам нужно знать доступность каждого элемента в реальном времени.
  2. Возможность поиска. Иногда из-за нашего исчерпывающего каталога товаров покупатели не могут найти все товары, имеющиеся в магазине. Это может быть связано с тем, что товары перемещаются на переднюю часть магазина для сезонной акции или объединяются в пары для увеличения продаж. Например, фишки кладут рядом с сальсой, а не в обычный проход. Рекомендация товаров, которые легко найти, экономит время покупателей и сокращает количество замен для покупателей.

Следовательно, чтобы делать выводы о доступности в режиме реального времени и фиксировать возможность поиска, мы построили модель доступности товаров, которая постоянно прогнозирует наличие 200 миллионов продуктовых товаров каждые 60 минут.

Построение модели

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

Возможности

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

Функции на уровне товара

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

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

Функции, зависящие от времени:

Мы используем функции на основе времени, такие как время суток и день недели, когда заказ был получен в магазине. Обычно мы видим лучшую доступность товаров по утрам. (Совет от профессионалов: всегда ходите в магазин по утрам! Тогда на полках снова будет запас.)

Проблема категориальных признаков высокой мощности

У нас также есть несколько категориальных функций (например, идентификаторы магазина, продукта, продавца, отдела, прохода, бренда, региона и т. Д.), Которые можно использовать непосредственно в модели. Но некоторые из них имеют чрезвычайно высокую мощность (количество уникальных категорий). Количество элементов исчисляется миллионами для идентификатора продукта и десятками тысяч для идентификатора магазина. Использование их в качестве функций с горячим кодированием приводит к неэффективному обучению, и они также неэффективны с точки зрения масштабирования (функции OHE могут увеличить размер данных и время обучения / оценки модели, и нам нужно как можно чаще оценивать сотни миллионов элементов. !). Кроме того, обучающие вложения, вероятно, не являются хорошей идеей, учитывая их количество в миллионы. Чтобы модель научилась правильному внедрению, каждая категория должна иметь достаточное количество выборок в обучающих данных, что снова приведет к увеличению размера обучающих данных. Мы исправили эту проблему, выполнив простое действие, которое также устранило еще одну важную проблему, описанную ниже.

Предметы в длинном хвосте

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

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

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

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

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

Шкала оценки

Доступность товара меняется практически в реальном времени по мере того, как он продается и пополняется, и поэтому мы хотим прогнозировать доступность как можно чаще. Иногда обучение в масштабе является узким местом, но для этой проблемы оценка масштаба является более узким местом. Следовательно, мы потратили больше усилий на оптимизацию конвейера скоринга, чтобы он мог оценивать более 200 миллионов элементов каждые 60 минут. В этом конвейере для каждого элемента создается около 130 функций, и каждые 60 минут обрабатываются 10 ТБ данных. Новая архитектура скоринга, которую мы создали с нуля, позволяет оценивать в 15 раз больше элементов, используя 1/5 ресурсов в 1/4 времени. Вот несколько вещей, которые помогли нам добиться такого масштабного масштабирования:

  1. Выполнение сложной разработки функций в нашем хранилище данных снежинки вместо Python.
  2. Выявление и кэширование функций, которые не часто меняются - это помогло нам сократить время разработки функций.
  3. Оптимизация передачи данных из хранилища данных в экземпляр AWS.
  4. Лучшее распараллеливание кода скоринга Python.
  5. Более быстрая и эффективная загрузка результатов в таблицу Postgres.

Развитие модели

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

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

Заинтересованы в работе над такими масштабными и результативными проектами в Instacart? Посетите нашу страницу вакансий на сайте careers.instacart.com.

Не стесняйтесь обращаться с любыми отзывами / вопросами через комментарии, напишите мне по адресу [email protected] или напишите мне в Linkedin или twitter.

Особая благодарность всем, кто работал над этим на протяжении многих лет, чтобы довести его до нынешнего состояния: Шишир Прасад, Ангадх Сингх и Шарат Рао. Также спасибо Джереми Стэнли, Рэйчел Холм, Тайлеру Тейту и многим другим, чьи отзывы помогли значительно улучшить этот пост.