company_banner

Рекомендации друзей ВКонтакте: ML на эго-графах

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

    Меня зовут Женя Замятин, я работаю в команде Core ML ВКонтакте. Хочу рассказать, как устроены рекомендации, которые делают ближе пользователей самой крупной социальной сети рунета. 

    Обзор

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

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

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

    Ещё один важный метод рекомендаций — Adamic/Adar. В его основе лежит всё тот же анализ общих друзей, но с модификацией: авторы предлагают учитывать число друзей у «общего» друга. Чем больше это значение, тем меньше информации о релевантности он несёт.

    Кроме методов на основе анализа общих друзей, довольно распространены рекомендации на базе эмбеддингов. В Лаборатории искусственного интеллекта ВКонтакте в МФТИ мы провели исследование: сравнили эффективность разных подходов к задаче предсказания дружб в VK. Результаты совпали с нашим опытом — решения на базе графовых эмбеддингов у нас работают плохо. Учитывая это, мы стали развивать систему отбора кандидатов по пути анализа общих друзей.

    EGOML

    Общая схема нашего метода продолжает идеи числа общих друзей и Adamic/Adar. Финальная мера релевантности E(u, v), с помощью которой мы будем отбирать кандидатов, всё так же раскладывается в сумму по общим друзьям u и v. Ключевое отличие — в форме слагаемого под суммой: в нашем случае это мера ez_c(u, v).

    Сначала попробуем понять «физический» смысл меры ez_c(u, v). Представим, что мы взяли пользователя c и спросили у него: «Насколько вероятно, что два твоих друга, u и v, подружатся?» Чем больше информации для оценки он учтёт, тем точнее будет его предсказание. Например, если c сможет вспомнить только число своих друзей, его рассуждения могут выглядеть следующим образом: «Чем больше у меня друзей, тем менее вероятно, что случайные двое из них знакомы». Тогда оценка вероятность дружбы u и v (с точки зрения c) может выглядеть как 1/log(n), где n — число друзей. Именно так устроен Adamic/Adar. Но что если c возьмёт больше контекста?

    Прежде чем отвечать на этот вопрос, разберёмся, почему ez_c(u, v) важно определять через пользователя c. Дело в том, что в таком виде очень удобно решать задачу распределённо. Представим, что теперь мы разослали всем пользователям платформы анкету с просьбой оценить вероятность дружбы в каждой паре их друзей. Получив все ответы, мы можем подставить значения в формулу E(u, v). Именно так выглядит вычисление E(u, v) с помощью MapReduce:

    • Подготовка. Для каждого c выделяется тот контекст, который он будет учитывать для вынесения оценок. Например, в Adamic/Adar это будет просто список друзей.

    • Map. «Спрашиваем» у каждого c, что он думает про возможность дружбы в каждой паре его друзей. По сути, вычисляем ez_c(u, v) и сохраняем в виде (u, v) → ez_c(u, v) для всех u, v in N(c). В случае Adamic/Adar: (u, v) → 1/log|N(c)|.

    • Reduce. Для каждой пары (u, v) суммируем все соответствующие ей значения. Их будет ровно столько, сколько общих друзей у u и v.

    Таким образом мы получаем все ненулевые значения E(u, v). Заметим: необходимое условие того, что E(u, v) > 0, — существование хотя бы одного общего друга у u и v.

    Эго-граф Хоппера
    Эго-граф Хоппера

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

    Ключевая идея меры ez_c в том, что её можно сделать обучаемой. Для каждого пользователя c, его эго-графа и всех пар пользователей u, v внутри него мы можем посчитать много разных признаков, например:

    • число общих друзей u и v внутри эго-графа c;

    • число общих друзей u и c;

    • интенсивность взаимодействий между v и c;

    • время, прошедшее с последней дружбы между u и кем-либо из эго-графа c;

    • плотность эго-графа c;

    • и другие.

    Таким образом мы получим датасет с признаками. Но для обучения нужны ещё и метки. Пусть датасет был построен по состоянию графа на момент времени T. Тогда в качестве положительных примеров возьмём те пары пользователей, которые не были друзьями на момент T, но подружились к T + △T. А как отрицательные — все остальные, не подружившиеся, пары пользователей. Заметим: поскольку мы решаем задачу предсказания новых дружб, те пары пользователей, которые уже дружат на момент T, учитывать не нужно ни на обучении, ни на применении.

    В конечном счёте мы получаем датасет следующего вида:

    • для каждой пары пользователей u и v, а также их общего друга c, посчитаны признаки по эго-графу c;

    • пара пользователей u и v встречается в датасете ровно столько раз, сколько у них общих друзей;

    • все пары пользователей в датасете не являются друзьями на момент времени T;

    • для каждой пары u и v проставлена метка — подружились ли они в течение определённого промежутка времени начиная с T.

    По такому датасету мы и будем обучать нашу меру ez_c. В качестве модели выбрали градиентный бустинг с pairwise функцией потерь, где идентификатором группы выступает пользователь u.
    По сути, мера ez_c(u, v) определяется как предсказание описанной выше модели. Но есть один нюанс: при pairwise-обучении распределение предсказаний модели похоже на нормальное. Поэтому, если в качестве определения меры ez_c(u, v) взять «сырое» предсказание, может возникнуть ситуация, когда мы будем штрафовать финальную меру E(u, v) за общих друзей, так как значения предсказаний бывают отрицательными. Это выглядит не совсем логично — хочется, чтобы с ростом числа общих друзей мера E(u, v) не убывала. Так что поверх предсказания модели мы решили взять экспоненту:

    Такой подход хорошо себя показывает на небольших графах. Но чтобы применить его на реальных данных, необходимо выполнить ещё одно действие. Суть проблемы такая: мы не можем вычислять признаки и применять модель для каждой пары пользователей всех эго-графов — это слишком долго. Для решения мы придумали специальный трюк. Представим, что наш градиентный бустинг обучился таким образом, что каждое дерево использует признаки только одного пользователя: либо u, либо v. Тогда мы могли бы разделить весь ансамбль на две группы: к группе A мы бы отнесли деревья, которые используют только признаки пользователя u, к B — пользователя v. Предсказание такой модели можно представить в виде:

    Имея такую модель, мы могли бы получить предсказания для всех пар пользователей одного эго-графа быстрее. Достаточно применить модели A и B для каждого пользователя, а затем сложить соответствующие парам предсказания. Таким образом, для эго-графа из n вершин мы могли бы сократить число применений модели с O(n^2) до O(n). Но как получить такую модель, каждое дерево которой зависит только от одного пользователя? Для этого сделаем следующее:

    1. Исключим из датасета все признаки, которые одновременно зависят и от u и от v. Например, от признака «число общих друзей u и v внутри эго-графа c» придётся отказаться.

    2. Обучим модель A, используя только признаки на базе u, c и эго-графа c.

    3. Для обучения модели B оставим только признаки на базе v, c и эго-графа c. Также в качестве базовых предсказаний передадим предсказания модели A.

    Если объединим модели A и B, получим то что нужно: первая часть использует признаки u, вторая — признаки v. Совокупность моделей осмысленна, поскольку B была обучена «корректировать» предсказания A. Эта оптимизация позволяет ускорить вычисления в сотни раз и делает подход применимым на практике. Финальный вид ez_c(u, v) и E(u, v) выглядит так:

    Вычисление меры E в онлайне

    Заметим, что E(u, v) можно представить в виде:

    Эта формула — скалярное произведение разреженных векторов, индексами которых являются пользователи, а значениями — экспоненты предсказаний модели. Ненулевые значения здесь проставлены только у друзей u — по сути это просто списки друзей с дополнительными значениями. 

    При построении рекомендаций мы уже вычислили предсказания моделей для всех существующих дружб. Поэтому для каждого пользователя мы можем собрать векторы и сложить их в доступное онлайн key-value хранилище. После этого сможем получать значение E(u, v) для любой пары пользователей в онлайне простой операцией перемножения векторов. Это даёт возможность использовать E(u, v) как лёгкую функцию релевантности в нагруженных местах либо как дополнительный признак финальной модели ранжирования.

    Итог

    В результате система EGOML позволяет:

    1. Распределённо отбирать кандидатов для каждого пользователя в офлайне. Асимптотическая сложность оптимизированного алгоритма составляет O(|E|) вычислений признаков и применений модели, где |E| — число связей в графе. На кластере из 250 воркеров время работы алгоритма составляет около двух часов.

    2. Быстро вычислять меру релевантности E(u, v) для любой пары пользователей в онлайне. Асимптотическая сложность операции O(|N(u)| + |N(v)|).

    3. Улучшать качество рекомендаций, расширяя количество учтённых графов (по дружбам, скрытиям рекомендаций, отправленным сообщениям и другим графам) и добавляя всевозможные метки на рёбра и вершины. Например, интенсивность взаимодействий на ребре, дату образования ребра, город, место работы или учёбы пользователя.

    В конечном счёте мы перешли со способа отбора кандидатов с использованием Adamic/Adar к системе EGOML и внедрили в модель второй уровень признаков на основе меры E(u, v). И это позволило увеличить количество подтверждённых дружб со всей платформы на несколько десятков процентов.

    Благодарность

    Хочу сказать спасибо руководителю команды Core ML Андрею Якушеву за помощь в разработке метода и подготовке статьи, а также всей команде Core ML — за поддержку на разных этапах этой работы.

    ВКонтакте
    Один из самых высоконагруженных проектов рунета

    Комментарии 11

      +1
      Мне надавно ВК рекомендовал в друзья человека, который у меня есть ТОЛЬКО в whatsapp. У нас с ним нет и небылообщих друзей. Как так?
        0
        Мы используем ориентированные графы, и иногда, в том числе благодаря подходу с эго-графами, рекомендуемый пользователь влияет на то, что вы видите. Такое возможно благодаря тому, что мы используем разные типы связей между пользователями.
          0
          Единсвенное общее у меня с этим пользователем, это номер телефона и переписка в вотсап раз в 0,5 года
          +1
          Приложуха на смартфоне стоит? Скорее всего ВК просто угнал адресную книгу и предлагает «друзей» по номеру телефона.
            0
            Нет, я в вк только через комп захожу, на телефоне даже в браузере не открываю.
            +2
            Попробуйте в настройке «Кто может найти мой профиль при импорте контактов» выставить «Никто».
            Лично мне рекомендации друзей вообще не нужны, в VkOpt отключил их показ, как и рекламу.
              +1
              Версия: тот человек что-то сделал: дал доступ к телефонной книжке для ВК, добавил ваш профиль в закладки, может ещё что-то.
              +1
              Привет! Правильно я понимаю, что добавив в модель эго-графы пользователя C, вы таким образом неявно учитываете нахождение пользователей u и v в одном кластере (одной социальной группе), что не реализуется Adamic/Adar?

              Другой вопрос, временным разрешением и признаками. Для обучения используются метки добавления друзья с момента времени T, но у разных пользователей: «новичок», «социофоб», «с очень большим количеством друзей» и т.д., — разные изменения друзей за этот промежуток времени. Однако, мера ez_c(u, v) — обучается одинаково для всех или же там всё-таки неявно учитывается разный тип пользователей?
                0
                Привет!
                1) В целом да. Мы считаем разные признаки о возможной дружбе u и v в эго-графе c. Определить, что u и v из разных социальных кругов относительно c может помочь, например, признак — число общих друзей у v и c. Если мы строим предсказания для u, при этом u и c — одноклассники, а v — бабушка c (явно нерелевантный кандидат в ранжирование для u), то у v и c скорее всего будет мало общих друзей, а у u и c — много. Модель сможет выучить, что в таких случаях v — нерелевантный кандидат для u.

                2) Всю такую информацию про активность u можно также представить в виде признаков. Поэтому «поддержать» учет разных типов пользователей можно через такие признаки: модель будет понимать что u активный, поэтому у него будет одно поведение, либо наоборот — он редко добавляет друзей, поэтому поведение у него другое.
                  +1
                  1) Спасибо!

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

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

                  P.S. Спасибо за статью! Интересно и познавательно!
                0

                Помнится мне одна дождливая ночь Петербурга, осенью 2017 года, когда я искал удовольствие и утешение в ласках Милены и её коллеги по цеху(не помню имя) в одном злачном борделе. Который находился между магазином, в котором можно было купить алкоголь в первом часу ночи пьяному работяге, и съемной квартирой.
                Чудесная ночь с двумя жрицами любви и обилием выпивки прошла быстро, окончившись с первыми лучами солнца, которого не видно в сем прекрасном городе. Организм смог проснутся ближе к вечеру, с осознанием того, что вся сумма за квартиру благополучно потрачена.


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


                А вот вк… Вк мне до сих пор рекомендует мертвые сообщества, в которых последний пост выходил более года назад или полумертвую группу с четырьмя новыми постами за последние пол года. Аналогичная ситуация и с друзьями, но примем факт того, что я интроверт, общаясь с небольшим количеством людей, и само по себе предсказания алгоритмов для меня усложняются. Надеюсь, что вк и его команда значительно преуспеет в своих разработках. Ребят, успехов вам!

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

                Самое читаемое