Люди бывают всех форм и размеров. Это затрудняет поиск индивидуально подходящей одежды в Интернете без предварительной примерки. Отображаемый размер продукта очень помогает, хотя часто это просто приблизительная оценка. Даже знание своего размера для аналогичных предметов одежды не означает, что другие предметы одежды того же размера также подойдут нам. Что еще хуже, размеры одежды также представлены во всех вариантах. Как и рядовой покупатель, мы в Otto Group постоянно сталкиваемся с проблемой сравнения различных типов размеров одежды: Как соотносится размер 44 немецкого бренда с размером XL американского бренда? Или футболки 42 года на свитера 42 года?

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

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

2. Данные

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

Здесь покупатель А купил и оставил у себя два товара: товар X размера 40 и товар Y размера 42. Таким образом, его покупательский профиль состоит из двух наборов размеров товаров (X, 40) и (Y, 42). Мы будем часто использовать это обозначение.

3.Основная идея

Предположим, у нас есть два предмета одежды и их размеры в магазине (X, 42) и (Y, 44). В настоящее время мы не можем точно сказать, если (X, 42) ‹ (Y, 44), потому что размеры трудно сравнивать (как объяснялось выше). Наша главная цель — изучить универсальное сопоставление размеров S для всех размеров продуктов, что позволит нам лучше сравнивать размеры для всего ассортимента одежды.

Если продукт X размера 42 меньше или теснее для большинства покупателей, чем продукт Y размера 44, наше сопоставление S должно дать: S(X, 42) ‹ S (Д, 44).

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

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

4. Парное ранжирование

Чтобы превратить наш набор данных в обучающий набор с несколькими попарно ранжированными выборками, давайте сначала посмотрим на профиль одного клиента B из наших фиктивных данных. Этот покупатель купил три предмета одежды:
(Z, 16), (X, 44) и (Y, 44).

  • Допущение 1. Первое допущение, лежащее в основе нашего подхода, заключается в том, что два предмета одежды, купленные и хранящиеся у одного и того же покупателя, должны иметь одинаковый размер одежды. Таким образом, для нашего единственного клиента B мы можем заключить, что, например. (X, 44) = (Y, 44), потому что он купил эти два предмета и оставил их у себя.
    Это общее предположение, конечно, во многих случаях неверно, поскольку, например, люди также покупают товары за свои деньги. партнеров и детей. Однако этот шум должен нивелироваться при использовании большого количества исторических данных, и для большинства профилей мы можем предположить, что сохраненные продукты имеют схожий размер.
  • Допущение 2. Второе допущение заключается в том, что для одного и того же предмета одежды более высокий размер одежды означает больший общий размер. Таким образом, можно смело предположить, что (Y, 44) ‹ (Y, 46) или (X, 42) ‹ (X, 44), так как эти соотношения задаются производителем и всегда должны быть верными.

При этих двух предположениях мы можем создать следующий каскад:
(X, 42) ‹ (X, 44) = (Y, 44) ‹ (Y, 46)

И, следовательно, следующие попарно ранжированные кортежи:
(X, 44) ‹ (Y, 46)
(X, 42) ‹ (Y, 44)

Конечно, мы могли бы создать намного больше сэмплов, но эти два, как правило, труднее всего изучить, поскольку они ближе всего друг к другу.

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

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

  1. Выберите два случайных кортежа размера продукта из каждого профиля клиента.
  2. Приравняйте обе выборки (см. предположение 1).
  3. Создайте каскад ранжирования (см. предположение 2).
  4. Выберите попарные образцы, расположенные ближе всего друг к другу.

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

Наша функция выборки может быть легко расширена для включения двоичного целевого столбца для каждого парного кортежа. Мы создали тройки с попарным ранжированием (A, B, T), где A и B — кортежи размера продукта, а T — бинарная цель, которая сигнализирует, больше ли B, чем A.

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

5. Модель Pytorch

Давайте сначала посмотрим на нашу простую модель:

Для каждой обучающей тройки (A, B, T) мы прогнозируем вероятность того, что кортеж размера продукта B больше, чем кортеж размера продукта A. Для нашей модели мы интерпретируем универсальное отображение размеров S, которое мы ищем как одномерное вложение. Таким образом, мы используем слой встраивания pytorch. Результат нашей модели определяется следующим образом: Sigmoid(S(B)-S(A))

Внутренний член S(B)-S(A) в идеале должен стать очень большим, если B больше, чем A, что также эквивалентно T=1. Если, с другой стороны, A больше, чем B, то разница вложения S(B)-S(A) должна стать отрицательной.

Мы используем сигмовидную функцию активации, чтобы превратить разницу встраивания в вероятность, чтобы ответить на вопрос: Какова вероятность того, что B больше, чем A?. Это также позволяет нам просто использовать бинарную кросс-энтропийную потерю в качестве нашей функции потерь при обучении.

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

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

Чтобы использовать нашу функцию выборки, мы создаем новую большую партию обучающих выборок для каждой итерации модели. Это можно сделать с помощью класса IterableDataset в pytorch:

6. Давайте тренироваться

Во время обучения мы отслеживаем две метрики:

  • Точность: правильно ли мы предсказали цель?
  • Монотонность: для одного продукта X мы должны быть в состоянии узнать, что, например,
    S(X, 40) ‹ S(X, 42) ‹ S(X, 44) ‹ S(X, 46).
    Мы отслеживаем соотношение для скольких продуктов выполняется это условие монотонности. В идеале этот показатель должен приближаться к 1.

Для наших фиктивных данных процесс обучения выглядит так:

После обучения мы можем извлечь изученные вложения:

Как мы видим, наш критерий монотонности верен для X и Y, но не для Z. Однако результаты сильно различаются при каждом запуске, потому что мы используем такой крошечный фиктивный набор данных. Мы достигли оценки монотонности около 90%, используя наш большой набор реальных данных с миллионами покупок и тысячами продуктов.

7. Случаи использования

Наш подход к универсальному размеру помог нам найти расположение всех размеров, применимое ко всем статьям. Вариантов использования множество:

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

8. Улучшения и замечания

Есть еще возможности для улучшения.

  • Одно универсальное сопоставление размеров может ввести в заблуждение при сравнении обуви и одежды для верхней части тела. В зависимости от варианта использования может потребоваться обучение нескольких моделей для разных ассортиментов одежды. Точно так же можно обучить два разных пространства для встраивания женской и мужской моды.
  • Показатель монотонности также можно улучшить, добавив обучающие триплеты для одного продукта, такие как ((X, 42), (X, 44), 1) или ((Y, 40), (Y, 38), 0).
  • Модель pytorch может быть излишней. Можно было бы легко пропустить pytorch и получить правила обновления для такой модели вручную. Это может быть даже быстрее в конце. Однако для процесса моделирования, который часто является методом проб и ошибок, нам понравилась гибкость, которую нам дали pytorch и skorch.

9. Блокнот Юпитер

Чтобы воссоздать эти результаты, вы можете использовать наш гист: https://gist.github.com/jfeigl-ottogroup/79559d3f8105b389534dfc6876fddb33.