Поиск по сайту:

Глубокое погружение в графовые нейронные сети


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

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

Основные выводы

  • Графовые нейронные сети (GNN) отлично справляются с моделированием отношений внутри взаимосвязанных данных, что делает их идеальными для задач, где важны структура и зависимости.
  • Графовые нейронные сети (GNN) обобщают традиционные методы глубокого обучения на графовые структуры, позволяя обучаться на узлах, ребрах и их связности.
  • Популярные архитектуры GNN, такие как графовые сверточные сети (GCN), графовые сети с вниманием (GAT) и GraphSAGE, предлагают различные способы агрегации и распространения информации между узлами.
  • Применение GNN в реальном мире охватывает анализ социальных сетей, прогнозирование свойств молекул, рекомендательные системы, выявление мошенничества и графы знаний.
  • Реализация GNN стала доступной благодаря современным фреймворкам, таким как PyTorch Geometric, который упрощает обработку данных, передачу сообщений и построение моделей.
  • Практическая реализация демонстрирует рабочий процесс GNN, включая загрузку графовых данных, определение модели, обучение и оценку результатов.
  • Графовые нейронные сети (GNN) продолжают быстро развиваться, а новые достижения улучшают масштабируемость, эффективность и производительность при работе с все более крупными и сложными графами.

Что такое графовые нейронные сети?

Графовые нейронные сети, или GNN, являются относительно новым типом нейронных сетей, которые могут работать с данными, структурированными как графы. Графы, по сути, представляют собой набор объектов, которые отображаются в виде узлов, и связи между этими объектами, представленные в виде рёбер, соединяющих узлы. GNN могут работать как с ориентированными графами, где рёбра имеют направление, так и с неориентированными графами, где рёбра не имеют конкретного направления. Размер и форма этих графов также могут значительно различаться. Архитектура GNN состоит из нескольких слоёв, каждый из которых получает информацию от предыдущего слоя. Мы подаём в GNN граф, представленный в виде набора узлов и рёбер, а также их соответствующих признаков. То, что мы получаем на выходе, — это набор вложений узлов для каждого узла во входном графе. Эти вложения представляют собой признаки, которые сеть изучила для каждого узла. Вместо того чтобы работать только с векторами, матрицами или тензорами, как обычная нейронная сеть, GNN могут работать с данными, структурированными в виде полноценного графа. Это делает их особенно гибкими при работе с сетевыми данными, такими как социальные сети, молекулярные структуры или транспортные системы. Математика, задействованная здесь, сложна, но основная идея заключается в том, что они итеративно проходят по графу, передавая сообщения между узлами для изучения полезных представлений.

Как работают графовые нейронные сети?

Графовые нейронные сети, или GNN, это сети, которые изучают закономерности между узлами в сети. Основная идея заключается в том, что каждый узел передает сообщения своим соседним узлам, делясь информацией о себе.

  • В графовой нейронной сети каждый узел обменивается информацией с узлами, к которым он подключен, что помогает модели постепенно понять полную структуру графа.
  • Каждый узел создаёт «сообщение», используя свои собственные признаки и признаки соседних узлов.
  • В то же время соседние узлы генерируют и отправляют свои собственные сообщения обратно.
  • Когда узел получает эти сообщения, он обновляет своё внутреннее состояние, агрегируя всю поступающую информацию.
  • Этот повторяющийся обмен сообщениями позволяет знаниям распространяться по графу, позволяя узлам узнавать о частях графа, находящихся за пределами их ближайших соседей.
  • Накладывая несколько слоев этого процесса, графовые нейронные сети могут изучать более сложные и глубокие зависимости.
  • С каждым добавленным слоем модель создает более богатые и содержательные представления признаков графа.

Реализация графовой нейронной сети в PyTorch

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

Набор данных Cora является популярным эталоном, используемым исследователями, работающими с обучением представлений графов. Этот набор данных включает множество научных публикаций, разделённых на семь категорий, таких как «Case Based», «Genetic Algorithms», «Neural Networks», «Probabilistic Methods», «Reinforcement Learning» и «Rule Learning». Набор данных Cora существует уже некоторое время и остаётся популярным ресурсом для многих проектов в этой области. Он предоставляет возможность оценить, насколько эффективно ваша модель может анализировать как текстовое содержание документов, так и взаимосвязанную сеть цитирований между ними. Многие значимые статьи по графовым нейронным сетям использовали Cora для оценки производительности по этим двум задачам. Она построена в виде графа, где публикации являются узлами, а ссылки между ними — ребрами, соединяющими узлы. Каждому документу соответствует вектор признаков, представляющий его содержание. Задача здесь состоит в том, чтобы разработать модель, которая сможет анализировать граф ссылок, векторы содержания и отношения между ними, чтобы предсказать, к которому из семи классов принадлежит любая данная публикация.

Предварительная обработка данных

Мы устанавливаем библиотеку PyTorch Geometric с помощью команды:

pip install torch_geometric

Затем мы можем использовать библиотеку PyTorch Geometric для загрузки и предварительной обработки набора данных.

from torch_geometric.datasets import Planetoid
import torch_geometric.transforms as T

dataset = Planetoid(root='data/Cora', name='Cora', transform=T.NormalizeFeatures())

Класс Planetoid загружает набор данных Cora и нормализует векторы признаков. Мы можем получить предварительно обработанные данные с помощью этого набора данных, который предоставляет объект Data с следующими атрибутами:

  • x: матрица признаков узлов размером ‘(num_nodes, num_features)’
  • edge_index: матрица соединений рёбер формы «(2, num_edges)»
  • y: вектор меток узлов размерностью «(num_nodes)»
  • train_mask, val_mask, test_mask: булевы маски, показывающие, какие узлы используются для обучения, проверки и тестирования.

Архитектура модели

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

import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv

class GNN(torch.nn.Module):
    def __init__(self, in_channels, hidden_channels, out_channels):
        super(GNN, self).__init__()
        # Define the first graph convolutional layer
        self.conv1 = GCNConv(in_channels, hidden_channels)
        # Define the second graph convolutional layer
        self.conv2 = GCNConv(hidden_channels, out_channels)
        # Define the linear layer
        self.linear = torch.nn.Linear(out_channels, out_channels)

    def forward(self, x, edge_index):
        # Apply the first graph convolutional layer
        x = self.conv1(x, edge_index)
        # Apply the ReLU activation function
        x = F.relu(x)
        # Apply the second graph convolutional layer
        x = self.conv2(x, edge_index)
        # Apply the ReLU activation function
        x = F.relu(x)
        # Apply the linear layer
        x = self.linear(x)
        # Apply the log softmax activation function
        return F.log_softmax(x, dim=1)
  • В приведённом выше коде мы импортировали torch и torch.nn.functional, чтобы получить доступ к некоторым полезным модулям и функциям нейронных сетей. Затем мы определили класс GNN, наследующийся от torch и nn.Module.
  • В методе init мы определили два сверточных слоя с использованием модуля GCNConv из PyTorch Geometric. Это позволяет легко реализовывать графовые свертки. Мы добавили простой линейный слой.
  • Прямой проход сначала пропускает вход через два сверточных слоя, каждый раз применяя активацию ReLU. Затем он проходит через линейный слой и, наконец, через log softmax, чтобы сжать выходные данные.

Всего несколькими строками кода мы можем построить прекрасную маленькую графовую нейронную сеть!

Очевидно, это простой пример, но мы можем видеть, как PyTorch и PyTorch Geometric позволяют быстро создавать прототипы и совершенствовать архитектуры графовых нейронных сетей. Слои GCNConv делают очень простым включение графовой структуры в наши модели.

Тренировка

Для обучения мы будем использовать функцию потерь кросс-энтропии и оптимизатор Adam. Мы можем разделить данные на обучающую, валидационную и тестовую выборки, используя эти маски на объекте Data.

# Set the device to CUDA if available, otherwise use CPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Define the GNN model with the specified input, hidden, and output dimensions, and move it to the device
model = GNN(dataset.num_features, 16, dataset.num_classes).to(device)
# Define the Adam optimizer with the specified learning rate and weight decay
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

# Define the training function
def train():
    # Set the model to training mode
    model.train()
    # Zero the gradients of the optimizer
    optimizer.zero_grad()
    # Perform a forward pass of the model on the training nodes
    out = model(dataset.x.to(device), dataset.edge_index.to(device))
    # Compute the negative log-likelihood loss on the training nodes
    loss = F.nll_loss(out[dataset.train_mask], dataset.y[dataset.train_mask])
    # Compute the gradients of the loss with respect to the model parameters
    loss.backward()
    # Update the model parameters using the optimizer
    optimizer.step()
    # Return the loss as a scalar value
    return loss.item()

# Define the testing function
@torch.no_grad()
def test():
    # Set the model to evaluation mode
    model.eval()
    # Perform a forward pass of the model on all nodes
    out = model(dataset.x.to(device), dataset.edge_index.to(device))
    # Compute the predicted labels by taking the argmax of the output scores
    pred = out.argmax(dim=1)
    # Compute the training, validation, and testing accuracies
    train_acc = pred[dataset.train_mask].eq(dataset.y[dataset.train_mask]).sum().item() / dataset.train_mask.sum().item()
    val_acc = pred[dataset.val_mask].eq(dataset.y[dataset.val_mask]).sum().item() / dataset.val_mask.sum().item()
    test_acc = pred[dataset.test_mask].eq(dataset.y[dataset.test_mask]).sum().item() / dataset.test_mask.sum().item()
    # Return the accuracies as a tuple
    return train_acc, val_acc, test_acc

# Train the model for 500 epochs
for epoch in range(1, 500):
    # Perform a single training iteration and get the loss
    loss = train()
    # Evaluate the model on the training, validation, and testing sets and get the accuracies
    train_acc, val_acc, test_acc = test()
    # Print the epoch number, loss, and accuracies
    print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}, Train Acc: {train_acc:.4f}, Val Acc: {val_acc:.4f}, Test Acc: {test_acc:.4f}')

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

Вычислите точность модели GNN

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

@torch.no_grad()
def compute_accuracy():
    model.eval()
    out = model(dataset.x.to(device), dataset.edge_index.to(device))
    pred = out.argmax(dim=1)
    correct = pred.eq(dataset.y.to(device)).sum().item()
    total = dataset.y.shape[0]
    accuracy = correct / total
    return accuracy

accuracy = compute_accuracy()
print(f"Accuracy: {accuracy:.4f}")

В этом случае точность модели на наборе данных Cora составила 0,8006. Это означает, что примерно в 80% случаев модель смогла правильно предсказать класс. Это довольно хорошо, но не идеально. Точность даёт нам быстрое, общее представление о том, насколько хорошо работает модель. Но чтобы действительно понять, где она успешна, а где испытывает трудности, нужно копнуть глубже.

Для более глубокого понимания эффективности модели рекомендуется учитывать и другие метрики оценки, такие как точность, полнота, F1-мера и матрица ошибок. Эти метрики предоставляют представление о работе модели по различным аспектам, например, по правильной идентификации положительных и отрицательных случаев и обработке несбалансированных наборов данных. Поэтому, хотя точность 80% является хорошим показателем, прежде чем объявлять эту модель по-настоящему успешной, важно учитывать контекст. Только по точности нельзя полностью оценить происходящее внутри модели. Однако это хороший отправной пункт для оценки её производительности.

Оценка

Мы можем оценить, как работает GNN, используя такие показатели, как точность, полнота, отзыв и F1-оценка. Но мы также можем визуализировать встраивания узлов, которые обучает модель, с помощью t-SNE. Этот метод преобразует высокоразмерные встраивания в 2D, что позволяет нам их визуализировать.

# Import the necessary libraries
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt

# Set the model to evaluation mode
model.eval()

# Perform a forward pass of the model on the dataset
out = model(dataset.x.to(device), dataset.edge_index.to(device))

# Apply t-SNE to the output feature matrix to obtain a 2D embedding
emb = TSNE(n_components=2).fit_transform(out.cpu().detach().numpy())

# Create a figure with a specified size
plt.figure(figsize=(10,10))

# Create a scatter plot of the embeddings, color-coded by the true labels
plt.scatter(emb[:,0], emb[:,1], c=dataset.y, cmap='jet')

# Display the plot
plt.show()

Примечание: читатель может запустить приведённый выше код. Он отобразит диаграмму рассеяния, которую можно интерпретировать. Код использует t-SNE для отображения обученных векторных представлений узлов на 2D-диаграмме рассеяния, что является умным способом визуализации данных высокой размерности. Давайте разберём, что происходит:

  • Каждая точка на графике представляет узел в наборе данных. Оси x и y — это две размерности, в которые t-SNE сжал эмбеддинги. Цвет каждой точки отражает истинную метку соответствующего узла в наборе данных.
  • У узлов с похожими векторными представлениями (эмбеддингами) должны быть похожие метки, поэтому они будут группироваться вместе на графике. С другой стороны, узлы с сильно отличающимися эмбеддингами, вероятно, будут иметь разные метки, поэтому они окажутся дальше друг от друга.
  • В целом, график наглядно показывает отношения между узлами на основе их обученных встраиваний. Можно увидеть формирующиеся группы, которые, должно быть, имеют какую-то общую схожесть. Это удобный способ заглянуть внутрь модели и понять, как она организует концепции.

Потенциальные проблемы и аспекты, требующие учета

  • С 2708 узлами и 5429 ребрами датасет Cora считается относительно небольшим. Это может повлиять на эффективность GNN, что потребует применения более продвинутых методов, таких как увеличение данных и перенос обучения.
  • Набор данных Cora состоит из одного типа узлов и одного типа связей, что делает его однородной сетью. Это может ограничивать применимость GNN при работе с более сложными сетями, которые включают разнообразные типы узлов и связей.
  • Выбор подходящих значений гиперпараметров, таких как количество скрытых слоев, количество скрытых единиц и скорость обучения, может существенно повлиять на производительность GNN и требует тщательной настройки.

Часто задаваемые вопросы

  • 1. Что такое графовая нейронная сеть (GNN)?

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

  • 2. Чем ГНС отличается от традиционной нейронной сети?

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

  • 3. Для каких типов задач используются GNN?

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

  • 4. Что такое передача сообщений в GNN?

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

  • 5. Хорошо ли ГНС масштабируются на очень большие графы?

Масштабирование может быть сложным из-за увеличения объёма памяти и соседней области. Такие методы, как семплирование (GraphSAGE), мини-пакеты и распределённое обучение, помогают справляться с этим.

  • 6. Какие программные библиотеки лучше всего подходят для реализации GNN?

Популярные фреймворки включают PyTorch Geometric (PyG) и Deep Graph Library (DGL), оба предоставляют готовые слои и инструменты для создания моделей GNN.

  • 7. Подходят ли ГНС для использования в реальном времени?

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

  • 8. Могут ли ГНС работать с динамическими или изменяющимися графами?

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

  • 9. Какая предварительная обработка данных требуется для GNN?

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

  • 10. Являются ли GNN интерпретируемыми?

Интерпретируемость улучшается с помощью таких инструментов, как механизмы внимания и GNNExplainer, которые выделяют влиятельные узлы и ребра.

Заключение

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

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

Мы подготовили набор данных с использованием библиотеки PyTorch Geometric, нормализовав векторы признаков и разделив данные на обучающую, валидационную и тестовую выборки. Затем мы построили простую графовую нейронную сеть с использованием слоёв графовой свёртки, за которыми следовал линейный классификатор, и обучали её с помощью функции потерь кросс-энтропии и оптимизатора Adam. Наконец, мы оценили производительность модели, измерив её точность.

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

Ресурсы

  • Создание нейронных сетей с нуля: Часть 1
  • Что такое глубокое обучение? Руководство для начинающих по нейронным сетям
  • Объяснение архитектур глубокого обучения: ResNet, InceptionV3, SqueezeNet
  • PyTorch 101: Изучаем глубокое обучение с PyTorch

Спасибо, что учитесь вместе с сообществом Linux-Console.net.