Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Мы команда data science Ozon fresh. В этой статье мы расскажем об одной из наших задач – алгоритме, который помогает управлять нашим огромным ассортиментом.
Ozon fresh — это сервис быстрой доставки продуктов, бакалеи, бытовой техники, электроники и других товаров. В нашем ассортименте более 35 000 уникальных позиций (готовая еда, мясо, рыба, фрукты, овощи, товары для гигиены и многое другое). Специфика Ozon fresh заключается в мини-складах, где хранятся товары. Они доставляются клиентам в радиусе нескольких километров.
Управление таким количеством позиций требует много человеческих и технологических ресурсов. У нас этим занимаются более 30 человек. Для упрощения работы мы используем различные группировки товарных позиций. Самая популярная — иерархическая четырёхуровневая группировка (далее мы будем называть её «категорийное дерево»).
Для решения задач разработки товарных рекомендаций, управления ценами и ассортиментом возникла необходимость реализовать автоматическое формирование пятого уровня группировки. В этой статье мы поделимся одним из возможных подходов к решению этой задачи, который показался нам самым интересным.
Термины, используемые в статье (определения могут не совпадать с классическими, принятыми в академической среде):
SKU, товар, товарная позиция — уникальный товар с уникальным идентификатором.
Экземпляр товара — конкретная единица/штука, находящаяся на полке на складе.
Ассортимент склада — список всех товарных позиций, продаваемых с данного склада.
Категорийное дерево — иерархическая структура ассортимента для управления им.
Пример использования терминологии
SKU — яблоки сезонные, садовые, 1 кг
На складе может быть десять разных упаковок с надписью «Яблоки сезонные, садовые, 1 кг»,
Категорийное дерево выглядит так:
Как мы жили раньше
Историческая справка о том, как обычно происходит формирование категорийного дерева.
Задача построения категорийного дерева — это, по сути, задача кластеризации: сгруппировать существующие товары по какой-то логике. Как и в случае с любой другой задачей кластеризации, решение сильно зависит от цели. То есть в первую очередь нужно понять, для чего нам необходима группировка.
В случае с категорийным деревом цель — упростить работу с большим ассортиментом. В основном формированием категорийного дерева занимаются категорийные менеджеры (отвечающие за разные категории товаров). Поэтому они часто делят товары на группы так, чтобы товары от одного поставщика находились в одной группе. Это своего рода наследие от принципа работы офлайн-магазинов.
Когда культура ритейла только формировалась, категорийные деревья строились на базе CDT (Customer Decision Tree):
Собирались фокус-группы покупателей.
Проводилось социологическое исследование с целью выяснить, по какому принципу люди выбирают товары.
На основании результатов формировались группы потребностей пользователей.
Пример:
Сегодня есть огромное количество товаров, и с каждым днём появляются новые. Каждый раз опрашивать покупателей нецелесообразно и очень трудоёмко. Поэтому с нуля дерево никто не строит, а просто добавляют новые товары в уже существующие категории. Этим и занимаются категорийные менеджеры.
И как раз здесь возникает проблема: у каждого человека разная экспертиза и разное видение своей категории. Бывают ситуации, когда в компанию приходит новый категорийный менеджер и перестраивает категорийное дерево. Кроме того, есть много внешних факторов, которые не позволяют зафиксировать структуру дерева раз и навсегда (или хотя бы на долгое время). А ещё некоторые товары относятся к нескольким категориям сразу. Например, банку тушёнки можно отнести как к категории «Мясо», так и к категории «Консервы».
Поэтому, когда у нас возникла необходимость добавить ещё один уровень иерархии в категорийное дерево с целями управления ценами, рекомендации товаров и решения других аналитических задач, мы захотели реализовать разбиение существующих категорий только на основе данных о продажах, чтобы исключить человеческий фактор и иметь возможность регулярной автоматической актуализации дерева.
Муки поиска
Для решения нашей задачи было важно, чтобы в одну мини-группу товаров (далее группу на самом низком уровне иерархии мы будем называть бакетом) попадали товары, удовлетворяющие одну потребность покупателя.
Мы решили подойти к этому через определение товаров-аналогов.
Товар-аналог (иногда используют термин «товар-заменитель») — это товар со схожими свойствами. Если нужного покупателю товара нет в наличии, то он с большой вероятностью возьмёт товар-аналог.
Для себя мы сформулировали задачу так:
Рассчитать степень аналогичности товаров между собой
Объединить в группы товары с высокой степенью аналогичности.
Ограничения: алгоритм должен базироваться только на данных о продажах.
Почему мы не реализовали группировку на основе атрибутов товаров из карточек? На первый взгляд этот вариант кажется самым логичным, ведь, если у товаров одинаковые атрибуты, значит, они взаимозаменяемы и являются аналогами. Но у этого подхода есть минусы:
у каждой категории свои наборы атрибутов, и их сложно учесть автоматически;
атрибуты указываются вручную разными людьми (категорийными менеджерами и селлерами), и, естественно, в них часто встречаются ошибки и разные трактовки.
Этот вариант нам не подходил из-за сильного влияния человеческого фактора.
В качестве первой итерации мы использовали подход из статьи. В ней описан алгоритм автоматического построения CDT (customer decision tree) для food retail.
Для каждой пары товаров на основе истории чеков рассчитывается коэффициент похожести (The Yule’s Q coefficient) (в нашей терминологии это степень аналогичности) по формуле:
, где
a — количество чеков, в которых не было ни одного товара из пары,
b — количество чеков, в которых был только первый товар из пары,
c — количество чеков, в которых был только второй товар из пары,
d — количество чеков, в которых были оба товара из пары.
После этого выполняется иерархическая кластеризация и строится дендрограмма на дефолтных параметрах для метода scipy.cluster.hierarchy.dendrogram.
Авторы статьи не ставят перед собой цели нахождения бакетов — они строят CDT. Но из-за того, что используемый ими метод раскрашивает близкие товары в один цвет, выглядит это так, как нам нужно:
Подход выглядит вполне достойно, но на наших данных он не сработал