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

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

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

Материал подготовлен по мотивам статьи Марка Ко, Exclude from Your Taste Profile, опубликованной в Spotify Engineering 20 октября 2023 года. Это краткий пересказ истории и авторский разбор её применения в электронной торговле, а не полный перевод оригинала.

#Как Spotify дал человеку возможность поправить алгоритм

Инженер Spotify Марк Ко столкнулся с проблемой лично: музыка для сна вытесняла из рекомендаций то, что ему хотелось слушать днём. В 2019 году он занялся этим во время внутренней Hack Week.

В феврале 2023 года появилась функция Exclude from your taste profile — «Исключить из профиля вкуса». Через меню плейлиста пользователь мог уменьшить его влияние на персонализацию.

Решение учитывало источник прослушивания. Исключались прошлые и будущие воспроизведения из выбранного плейлиста; та же композиция, включённая отдельно, продолжала учитываться. Другие жанры система за пользователя не исключала.

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

Первый A/B-тест охватывал лишь часть инфраструктуры: представления пользователей в модели и подборку On Repeat. По сообщению Spotify, эксперимент дал положительные результаты и помог обосновать дальнейшую разработку. История создания функции →

Для нашей задачи здесь особенно интересна возможность уточнить смысл действия, сохранив само действие в истории.

#Часто пользоваться — не всегда хотеть ещё

Рекомендательная система редко получает аккуратно сформулированное пожелание: «Мне нравится вот это, но только в определённых обстоятельствах». Обычно ей приходится судить по поведению: что человек открыл, сколько времени провёл, к чему вернулся и за что заплатил.

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

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

Даже оплата не снимает неопределённость. Она подтверждает, что товар оказался достаточно нужен для покупки. Но не сообщает, кто будет им пользоваться и нужно ли предлагать похожее в следующем месяце.

Условно рекомендацию можно строить вокруг двух разных вероятностей:

  • P(купит товар сейчас | текущая задача) — полезна для помощи с сегодняшним выбором;
  • P(заинтересуется товаром позже | устойчивые предпочтения) — полезна для следующего визита.

Они могут сильно различаться. Человек охотно купит детский конструктор на день рождения племянника и совершенно не захочет видеть конструкторы на своей главной странице весь оставшийся год.

#Подарок — хороший сигнал для корзины и спорный для личного профиля

Представим отдельную ситуацию: посетитель выбирает кофемашину родителям. Он ищет модель с простым управлением, смотрит средства для очистки и добавляет подарочную упаковку.

Во время этого визита рекомендации аксессуаров вполне уместны. Они помогают завершить именно ту покупку, ради которой человек пришёл. Если полностью удалить все действия с кофемашиной из персонализации, система потеряет полезный контекст.

После покупки смысл истории меняется. Человек, возможно, вообще не пьёт кофе. Система, которая надолго записала ему интерес к кофемашинам, будет занимать первые позиции товарами, предназначенными другому человеку.

Один и тот же заказ полезен сразу нескольким процессам. Бухгалтерии нужен факт оплаты. Аналитике продаж — товар и сумма. Рекомендациям в корзине — совместимые дополнения. Модели постоянных интересов — ещё и понимание, насколько покупка характеризует самого клиента.

Одна покупка: подтверждённый заказ, текущая задача и постоянный интерес

Факт покупки сохраняется. Его значение для разных задач может различаться.

Отметка «Это подарок» поэтому может быть полезнее ещё одной сложной догадки алгоритма. Но использовать её нужно по смыслу. Она помогает определить получателя, а не делает товар неинтересным для покупателя: иногда люди дарят то, что нравится им самим, или регулярно покупают подарки в одной категории.

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

#Почему одинаковый вес событий может перекосить рекомендации

Рассмотрим упрощённый расчёт. В истории посетителя есть 10 действий, связанных с его собственным увлечением, и 40 действий во время выбора подарка. Числа условные; модель ниже нужна только для объяснения.

Если каждое действие получает одинаковый вес, на подарочную категорию приходится:

40 / (10 + 40) = 80% суммарного веса.

Так возникает сильный перекос. Человек долго выбирал подарок, и алгоритм принял тщательность выбора за силу постоянного интереса.

Теперь допустим, что для формирования долгосрочного профиля подарочные события получают вес 0,1. Их суммарный вес становится равен 4, а доля —

4 / (10 + 4) ≈ 29%.

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

Условный расчёт: изменение вклада подарочных событий в долгосрочный профиль

Иллюстрация простого взвешивания. Коэффициент 0,1 выбран для примера; это не описание алгоритма Spotify или Sales Ninja.

Реальные модели устроены сложнее счётчика действий: они могут учитывать порядок просмотров, свойства товаров, время и множество других признаков. Но сложность модели не отменяет исходный вопрос. Если обучающие данные называют временную задачу постоянным предпочтением, модель получает противоречивое обучение.

#Почему нельзя просто забывать старые покупки

Постепенно снижать влияние давних событий полезно. Старые интересы могут потерять актуальность, а новые — появиться. Но возраст события и его смысл — разные вещи.

Вчерашняя покупка подарка уже сегодня может быть плохим основанием для личной подборки. Зато годичной давности покупка принтера всё ещё помогает предложить совместимый картридж.

В первом случае нужно осторожнее переносить интерес между сессиями. Во втором — помнить владение устройством, хотя покупатель вряд ли собирается снова покупать принтер.

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

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

#Качество данных начинается раньше обучения модели

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

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

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

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

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

#Как понять, что рекомендации стали лучше

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

Изменение профиля лучше сравнивать в A/B-тесте на уровне пользователей: одна группа получает прежнюю логику, другая — новую. Разделение по отдельным визитам может смешать версии, если обе обновляют один профиль.

Основной показатель выбирают под задачу: например, выручку или прибыль на пользователя за одинаковый период наблюдения. Клики и добавления в корзину помогают объяснить результат, а отмены и возвраты — проверить, не улучшили ли мы ранние действия ценой плохих покупок.

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

#Где здесь товарные рекомендации и ML-ранжирование Sales Ninja

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

В Sales Ninja для этих задач есть два дополняющих друг друга продукта. Товарные рекомендации подбирают предложения для отдельных блоков — в карточке, корзине и на главной. ML-ранжирование по API определяет порядок уже переданного списка товаров: магазин получает результат модели и применяет его в своём интерфейсе.

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

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

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