В прошлых статьях я рассказывал, как мы научились сопоставлять товары из разных источников и заполнять карточку товара — характеристики, изображения, описание. А когда цены поставщиков, цены конкурентов и характеристики товара известны, логичным продолжением стал поиск информации об аналогах или просто похожих по своим свойствам товарах.
Использовать это можно разными способами, например, показать покупателю несколько похожих позиций на карточке товара, возможно, какая-то ему приглянется больше. Если чего-то нет в наличии, список похожих товаров в наличии тоже будет не лишним. Второй вариант — дать эту информацию сотрудникам колл-центра, чтобы они могли быстрее (или в принципе могли) предлагать аналоги, если запрашиваемого товара нет в наличии, или аналог лучше подходит под пожелания клиента.
Как определить, что товары похожи? Можно сравнить характеристики, чем больше совпало, тем более похожи товары. Но это не работает так просто, к сожалению. На практике оказывается, что, как правило, почти не бывает товаров, где заполнены все характеристики. 80% — хороший результат. Во-вторых, какие-то характеристики важнее, чем другие. Например, телевизор с диагональю в 65 дюймов совершенно не похож на телевизор с диагональю 22 дюйма, хотя у обоих по 2 USB-порта. Или, другой пример, металлический корпус и алюминиевый корпус гораздо ближе друг к другу, чем к пластику, хотя это три разных значения.
Таким образом, для подбора похожих товаров нам нужно решить следующие задачи:
- Назначить характеристикам веса. Размер диагонали — важно, количество USB-портов — менее важно.
- Определить область значений каждой характеристики, а на ней задать функцию расстояния между значениями.
- Определиться со стратегией обработки случаев, когда для одного товара характеристика известна, а для другого — нет.
- Имея расстояния между значениями всех характеристик, вычислить расстояние между товарами.
- Подумать над производительностью, вычисление всех пар расстояний имеет сложность И если вычисление 50 миллионов расстояний для 10 тысяч товаров не кажется большой проблемой, то 50 миллиардов для 300 тысяч — уже много.
Давайте эти задачи решать. В какой-то мере это будет исследовательская работа.
Как мы определяем веса характеристик
С весами мы использовали две основные идеи.
- Характеристики, которые влияют на цену — важные. Обратное не обязательно верно. Например, цвет мобильного телефона достаточно важен, но на цену почти не влияет.
- Чтобы выявить важные характеристики, которые не влияют на цену, мы предполагаем, что они, в среднем, лучше заполнены.
Дальше по каждой категории всем характеристикам мы назначаем веса. Для этого делаем следующее:
- Если характеристика числовая, то считаем корреляцию с ценой по Пирсону.
- Если перечисление с взаимоисключающим выбором (но не чисел), то упорядочиваем его элементы по средней цене товаров с таким значением, и считаем корреляцию с ценой по Спирмену.
- Если предусмотрен множественный выбор, то сводим его к множеству взаимоисключающих (да/нет), и считаем корреляцию каждого с ценой по Спирмену. Полученный коэффициент уменьшаем в зависимости от количества вариантов.
- Считаем процент заполненных значений для каждой из характеристик и увеличиваем или уменьшаем её вес, полученный ранее.
- Полученные значения могут использоваться в качестве весов, но на практике лучший результат получается, если их еще раз нелинейно преобразовать, сохраняя порядок.
На каждом из шагов есть свои нюансы, например, как считать цену, если в одном случае известны только розничные цены, в другом — только оптовые, а в третьем и те, и другие. Или какой-то из магазинов ошибся с ценой и продает тумбочку по цене шкафа из той же серии.
Как мы считаем расстояние между товарами
Выбирая алгоритм, по которому мы будем считать расстояние между значениями характеристики, нужно держать в уме то, как мы собираемся считать расстояние между товарами, имея расстояния между отдельными характеристиками и их вес. Моя интуиция подсказывает, что начать следует с просто расстояния в n-мерном пространстве, т.е. квадратного корня из суммы квадратов расстояний между характеристиками.
Дальше интуиция говорит, что в таком случае функция расстояния между значениями должна быть дистрибутивной, а еще лучше, если и неравенство треугольника будет выполняться. Доказать корректность таких требований я не могу, но эти условия мы будем соблюдать.
Тогда в качестве функции расстояния можно взять такие функции:
- В случае чисел — разницу их значений, деленную на фактическую длину диапазона всех значений. То есть, если минимальная глубина всех стиральных машин составляет 35 см, а максимальная — 75 см, то размер диапазона составит 40 см. Умножим это число на вес характеристики.
- В случае перечислений — разницу порядковых номеров значений (помните, мы их упорядочивали?), деленную на количество значений в перечислении. Это число мы тоже умножим на вес характеристики.
- Если характеристика в одном из товаров не заполнена, возьмем среднее значение попарных расстояний между всеми заполненными значениями этой характеристики в других товарах.
Теперь о производительности. На практике оказалось, что за приемлемое время (до 5 минут) мы можем посчитать попарные расстояния между 30 тысячами товаров. Но в то же время в некоторых категориях товаров больше, например, матрасов в каталоге может быть и сто тысяч, и в этом случае речь идет о увеличении затраченного времени в 10 раз.
Оптимизация этого случая выглядит так: мы упорядочиваем все товары по значению характеристики с наибольшим весом Это быстрее, чем Потом делим все товары на пересекающиеся группы (скажем, пересекающиеся на 20%), и считаем попарные расстояния внутри каждой группы. Таким образом, до 30 тысяч товаров в категории время обработки растет как а начиная с 30 тысяч — как
Результаты
Приведу несколько примеров результатов автоматического поиска похожих товаров по этому алгоритму (первым в таблице будет товар, для которого мы искали похожие товары)
Bosch WLT24540OE |
Bosch WLN24240OE |
Samsung WW80K6210RW |
Bosch WLT24460OE |
Siemens WS12T440OE |
Siemens WS12T540OE |
|
Тип | автоматическая |
автоматическая |
автоматическая |
автоматическая |
автоматическая |
автоматическая |
Исполнение | свободностоящее |
свободностоящее |
свободностоящее |
свободностоящее |
свободностоящее |
свободностоящее |
Загрузка белья | фронтальная |
фронтальная |
фронтальная |
фронтальная |
фронтальная |
фронтальная |
Максимальная загрузка | 7 |
7 |
8 |
7 |
7 |
7 |
Цвет | белый |
белый |
белый |
белый |
белый |
белый |
Класс энергопотребления | A+++ |
A+++ |
A+++ |
A+++ |
A+++ |
A+++ |
Класс отжима | B |
B |
B |
B |
B |
B |
Количество программ | 14 |
15 |
14 |
15 |
|
14 |
Цвет люка | серебристый |
белый |
черный |
серебристый |
серебристый |
серебристый |
Максимальная скорость отжима | 1200 |
1200 |
1200 |
1200 |
1200 |
1200 |
Инд. времени до конца программы | + |
|
+ |
+ |
+ |
|
Потребляемая мощность | 2300,00 |
|
|
2300,00 |
2300,00 |
|
Контроль дисбаланса | + |
+ |
+ |
+ |
+ |
+ |
Материал корпуса | пластик |
пластик |
пластик |
пластик |
пластик |
пластик |
Длина сетевого шнура | 1,75 |
1,75 |
|
|
|
|
Встраивание | |
|
|
|
|
под столешницу |
Количество барабанов | |
1 |
|
|
|
1 |
Выбор скорости отжима | + |
+ |
+ |
+ |
+ |
+ |
Отмена отжима | + |
+ |
+ |
+ |
+ |
+ |
Генератор пузырьков | |
|
+ |
|
|
|
Все программы | синтетика |
дополнительное полоскание |
дополнительное полоскание |
дополнительное полоскание |
дополнительное полоскание |
эко стирка |
Дата выхода на рынок | 2016 |
2016 |
2016 |
2015 |
|
|
Расход электроэнергии за цикл | 0,91 |
0,91 |
|
0,96 |
0,91 |
0,91 |
Расход воды за цикл | 38,00 |
38,00 |
|
38,00 |
38,00 |
38,00 |
Годовой расход воды | |
|
8100,00 |
|
|
8550,00 |
Класс стирки | A |
A |
A |
A |
A |
A |
Инверторная технология | + |
+ |
+ |
+ |
+ |
+ |
Прямой привод | — | — | |
— | — | — |
Уровень шума при стирке | 56 |
56 |
56 |
56 |
|
56 |
Уровень шума при отжиме | 77 |
78 |
75 |
78 |
76 |
77 |
Защита от протечек | — | — | — | — | — | — |
Обработка паром | — | — | — | — | — | — |
Открытие дверцы | |
|
|
|
|
угол 165° |
Диаметр люка | 32,00 |
|
|
32,00 |
32,00 |
32,00 |
Подсветка барабана | |
— | — | — | — | + |
Подключение к горячему водоснабжению | — | — | — | — | — | — |
Объём барабана | |
46,00 |
|
46,00 |
46,00 |
46,00 |
Управление | электронное |
электронное |
электронное |
электронное |
электронное |
электронное |
Индикация | цифровая |
цифровая |
|
цифровая |
цифровая |
цифровая |
Индикация ошибок | + |
+ |
+ |
+ |
+ |
+ |
Сопряжение со смартфоном | |
|
|
— | |
+ |
Сушка по таймеру | — | |
|
— | |
|
Контроль пенообразования | + |
+ |
|
|
+ |
+ |
Дозагрузка белья во время стирки | + |
|
|
|
+ |
+ |
Регулировка температуры стирки | + |
+ |
|
|
|
+ |
Звуковой сигнал | + |
+ |
+ |
+ |
+ |
+ |
Таймер отложенного старта | + |
+ |
+ |
+ |
+ |
+ |
Блокировка от детей | + |
+ |
+ |
+ |
+ |
+ |
Самоочистка | + |
|
|
— | |
+ |
Режим экономии времени | |
|
|
|
|
— |
Автоматическая дозировка моющего средства | |
|
|
|
|
|
Высота | 84,80 |
84,80 |
85,00 |
84,80 |
84,80 |
84,80 |
Ширина | 59,80 |
59,80 |
60,00 |
59,80 |
59,80 |
60,00 |
Глубина | 44,50 |
44,60 |
45,60 |
44,40 |
44,60 |
44,60 |
Глубина с люком | 48,60 |
48,60 |
|
48,60 |
47,40 |
|
Вес | 65,00 |
63,00 |
67,00 |
64,00 |
65,00 |
63,00 |
Страна-производитель | Россия |
Россия |
Китай |
Россия |
Россия |
Россия |
Hotpoint-Ariston WMTF 701 H CIS |
Hotpoint-Ariston WMTL 601 L CIS |
Gorenje WT62093 468938 |
Whirlpool AWE 7515/1 |
Zanussi ZWY51004WA |
|
Тип | автоматическая |
автоматическая |
автоматическая |
автоматическая |
|
Исполнение | свободностоящее |
свободностоящее |
свободностоящее |
свободностоящее |
|
Загрузка белья | вертикальная |
вертикальная |
вертикальная |
вертикальная |
|
Максимальная загрузка | 7 |
6 |
6 |
5.5 |
5.5 |
Цвет | белый |
белый |
белый |
белый |
белый |
Класс энергопотребления | A+ |
A+ |
A+ |
A+ |
A+ |
Класс отжима | C |
C |
C |
C |
C |
Количество программ | 18 |
18 |
18 |
11 |
|
Цвет люка | |
|
|
белый |
|
Максимальная скорость отжима | 1000 |
1000 |
900 |
1000 |
1000 |
Потребляемая мощность | 2100,00 |
2100,00 |
|
2100,00 |
|
Контроль дисбаланса | |
+ |
+ |
+ |
+ |
Материал корпуса | пластик |
пластик |
пластик |
пластик |
пластик |
Количество барабанов | |
|
|
1 |
|
Выбор скорости отжима | |
+ |
+ |
+ |
+ |
Отмена отжима | |
+ |
+ |
+ |
+ |
Все программы | дополнительное полоскание |
дополнительное полоскание |
спортивная обувь |
дополнительное полоскание |
|
Расход электроэнергии за цикл | 1,18 |
|
1,02 |
0,93 |
|
Расход воды за цикл | 50,00 |
|
48,00 |
48,00 |
|
Годовой расход воды | |
|
|
8674,00 |
|
Класс стирки | A |
A |
A |
A |
A |
Прямой привод | — | — | — | |
— |
Уровень шума при стирке | 59 |
59 |
59 |
59 |
58 |
Уровень шума при отжиме | 75 |
76 |
76 |
76 |
75 |
Защита от протечек | — | — | — | |
— |
Обработка паром | — | — | — | — | — |
Открытие дверцы | |
|
|
вверх |
|
Подсветка барабана | — | — | — | — | |
Подключение к горячему водоснабжению | |
|
|
— | |
Объём барабана | |
|
|
42,00 |
|
Управление | электронное |
электронное |
электронное |
|
электронное |
Индикация | светодиодная |
светодиодная |
цифровая |
цифровая |
светодиодная |
Индикация ошибок | + |
|
+ |
+ |
+ |
Сушка по таймеру | — | — | — | — | |
Класс сушки | A |
A |
|
|
|
Контроль пенообразования | |
+ |
|
+ |
|
Регулировка температуры стирки | |
|
|
+ |
|
Звуковой сигнал | + |
+ |
+ |
+ |
+ |
Таймер отложенного старта | + |
+ |
+ |
+ |
|
Блокировка от детей | — | |
|
— | |
Самоочистка | — | — | — | |
|
Высота | 90,00 |
90,00 |
85,00 |
90,00 |
89,00 |
Ширина | 40,00 |
40,00 |
40,00 |
40,00 |
40,00 |
Глубина | 60,00 |
60,00 |
60,00 |
60,00 |
60,00 |
Вес | |
58,00 |
58,00 |
58,00 |
58,00 |
Страна-производитель | Словакия |
|
Словения |
Словакия |
Польша |
По этим примерам видно, что, в принципе, алгоритм неплохо справился и подобрал в первом случае свободностоящие автоматические стиральные машины с горизонтальной загрузкой одинаковой глубины с примерно одинаковой максимальной загрузкой (я не большой специалист по стиральным машинам, но именно эти характеристики мне кажутся важными). Во втором случае — тоже свободностоящие автоматические стиральные машины, но с вертикальной загрузкой. Ширина и глубина предложенных вариантов одинаковая. В обоих случаях не предлагались активаторные или встраиваемые машины, а также компактные машины с настенным креплением, хотя они в каталоге есть.
Скорее всего, специалист по крупной бытовой технике смог бы выполнить эту работу лучше (мы обсуждали результаты в разных категориях с менеджерами по продажам, большинство вариантов они одобряли, но также предлагали варианты, которые мы в результат не включили). Примеряя результат на себя как покупателя, такие рекомендации я нахожу полезными, грубых непопаданий в ожидания я не нашел.
Таким образом, после реализации этого алгоритма, имея на входе только название товара, мы можем автоматически найти его у поставщиков и конкурентов, заполнить его характеристики, подобрать изображения и даже предложить аналоги. Это здорово упрощает работу контент-менеджеров и менеджеров по продажам.
Newm
Самая большая сложность возникает не когда куча примерно одинаковых товаров, а в той области, где их мало. Например выбрать подобные из 1000 телевизоров обычно не проблема как автоматом, так и вручную. А вот автоматом подобрать замену из 15 подвесов телевизоров — это может оказаться относительно легко вручную (если вбивальщики поставили расстояния между центрами креплений) и практически нереализуемо автоматически.
Мы как-то делали блок «с этим товаром покупают». С популярными товарами нет проблем, просто бери и сортируй, что же с ними покупали. А вот что делать со свежаком, который не продавали ни разу, это был некоторый квест, чтобы оказалось адекватно.
Razoomnick Автор
Да, все так. К сожалению, автоматом мы не сможем определить, что расстояние между креплениями — это критически важно, а бренд — нет. Но если свойств в категории немного, то расстояние все равно будет учитываться с большим относительным весом. У меня на этот счет есть такая идея: позволить человеку отмечать важные свойства для таких категорий. И для них мы не будем считать вес автоматически, а возьмем заведомо большое число.
Пока мы этого не делали, потому что рассматривали этот функционал как возможность получить полезный результат вообще без ручной работы, и оценить его востребованность клиентами. В дальнейшем будем экспериментировать, я думаю.