Автороцентричное ранжирование. Доклад Яндекса о поиске релевантной аудитории для авторов Дзена

Важнее всего для сервиса Яндекс.Дзен — развивать и поддерживать платформу, которая соединяет аудитории с авторами. Чтобы быть привлекательной платформой для хороших авторов, Дзен должен уметь находить релевантную аудиторию для каналов, пишущих на любые темы, в том числе на самые узкие. Руководитель группы счастья авторов Борис Шарчилев рассказал про автороцентричное ранжирование, которое подбирает для авторов наиболее релевантных пользователей. Из доклада можно узнать о том, чем такой подход отличается от подбора релевантных айтемов — более популярного в рекомендательных системах.


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


— Коллеги, всем привет. Меня зовут Боря. Я занимаюсь качеством ранжирования в Дзене. Я уверен, что у нас один из самых интересных сервисов Яндекса, у нас очень крутое машинное обучение, и в следующие 17 минут я вас в этом постараюсь убедить.

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

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

qanzskuimea9hc8y66kn0h9hssg.jpeg

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

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

een80tjarg_yfrkcsi1rgyoh1ne.jpeg

Важно понимать, что Дзен уже очень большой. По данным Яндекс.Радара, число дневных читателей на конец прошлого года — примерно 11 млн в день. И даже, по некоторым данным, по данным того же Яндекс.Радара, мы в прошлом году впервые обошли по цитированию Яндекс.Новости. Это значит, что мы на полном серьезе делаем интернет, у нас очень серьезные задачи, их много, и мы очень ждем вашей помощи.

wmeceujreogtdcsemonqypheoiu.jpeg

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

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

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

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

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

avtx_9s-0plk0ku62fi372qvsqa.jpeg

Оказывается, что нам интересно заниматься примерно всем. Задач очень много. И пользы можно принести примерно везде, будь то какие-то инфраструктурные задачи. То есть нам интересно и увеличивать скорость доставки данных для ранжирования (чем более свежие у нас данные, тем более релевантные мы делаем рекомендации). Нам интересно ускорять время работы сервиса (чем быстрее работаем, тем лучше пользовательский экспириенс). Нам интересно повышать надежность. Нам важно, чтобы сервис был всегда доступен, всегда работал.

Нам важно улучшать ранжирование. То есть нам нужно как применять какие-нибудь новые модели машинного обучения, так и улучшать наши модели в других странах. Мы рекомендуемся не только в России, но и во многих других странах.

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

И очень важно — нам надо развивать нашу авторскую платформу. Это наше будущее, нам надо в нее вкладываться. Задач тут тоже очень много. В частности нам нужно уметь находить и бустить качественный контент. Нам важно показывать хорошие материалы, а не какой-то треш. Нам нужно уметь ранжировать новые форматы контента. У нас есть не только статьи, но и короткие видео, и посты, которые пользователи смотрят прямо в ленте. Все эти форматы нужно уметь ранжировать.

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

Давайте рассмотрим это на примере.

woyonxtv15n5batrgw15aefqthy.jpeg

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

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

yi-hfgy9sccz9smcfpklqblvn_i.jpeg

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

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

qhr1hrd1a4pxa-usmuyy_1krsac.jpeg

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

Как здесь быть?

cg14g9pi1y8hgl_pplqg30xzovo.jpeg

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

В обычном ранжировании, которое мы называем пользователецентричным, что нам интересно? Найти материал, который наиболее релевантен пользователю. Мы отвечаем на вопрос, что показать пользователю. В автороцентричном ранжировании мы как бы переворачиваем постановку задачи и говорим, что мы хотим показать данного автора, и вопрос в том, кому его показать, кому он наиболее релевантен. Отсюда и разница в метриках. В первом случае нас больше интересуют пользовательские метрики, то есть интегральные клики, интегральное время в Дзене, и т. д. Во втором же случае нас интересуют так называемые авторские метрики. Например, мы измеряем то, насколько хорошо живется в Дзене, например, bottom 10% авторов. Если им живется достаточно хорошо, то и все остальные и подавно будут счастливы.

9dsvhywttvke2g1tga-3lbw6mj8.jpeg

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

dhvd9dt4apy_wc1ohvzshl4uoke.jpeg

Сначала про интуицию того, что произошло. Вот у нас те же самые две карточки, одна из них в среднем более кликабельна, 20%, другая менее кликабельна, 1%. Теперь, если взять конкретного пользователя, возможна такая ситуация, что у него на более популярную карточку вероятность клика больше, чем на менее популярную. Скажем, 10% против 3%. Но так как в среднем вероятность клика на популярную карточку — 20%, а у пользователя — 10%, то он в среднем менее релевантен данной публикации, чем средний пользователь Дзена. А в другой ситуации наоборот: у него вероятность клика 3%, но в среднем у статьи — 1%. Поэтому он входит в более релевантную для статьи аудиторию, чем остальные пользователи Дзена. И ключевой инсайт здесь в том, что даже когда вероятность клика на статью меньше, с помощью такого фреймворка мы имеем шанс показать менее популярную статью, если пользователь входит в наиболее доверенное ядро для данной публикации.

rhstbaule5hhkmbwgiov4vsaxsi.jpeg

Тут есть, на самом деле, некоторая математика. Подробно не буду особо рассказывать, но можно доказать такое утверждение: если хочется, чтобы пользователи приходили к нам более-менее равномерно, то данный score, по которому мы ранжируем, то есть перцентиль, куда попадает каждый пользователь, будет распределен равномерно по пользователям. Это значит, что если все статьи ранжировать таким образом, то в среднем все соберут более-менее одинаковое количество показов. Не будет выбросов в десятки миллионов показов против 10 у каких-нибудь менее релевантных карточек. Таким образом, балансируя пользователецентричное и автороцентричное ранжирование, мы можем добиваться правильного соотношения счастья пользователей и счастья авторов.

dthye2ilefzks3syubg57lp3s1a.jpeg

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

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

3ljcjs8izgw1y66smeon0w2rsbi.jpeg

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

Я сейчас привел только один из примеров задач, которыми у нас можно заниматься. Разумеется, этих задач много, и с каждой из них нам нужна ваша помощь. Очень надеемся, что вы захотите у нас работать. Напоследок скажу пару слов о том, чего же мы ждем от стажеров и чего мы от них не ждем. От стажера мы ждем самого главного — умения писать код. У нет в сервисе все дата-саентисты, все ML-инженеры должны уметь делать полный цикл задач. Они должны уметь и имплементировать свое решение в production, и применять ML. То есть мы ожидаем, что вы умеете писать код на базовом уровне, понимаете подходы, знаете алгоритмы, структуры данных, основы машинного обучения.

Чего мы не ждем от стажеров — так это, в первую очередь, глубокого знания каких-то языков или фреймворков. То есть если вы не знаете, как работают корутины в Python — ничего страшного, мы вас всему научим. И мы не ждем от вас большого опыта. Мы ждем от вас знаний, желания работать. Если нет опыта — ничего страшного. Всему научим, и все будет хорошо. Спасибо!

© Habrahabr.ru