В этом посте я хотел бы познакомить вас с Graph Neural Networks (GNN), одним из самых захватывающих достижений в области машинного обучения (ML) на сегодняшний день. Действительно, многие наборы данных имеют внутреннюю структуру графа (социальные сети, обнаружение мошенничества, кибербезопасность и т. Д.). Сглаживание их и передача их традиционным архитектурам нейронных сетей - не лучший вариант. Введите GNN!

Вместо того, чтобы просто запустить образец записной книжки, давайте добавим в смесь несколько дополнительных ингредиентов. В реальной жизни данные вашего графика будут храниться в базе данных графиков, такой как Amazon Neptune. Вы извлекаете некоторые данные из этой базы данных, загружаете их в блокнот и поэкспериментируете с библиотекой машинного обучения, специализированной для GNN, такой как Deep Graph Library. Затем, когда вы выясните, какой алгоритм использовать, вы, вероятно, будете обучаться на полном наборе данных с помощью службы машинного обучения, такой как Amazon SageMaker.

Так как насчет того, чтобы я тебе все это показал? Давай перейдем к

Создание базы данных графов

Amazon Neptune - это полностью управляемая служба базы данных графов. Она поддерживает два языка запросов: Apache TinkerPop Gremlin и SPARQL от W3C.

Создание базы данных Neptune очень похоже на настройку RDS. Самый простой способ - использовать этот шаблон AWS CloudFormation. Если вы хотите использовать консоль AWS, процедура проста.

Через несколько минут моя база данных Neptune будет готова, и мы готовы загрузить данные.

Выбор набора данных

Воспользуемся пресловутым набором данных Zachary Karate Club. Он содержит 34 вершины и 78 двунаправленных ребер.

Как говорится, ребра представляют собой связи между учениками и двумя учителями (узлы 0 и 33). К сожалению, после ссоры учителей группу нужно разделить на две части. Это проблема, которую мы собираемся решить с помощью GNN: подробнее об этом через несколько минут!

Форматирование набора данных

Neptune принимает разные форматы файлов. Я выберу формат Гремлина:

  • Два файла CSV: один для вершин, другой для ребер.
  • Файл вершины: идентификатор (обязательно) плюс свойство имени (необязательно).
  • Файл ребра: идентификатор, исходная вершина, конечная вершина (все три обязательны).

Вершина - это просто причудливое слово для обозначения узла.

Конечно, вы можете (и должны) добавить гораздо больше свойств в оба файла.

Вот два файла в формате Gremlin.

Загрузка набора данных в Нептун

Нептун немного своеобразен, когда дело касается загрузки данных:

  1. База данных доступна только внутри VPC, на котором она размещена. Например, вы можете загружать данные с помощью экземпляра EC2 или лямбда-функции, находящейся в том же VPC.
  2. Neptune требуется конечная точка VPC для S3 в VPC. Это позволяет Neptune напрямую обращаться к S3 без использования общедоступных конечных точек. Создание конечной точки занимает несколько секунд, и вам нужно сделать это только один раз для каждого VPC.
  3. Загрузка данных инициируется вызовом curl. Ничего сверхъестественного, просто обратите внимание на параметры.

Хорошо, теперь давайте загрузим данные. Сначала я копирую два своих файла в корзину S3, размещенную в том же регионе, что и мой кластер Neptune.

$ aws s3 cp edges.csv s3://jsimon-neptune-useast-1/dgl/
$ aws s3 cp nodes.csv s3://jsimon-neptune-useast-1/dgl/

Затем настало время для вызова curl с использованием конечной точки кластера, видимой в консоли AWS или в выходных данных шаблона CloudFormation. Я использую регион us-east-1, вам, конечно, следует изменить его, если вы используете другой регион.

$ curl -X POST \
 -H ‘Content-Type: application/json’ \
 https://ENDPOINT:PORT/loader -d ‘
 {
 “source” : “s3://jsimon-neptune-useast-1/dgl/”,
 “format” : “csv”,
 “iamRoleArn” : “arn:aws:iam::123456789012:role/NeptuneRoleForS3”,
 “region” : “us-east-1”,
 “failOnError” : “FALSE”,
 “parallelism” : “MEDIUM”,
 “updateSingleCardinalityProperties” : “FALSE”
 }’

Если все настроено правильно, это возвращает статус HTTP 200 и идентификатор задания: я могу использовать его, чтобы проверить, нормально ли работает загрузка данных.

$ curl -G ‘https://ENDPOINT:PORT/loader/8af0f90a-9b72-4835-ab55-2de58918aa81'
{
 “status” : “200 OK”,
 “payload” : {
 “feedCount” : [
 {
 “LOAD_COMPLETED” : 2
 }
 ],
 “overallStatus” : {
   “fullUri” : “s3://jsimon-neptune-useast-1/dgl/”,
   “runNumber” : 1,
   “retryNumber” : 0,
   “status” : “LOAD_COMPLETED”,
   “totalTimeSpent” : 6,
   “startTime” : 1576847947,
   “totalRecords” : 146,
   “totalDuplicates” : 0,
   “parsingErrors” : 0,
   “datatypeMismatchErrors” : 0,
   “insertErrors” : 0
 }
 }

Что нужно проверить (в этом порядке), если у вас возникли проблемы: вы находитесь в том же VPC? Вы используете правильную конечную точку и порт для Нептуна? Группа безопасности для Нептуна в порядке? Роль IAM для Нептуна в порядке? Существует ли конечная точка S3 и разрешает ли она доступ (политика конечной точки)? Существует ли корзина S3 и разрешен ли доступ (политика корзины)? Существуют ли файлы и имеют ли они правильный формат? Если вы все еще не можете разобраться, AWS Forum for Neptune ждет вас;)

Теперь давайте подключимся к Нептуну и немного исследуем данные.

Изучение данных графика с помощью Gremlin

Вы можете запросить Нептун, используя разные языки. Я буду использовать Python с библиотекой gremlinpython.

$ pip3 install gremlinpython --user

Для подключения к базе данных Neptune требуется только ее конечная точка и ее порт.

Помните, что этот код должен запускаться в соответствующем VPC!

Теперь я могу исследовать граф с помощью языка запросов Гремлин. Вот несколько примеров.

В этом гораздо больше, но я остановлюсь на этом. Фактически, единственное, что мне нужно для построения графика в моем скрипте Deep Graph Library, - это список всех ребер.

Давайте возьмем это и сохраним в файл pickle.

Мы закончили обработку данных. А теперь давайте обучим GNN!

Обучение нашей первой GNN с помощью библиотеки Deep Graph

Deep Graph Library (DGL) - проект с открытым исходным кодом, упрощающий работу с моделями GNN. Он реализован на Python и поддерживает Apache MXNet и PyTorch.

$ pip3 install dgl --user

В следующих разделах я использую модифицированную версию этого учебника. Как обычно, ноутбук доступен на Github.

Я также записал видео, в котором просматриваю записную книжку и более подробно объясняю каждую строчку кода, которая вам, вероятно, небезразлична;)

Построение графика

Перво-наперво: нам нужно загрузить список ребер и построить наш граф.

Определение проблемы

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

Мы можем сформулировать это как задачу полууправляемой двоичной классификации:

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

Создание GNN

А теперь давайте построим саму GNN. Мы будем использовать сверточную сеть графов (GCN) со следующей структурой:

  • Два слоя GCN (мы определим их через минуту). Их цель - изучить параметры, которые помогут нам вычислить классы для всех узлов. При этом они также постепенно сжимают пространство функций до двух измерений (по одному для каждого класса).
  • Встроенный слой softmax для вывода вероятностей для двух классов.

Прямое распространение для уровня GCN выглядит так:

  • Установите входные характеристики для всех узлов,
  • Попросите каждый узел разослать свои элементы по всем его краям,
  • На каждом узле назначения обновите функции до суммы функций исходного узла (это секретный соус в GCN),
  • Примените линейное преобразование (представьте, что Y = WX + B… с матрицами), чтобы уменьшить размерность.

Как видно из приведенного ниже кода, DGL предоставляет простую семантику передачи сообщений для обработки связи между узлами.

Позвольте мне повторить центральную идею GCN: характеристики каждого узла будут многократно обновляться путем суммирования характеристик соседних узлов. Это похоже на операцию свертки, реализованную в нейронных сетях свертки (которая суммирует значения соседних пикселей), отсюда и название GCN.

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

Обучение GNN

Входные характеристики сохраняются в матрице (количество_узлов строк и количество_компонентов столбцов).

Здесь единственной функцией для каждого узла является вектор с горячим кодированием, представляющий идентификатор узла. Складывая все векторы узлов, мы получаем единичную матрицу размером node_count, которую мы можем легко построить с помощью torch.eye ().

DGL упрощает назначение узловых функций. В приведенном выше коде g.ndata ['h'] = inputs создает компонент с именем 'h' на каждом узле и устанавливает его в соответствующую строку в input. матрица.

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

Нам также необходимо определить метки: мы помечаем только узлы 0 и 33 соответственно классами 0 и 1.

Сам цикл обучения - это обычная работа PyTorch:

  • Запустите прямое распространение на графике и его входах,
  • Вычислить потерю между прогнозами и метками (только для помеченных узлов),
  • Запустите обратное распространение и обновите веса слоев.

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

Визуализация результатов

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

Одна картинка стоит тысячи слов!

Довольно круто! Это похоже на разумный раскол, не так ли?

Масштабное обучение с Amazon SageMaker

DGL доступен в Контейнерах глубокого обучения AWS, которые вы можете легко обучить на EC2, контейнерных сервисах и, конечно же, на Amazon SageMaker.

Если вы хотите узнать больше о сочетании DGL и SageMaker, вот несколько ресурсов:

Заключение

На сегодня все. Я надеюсь, что теперь у вас есть базовое представление о GNN и о том, как начать работу с ними на AWS.

Как всегда, спасибо за чтение. С удовольствием отвечу на вопросы здесь или в Твиттере.