Это руководство представляет собой попытку показать, как модели графического машинного обучения (ML) можно применять к задаче рекомендации на основе сеанса с использованием платформы PyG. Сопутствующий блокнот Colab можно найти здесь. Автор Ын Джи Сон, часть курсового проекта Stanford CS224W.

Содержание:
1. Обзор
2. Методы
3. Сеансы в виде графиков
4. Набор данных
5. Конвейер данных< br /> 6. SR-GNN
7. Результат

Обзор

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

  1. Идентификация и отслеживание пользователей по уникальным идентификаторам может быть неприемлемым для малых и средних компаний.
  2. Отпечатки пальцев и файлы cookie браузера могут быть нестабильными в разных средах.
  3. Каждый раз мы можем посещать каждый сайт с разными намерениями! Например, на Amazon пользователь может сегодня искать лыжи, а завтра — ноутбуки.

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

В этом руководстве мы изучим модель графового машинного обучения под названием Рекомендации на основе сеансов с графовыми нейронными сетями (SR-GNN), предложенную для этой задачи. Мы будем изучать SR-GNN при реализации модели с помощью инфраструктуры PyG. Мы также будем обучать модель, используя набор данных RetailRocket.

Q) Что такое PyG framework?
A) PyG framework — это самая популярная графовая инфраструктура глубокого обучения, построенная на основе PyTorch, которая предлагает удобные элементы для использования графовых наборов данных и разработки графовых моделей ML. Этот учебник предлагает только краткий обзор библиотеки PyG. Если вы хотите узнать больше о фреймворке, ознакомьтесь с этой документацией.

Методы

Существующие методы

Существующие методы рекомендаций на основе сеансов можно разделить на несколько категорий.

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

Методы глубокого обучения. С развитием глубокого обучения также активно предлагались рекуррентные нейронные сети (RNN), поскольку они показали впечатляющую производительность для задач, связанных с последовательными данными, например. обработка естественного языка и анализ видео. Некоторые из наиболее известных моделей включают GRU4Rec и NARM. GRU4Rec была одной из первых моделей, которые применили RNN к домену рекомендаций на основе сеансов [8]. NARM применил механизм внимания к RNN, чтобы зафиксировать подразумеваемое последовательное поведение и цели пользователей [9]. Однако эти последовательные модели имеют некоторые ограничения. Во-первых, их предсказания часто основаны на последнем взаимодействии. Во-вторых, трудно принять во внимание повторное потребление.

График машинного обучения. Недавние разработки в области машинного обучения графов также вдохновили несколько нейронных сетей графов (GNN) на задачи рекомендаций. Однако, согласно статье SR-GNN, которую мы изучаем сегодня, многие репрезентативные алгоритмы, такие как Node2Vec [11], DeepWalk [12] и LINE [13], нацелены на неориентированные графы, что затрудняет применение алгоритмов к рекомендательным задачам на основе сеансов. .

СР-ГНН

Сегодня мы изучим одну из классических моделей рекомендаций на основе сеансов: SR-GNN. Согласно оригинальной статье, явно моделируя поведение пользователей при переключении между узлами (элементами), эта модель может фиксировать повторяющиеся и сложные взаимодействия в рамках сеанса лучше, чем традиционные последовательные сети, такие как ванильная RNN [1]. . Кроме того, по сравнению с другими моделями графового машинного обучения, SR-GNN может моделировать направленные графы сеансов, поскольку использует ячейки GRU.

В документе утверждается, что он показал лучшую производительность, чем другие базовые версии, такие как GRU4Rec или NARM, для двух наиболее популярных наборов данных для рекомендаций на основе сеансов [7]. Мало того, эта статья была принята на конференцию AAAI 2019 года и по данным Google Scholar по состоянию на 9 декабря 2021 года цитировалась 408 раз!

Сессии как графики

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

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

Давайте посмотрим на пример. В приведенном ниже примере сеанса представлена ​​последовательность взаимодействия пользователя с элементами с идентификаторами 248676, 8775, 246453, 8775 и 193150 в указанном порядке. Мы видим, что графическое представление позволяет увидеть, что пользователь был весьма заинтересован в 8775 и сравнивал несколько продуктов. Возможно, предметы 8775, 246453 и 193150 были в чем-то похожи. Графическое представление позволяет извлекать такую ​​информацию из коротких, но сложных последовательностей сеансов.

Набор данных RetailRocket

Пример набора данных, который мы собираемся использовать в этом руководстве, — это набор данных RetailRocket [2]. Он был выпущен как набор данных о соревнованиях Kaggle и использовался в качестве эталонного набора данных для нескольких рекомендательных документов, основанных на сессиях. Розничная торговля — это одна из областей, где наиболее часто используются рекомендательные системы на основе сеансов, потому что часто пользователи используют один и тот же веб-сайт с разными намерениями в каждом сеансе.

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

Для простоты мы используем только события «просмотр» для нашей задачи прогнозирования. Мы также отфильтровываем посетителей, которые посетили веб-сайт только один или два раза. Поскольку нам нужна информация только об идентификаторах предметов, мы также удаляем раздел visitorid. Затем мы группируем события от одного и того же пользователя в течение двухчасового окна в «сеанс». Окончательный предварительно обработанный набор данных представляет собой список сеансов.

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

Конвейер данных

Как мы храним каждый сеанс?

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

Как передать Data экземпляров в нашу модель?

Для этого мы будем использовать PyG InMemoryDatasetand DataLoaderclass. PyG InMemoryDataset предлагает удобные функции для работы с наборами графических данных. Во-первых, если вы попытаетесь передать torch_geometric.data.Data экземпляров, используя обычные классы torch.data.Dataset и torch.data.DataLoader, он немедленно запросит у вас пользовательскую функцию сопоставления для сопоставления pyg.data.Data экземпляров в пакет. Библиотека PyG сделает это за вас!

Наш пользовательский код класса InMemoryDataset выглядит следующим образом. В коде edge_index представляет собой двумерный тензор с двумя столбцами, где первый столбец каждой строки представляет отправителя, а второй столбец представляет узел получателя ребра. y — это целевая метка каждого сеанса, которая является последним элементом, с которым взаимодействовали в реальном сеансе. x — это список исходных уникальных идентификаторов предметов.

Обратите внимание, что Dataclass PyG объединяется в один экземпляр класса oneBatch, который в основном представляет собой один большой сопоставленный граф (один экземпляр Data). Эта деталь пригодится позже.

СР-ГНН

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

Вложения узлов

Сначала мы должны создать начальные вложения наших узлов. Мы просто встроим уникальные идентификаторы элементов во вложения в векторной форме. Об этом позаботится слой torch.nn.Embedding.

Слой нейронной сети с закрытым графом (GG-NN)

Нам нужно уточнить эти первоначальные вложения в лучшие представления. Для этого SR-GNN использует (1) информацию о соединении сеансов и (2) структуру GG-NN.

Построение матрицы смежности

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

Приведенная выше матрица представляет собой матрицу смежности для данного ориентированного графа слева. Левая половина матрицы представляет «исходящие градусы», а правая половина представляет «входящие градусы». Затем матрица смежности преобразуется для создания активаций от ребер в обоих направлениях.

Ячейка ГРУ

Затем активации передаются в ячейку со следующими уравнениями:

Эти уравнения кажутся вам знакомыми? Это всего лишь слой Gated Recurrent Unit (GRU)! SR-GNN использует вариант GG-NN из статьи «Gated Graph Sequence Neural Networks» [6], который, в свою очередь, использует в своей архитектуре ячейку GRU.

В документе GG-NN утверждается, что использование ячейки GRU позволяет модели изучать изменяющиеся представления данных графа при последовательной обработке данных. Для нашей SR-GNN имеет смысл принять структуру GG-NN, поскольку наша модель нацелена на последовательные наборы данных.

Использование класса PyG MessagePassing

Давайте поместим это в коды. Библиотека PyG уже предлагает класс torch_geometric.nn.conv.GatedGraphConv, который реализует документ GG-NN, но SR-GNN использует немного другой слой графа закрытого сеанса. Чтобы быть точным, оригинальный GG-NN объединяет нулевую матрицу справа от матрицы признаков, но нам это не нужно для нашей сети. Поэтому мы будем реализовывать наш пользовательский слой свертки с вентилируемым графом, используя MessagePassingclass PyG (более подробную информацию вы можете найти в этой документации).

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

  1. Распространение сообщений для создания и использования матрицы смежности (self.propagate). В этой части класс PyG MessagPassing предлагает функциональные возможности для удобной реализации GNN. Нам нужно только правильно определить функции message() и message_and_aggregate() и вызвать propagate() .
  2. Ячейка ГРУ (self.gru). В этой части мы будем повторно использовать класс torch.nn.GRUCell из библиотеки PyTorch.

Нам часто нужно определить сложные функции передачи сообщений и функции агрегации для реализации GNN, но наш уровень графа закрытого сеанса довольно прост. Наши узлы будут передавать свои вложения узлов соседним узлам, поэтому наша функция message() будет напрямую передавать x_j себе. В наших графах нет сложных весов ребер или стратегий агрегирования, поэтому функция message_and_aggregate() просто умножит нашу матрицу смежности на вложения узлов, а класс torch_geometric.nn.conv.MessagePassing создаст матрицу смежности внутри себя из edge_index, которое мы передаем в self.propagate(), без какой-либо дополнительной работы с нашей стороны!

Окончательный код класса слоя GatedSessionGraphConv выглядит так:

Затем мы используем этот класс передачи сообщений внутри класса SRGNN следующим образом:

class SRGNN(nn.Module):
    def __init__(self, hidden_size, n_items):
        super(SRGNN, self).__init__()
        ...
        self.gated = GatedSessionGraphConv(self.hidden_size)
        ...
     def forward(self, data):
        ...
        v_i = self.gated(embedding, edge_index)
        ...

Создание встраивания сеанса

Теперь у нас есть хорошее представление каждого узла на наших графиках. Как мы можем использовать это для создания вложений каждого сеанса (графа)? В документе предлагается создать «локальное встраивание» и «глобальное встраивание» сеанса для создания окончательного «гибридного встраивания».

Локальное встраивание — это просто встраивание последнего элемента сеанса.

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

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

Уравнения просты, но может быть немного сложно поместить их в код и вычислить все в векторной форме.

Вы помните, что экземпляры класса Data PyG в пакете объединяются в единый граф (экземпляр Batch)? Мы можем сопоставить каждый узел обратно с отдельными графами, вызвав.batch для экземпляра, который сопоставляет каждый узел с соответствующим идентификатором графа.

Таким образом, мы можем реализовать уравнения (6) и (7) следующим образом:

# (1)-(5)
v_i = self.gated(embedding, edge_index)
# Divide nodes by session
sections = list(torch.bincount(batch_map).cpu())
v_i_split = torch.split(v_i, sections)
v_n, v_n_repeat = [], []
for session in v_i_split:
    v_n.append(session[-1])
    v_n_repeat.append(
        session[-1].view(1, -1).repeat(session.shape[0], 1))
v_n, v_n_repeat = torch.stack(v_n), torch.cat(v_n_repeat, dim=0)
q1 = self.W_1(v_n_repeat)
q2 = self.W_2(v_i)

Вычисление баллов за предметы

Окончательные оценки каждого элемента вычисляются путем вычисления косинусного сходства между вложением сеанса (1 x d) и вложением всех 466 867 уникальных элементов (466 867 x d). В нашем случае результирующая ненормализованная оценка будет иметь форму (466867 x 1). Это представляет собой баллы по каждому пункту для данного сеанса.

# Unnormalized scores
z = torch.mm(self.embedding.weight, s_h.T).T
# We take softmax of the unnormalized scores
# Note that this line is not in the colab, since softmax function is
# already included in the `nn.CrossEntropyLoss()` class.
y_hat = F.softmax(z)

Окончательная модель

Наша окончательная модель выглядит так:

Результат

Приступаем к обучению! Если вы пропустили это, проверьте блокнот Colab для обучения конвейера. Это график потерь при обучении, который я получил:

Это означает, что для нашего разделения проверки наша модель могла точно предсказать тот самый элемент, который фактические пользователи щелкнули после данного сеанса, из 480 000 элементов в 22% случаев!

Давайте запустим эту модель на тестовом сплите. Я буду использовать точность Hit@K в качестве оценочной метрики, так как это одна из самых популярных оценочных метрик для задач рекомендаций. Метрика Hit@K подсчитывает количество случаев, когда наши K-ые элементы с наибольшим количеством баллов (K рекомендуемых элементов) содержали целевой элемент. Моя лучшая модель получила следующие результаты:

  • Точность Hit@1: 20,45%
  • Точность Hit@10: 43,72%
  • Точность Hit@20: 49,64%

Захватывающий! Наша модель может точно предсказать следующий элемент, на который нажмет пользователь, с вероятностью 20%. Кроме того, если бы наша модель рекомендовала 10 товаров на выбор, пользователь предпочел бы один из рекомендованных товаров в 44% случаев!

Я надеюсь, что это руководство было полезно для всех, кто интересуется использованием методов машинного обучения графов для задач рекомендаций на основе сеансов. Если у вас есть вопросы, направляйте их на ejsung[at]stanford.edu.

При создании этого руководства я ссылался на репозитории github по userbehavioranalysis [3] и CRIPAC-DIG [10], но коды, статьи и изображения Colab были полностью написаны или созданы мной для более простой реализации и объяснения.

Я благодарю преподавательский состав Fall CS224W 2021 года за их увлеченное преподавание и конструктивные отзывы об этом руководстве.

Ссылка

[1] Ву, Шу и др. «Рекомендация на основе сеанса с графовыми нейронными сетями». Материалы конференции AAAI по искусственному интеллекту. Том. 33. №01. 2019.

[2] Набор данных RetailRocket. https://www.kaggle.com/retailrocket/ecommerce-dataset

[3] https://github.com/userbehavioranalysis/SR-GNN_PyTorch-Geometric

[4] Слайд лекции Stanford 2021Fall CS224W, неделя 1, слайд 40.

[5] http://colah.github.io/posts/2015-08-Understanding-LSTMs/

[6] Ли, Юцзя и др. «Нейронные сети с последовательностью графов». препринт arXiv arXiv:1511.05493 (2015 г.).

[7] Ву, Шивен и др. «Графические нейронные сети в рекомендательных системах: опрос». препринт arXiv arXiv:2011.02260 (2020 г.).

[8] Хидаси, Балаш и др. «Рекомендации на основе сеансов с рекуррентными нейронными сетями». препринт arXiv arXiv:1511.06939 (2015 г.).

[9] Ли, Цзин и др. «Неврально-внимательная рекомендация на основе сеанса». Материалы конференции ACM 2017 года по управлению информацией и знаниями. 2017.

[10] https://github.com/CRIPAC-DIG/SR-GNN

[11] Гровер, Адитья и Юре Лесковец. «node2vec: масштабируемое изучение функций для сетей». Материалы 22-й международной конференции ACM SIGKDD по открытию знаний и интеллектуальному анализу данных. 2016.

[12] Пероцци, Брайан, Рами Аль-Рфу и Стивен Скиена. «Deepwalk: онлайн-обучение социальным представлениям». Материалы 20-й международной конференции ACM SIGKDD по открытию знаний и интеллектуальному анализу данных. 2014.

[13] Тан, Цзянь и др. «Линия: встраивание крупномасштабной информационной сети». Материалы 24-й международной конференции по всемирной паутине. 2015.