Course
Uma introdução abrangente às redes neurais de grafos (GNNs)
O que é um gráfico?
Um gráfico é o tipo de estrutura de dados que contém nós e bordas. Um nó pode ser uma pessoa, um lugar ou um objeto, e as bordas definem a relação entre os nós. As bordas podem ser direcionadas e não direcionadas com base em dependências direcionais.
No exemplo abaixo, os círculos azuis são nós e as setas são bordas. A direção das bordas define as dependências entre dois nós.
Imagem do autor
Vamos aprender sobre o conjunto de dados complexo do Graph: Rede de Músicos de Jazz. Ele contém 198 nós e 2742 bordas. No gráfico da comunidade abaixo, as diferentes cores dos nós representam várias comunidades de músicos de jazz e as bordas que as conectam. Há uma rede de colaboração em que um único músico tem relacionamentos dentro e fora da comunidade.
Gráfico da comunidade plotado pela Jazz Musicians Network
Os gráficos são excelentes para lidar com problemas complexos com relações e interações. Eles são usados em reconhecimento de padrões, análise de redes sociais, sistemas de recomendação e análise semântica. A criação de soluções baseadas em gráficos é um campo totalmente novo que oferece insights valiosos sobre conjuntos de dados complexos e interligados.
Gráficos com o NetworkX
Nesta seção, aprenderemos a criar um gráfico usando o NetworkX.
O código abaixo foi influenciado pelo blog de Daniel Holmberg sobre Graph Neural Networks em Python.
- Criar o objeto DiGraph "H" da redex
- Adicionar nós que contenham rótulos, cores e tamanhos diferentes
- Adicione bordas para criar uma relação entre dois nós. Por exemplo, "(0,1)" significa que 0 tem uma dependência direcional de 1. Criaremos relações bidirecionais adicionando "(1,0)"
- Extrair cores e tamanhos na forma de listas
- Trace o gráfico usando a função draw do networkx
import networkx as nx
H = nx.DiGraph()
#adding nodes
H.add_nodes_from([
(0, {"color": "blue", "size": 250}),
(1, {"color": "yellow", "size": 400}),
(2, {"color": "orange", "size": 150}),
(3, {"color": "red", "size": 600})
])
#adding edges
H.add_edges_from([
(0, 1),
(1, 2),
(1, 0),
(1, 3),
(2, 3),
(3,0)
])
node_colors = nx.get_node_attributes(H, "color").values()
colors = list(node_colors)
node_sizes = nx.get_node_attributes(H, "size").values()
sizes = list(node_sizes)
#Plotting Graph
nx.draw(H, with_labels=True, node_color=colors, node_size=sizes)
Na próxima etapa, converteremos a estrutura de dados de um gráfico direcional para um gráfico não direcional usando a função to_undirected().
#converting to undirected graph
G = H.to_undirected()
nx.draw(G, with_labels=True, node_color=colors, node_size=sizes)
Por que é difícil analisar um gráfico?
As estruturas de dados baseadas em gráficos têm desvantagens, e os cientistas de dados devem entendê-las antes de desenvolver soluções baseadas em gráficos.
- Existe um gráfico em um espaço não euclidiano. Ele não existe no espaço 2D ou 3D, o que dificulta a interpretação dos dados. Para visualizar a estrutura no espaço 2D, você deve usar várias ferramentas de redução de dimensionalidade.
- Os gráficos são dinâmicos; eles não têm uma forma fixa. Pode haver dois gráficos visualmente diferentes, mas eles podem ter representações de matriz de adjacência semelhantes. Isso dificulta a análise de dados usando ferramentas estatísticas tradicionais.
- O tamanho e a dimensionalidade grandes aumentarão a complexidade do gráfico para interpretações humanas. A estrutura densa com vários nós e milhares de bordas é mais difícil de entender e extrair insights.
O que é uma Graph Neural Network (GNN)?
As redes neurais de grafo são tipos especiais de redes neurais capazes de trabalhar com uma estrutura de dados de grafo. Elas são altamente influenciadas pelas redes neurais convolucionais (CNNs) e pela incorporação de gráficos. Os GNNs são usados na previsão de nós, bordas e tarefas baseadas em gráficos.
- As CNNs são usadas para classificação de imagens. Da mesma forma, os GNNs são aplicados à estrutura do gráfico (grade de pixels) para prever uma classe.
- As redes neurais de recorrência são usadas na classificação de textos. Da mesma forma, os GNNs são aplicados a estruturas de gráficos em que cada palavra é um nó em uma frase.
As GNNs foram introduzidas quando as redes neurais convolucionais não conseguiram obter resultados ideais devido ao tamanho arbitrário do gráfico e à estrutura complexa.
Imagem de Purvanshi Mehta
O gráfico de entrada passa por uma série de redes neurais. A estrutura do gráfico de entrada é convertida em incorporação de gráfico, o que nos permite manter informações sobre nós, bordas e contexto global.
Em seguida, o vetor de recursos dos nós A e C é passado pela camada da rede neural. Ele agrega esses recursos e os passa para a próxima camada - neptune.ai.
Leia nosso tutorial de aprendizagem profunda ou faça nosso curso de Introdução à aprendizagem profunda para saber mais sobre algoritmos e aplicativos de aprendizagem profunda.
Tipos de redes neurais de grafos
Há vários tipos de redes neurais, e a maioria delas tem alguma variação de redes neurais convolucionais. Nesta seção, aprenderemos sobre as GNNs mais populares.
- As redes convolucionais de grafos (GCNs) são semelhantes às CNNs tradicionais. Ele aprende os recursos inspecionando os nós vizinhos. Os GNNs agregam vetores de nós, passam o resultado para a camada densa e aplicam a não linearidade usando a função de ativação. Em resumo, ele consiste em convolução de gráfico, camada linear e função de ativação sem aprendizagem. Há dois tipos principais de GCNs: Redes convolucionais espaciais e redes convolucionais espectrais.
- As redes com codificador automático de gráficos aprendem a representação de gráficos usando um codificador e tentam reconstruir os gráficos de entrada usando um decodificador. O codificador e os decodificadores são unidos por uma camada de gargalo. Eles são comumente usados na previsão de links, pois os Auto-Encoders são bons em lidar com o equilíbrio de classes.
- As Recurrent Graph Neural Networks (RGNNs) aprendem o melhor padrão de difusão e podem lidar com gráficos multi-relacionais em que um único nó tem várias relações. Esse tipo de rede neural gráfica usa regularizadores para aumentar a suavidade e eliminar o excesso de parametrização. Os RGNNs usam menos poder de computação para produzir melhores resultados. Eles são usados na geração de textos, tradução automática, reconhecimento de fala, geração de descrições de imagens, marcação de vídeos e resumo de textos.
- As GGNNs (Gated Graph Neural Networks) são melhores do que as RGNNs na execução de tarefas com dependências de longo prazo. As Redes Neurais de Grafos Gated aprimoram as Redes Neurais de Grafos Recorrentes adicionando um nó, uma borda e portas de tempo em dependências de longo prazo. Semelhante às GRUs (Gated Recurrent Units), as portas são usadas para lembrar e esquecer informações em diferentes estados.
Se você estiver interessado em saber mais sobre Redes Neurais Recorrentes (RNNs), confira o curso da DataCamp. Ele apresentará a você várias arquiteturas de modelos de RNNs, estruturas do Keras e aplicativos de RNN.
Tipos de tarefas de redes neurais de grafos
A seguir, descrevemos alguns dos tipos de tarefas GNN com exemplos:
- Classificação de gráficos: usamos isso para classificar os gráficos em várias categorias. Suas aplicações são a análise de redes sociais e a classificação de textos.
- Classificação de nós: essa tarefa usa rótulos de nós vizinhos para prever rótulos de nós ausentes em um gráfico.
- Previsão de links: prevê o link entre um par de nós em um gráfico com uma matriz de adjacência incompleta. É comumente usado para redes sociais.
- Detecção de comunidade: divide os nós em vários clusters com base na estrutura da borda. Ele aprende com os pesos das bordas, com a distância e com os objetos do gráfico de forma semelhante.
- Graph Embedding: mapeia gráficos em vetores, preservando as informações relevantes sobre nós, bordas e estrutura.
- Geração de gráficos: aprende com a distribuição de gráficos de amostra para gerar uma estrutura de gráficos nova, mas semelhante.
Imagem do autor
Desvantagens das redes neurais em grafo
Há algumas desvantagens no uso de GNNs. Compreendê-las nos ajudará a determinar quando usar o GNNa e como otimizar o desempenho de nossos modelos de aprendizado de máquina.
- A maioria das redes neurais pode se aprofundar para obter melhor desempenho, enquanto as GNNs são redes superficiais, em sua maioria com três camadas. Isso nos impede de obter o desempenho mais avançado em grandes conjuntos de dados.
- As estruturas do gráfico estão mudando constantemente, o que dificulta o treinamento de um modelo nele.
- A implementação do modelo na produção enfrenta problemas de escalabilidade, pois essas redes são computacionalmente caras. Se você tiver uma estrutura de gráfico grande e complexa, será difícil dimensionar os GNNs na produção.
O que é uma rede convolucional em gráfico (GCN)?
A maioria das GNNs são redes convolucionais de grafos, e é importante conhecê-las antes de entrar em um tutorial de classificação de nós.
A convolução em GCN é igual à convolução em redes neurais convolucionais. Ele multiplica os neurônios com pesos (filtros) para aprender com os recursos dos dados.
Ele atua como janelas deslizantes em imagens inteiras para aprender os recursos das células vizinhas. O filtro usa o compartilhamento de peso para aprender vários recursos faciais em sistemas de reconhecimento de imagens - Towards Data Science.
Agora, transfira a mesma funcionalidade para as redes convolucionais de gráfico, em que um modelo aprende os recursos dos nós vizinhos. A principal diferença entre o GCN e o CNN é que ele foi desenvolvido para trabalhar com estruturas de dados não euclidianas, em que a ordem dos nós e das bordas pode variar.
CNN vs GCN | Fonte da imagem
Saiba mais sobre as CNNs básicas seguindo o tutorial Redes Neurais Convolucionais (CNN) com o TensorFlow.
Há dois tipos de GCNs:
- As redes convolucionais de gráficos esp aciais usam recursos espaciais para aprender com gráficos localizados no espaço espacial.
- As redes convolucionais de grafo espectral usam a decomposição Eigen da matriz Laplaciana do grafo para a propagação de informações ao longo dos nós. Essas redes foram inspiradas na propagação de ondas em sinais e sistemas.
Como funcionam as GNNs? Criação de uma rede neural de gráfico com o Pytorch
Criaremos e treinaremos a convolução de gráfico espectral para um modelo de classificação de nós. O código-fonte está disponível no Workspace para que você experimente e execute seu primeiro modelo de aprendizado de máquina baseado em gráficos.
Os exemplos de codificação são influenciados pela documentação geométrica do Pytorch.
Primeiros passos
Instalaremos o pacote Pytorch, pois o pytorch_geometric foi desenvolvido com base nele.
!pip install -q torch
Em seguida, usaremos a versão do torch para instalar o torch-scatter e o torch-sparse. Depois disso, instalaremos a versão mais recente do pytorch_geometricdo GitHub.
%%capture
import os
import torch
os.environ['TORCH'] = torch.__version__
os.environ['PYTHONWARNINGS'] = "ignore"
!pip install torch-scatter -f https://data.pyg.org/whl/torch-${TORCH}.html
!pip install torch-sparse -f https://data.pyg.org/whl/torch-${TORCH}.html
!pip install git+https://github.com/pyg-team/pytorch_geometric.git
Conjunto de dados do Planetoid Cora
O Planetoid é um conjunto de dados de rede de citações do Cora, CiteSeer e PubMed. Os nós são documentos com vetores de recursos de 1433 palavras, e as bordas são links de citação entre artigos de pesquisa. Há 7 classes, e treinaremos o modelo para prever rótulos ausentes.
Vamos ingerir o conjunto de dados Planetoid Cora e normalizar em linha os recursos de entrada do saco de palavras. Depois disso, analisaremos o conjunto de dados e o primeiro objeto gráfico.
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures
dataset = Planetoid(root='data/Planetoid', name='Cora', transform=NormalizeFeatures())
print(f'Dataset: {dataset}:')
print('======================')
print(f'Number of graphs: {len(dataset)}')
print(f'Number of features: {dataset.num_features}')
print(f'Number of classes: {dataset.num_classes}')
data = dataset[0] # Get the first graph object.
print(data)
O conjunto de dados Cora tem 2708 nós, 10.556 bordas, 1433 recursos e 7 classes. O primeiro objeto tem 2708 máscaras de treinamento, validação e teste. Usaremos essas máscaras para treinar e avaliar o modelo.
Dataset: Cora():
======================
Number of graphs: 1
Number of features: 1433
Number of classes: 7
Data(x=[2708, 1433], edge_index=[2, 10556], y=[2708], train_mask=[2708], val_mask=[2708], test_mask=[2708])
Classificação de nós com GNN
Criaremos uma estrutura de modelo GCN que contém duas camadas GCNConv com ativação relu e uma taxa de abandono de 0,5. O modelo consiste em 16 canais ocultos.
Camada GCN:
A W(ℓ+1) é uma matriz de peso transferível na equação acima e Cw,v corresponde a um coeficiente de normalização fixo para cada borda.
from torch_geometric.nn import GCNConv
import torch.nn.functional as F
class GCN(torch.nn.Module):
def __init__(self, hidden_channels):
super().__init__()
torch.manual_seed(1234567)
self.conv1 = GCNConv(dataset.num_features, hidden_channels)
self.conv2 = GCNConv(hidden_channels, dataset.num_classes)
def forward(self, x, edge_index):
x = self.conv1(x, edge_index)
x = x.relu()
x = F.dropout(x, p=0.5, training=self.training)
x = self.conv2(x, edge_index)
return x
model = GCN(hidden_channels=16)
print(model)
>>> GCN(
(conv1): GCNConv(1433, 16)
(conv2): GCNConv(16, 7)
)
Visualização da rede GCN não treinada
Vamos visualizar a incorporação de nós de redes GCN não treinadas usando sklearn.manifold.TSNE e matplotlib.pyplot. Ele plotará um nó de 7 dimensões incorporando um gráfico de dispersão 2D.
%matplotlib inline
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
def visualize(h, color):
z = TSNE(n_components=2).fit_transform(h.detach().cpu().numpy())
plt.figure(figsize=(10,10))
plt.xticks([])
plt.yticks([])
plt.scatter(z[:, 0], z[:, 1], s=70, c=color, cmap="Set2")
plt.show()
Avaliaremos o modelo e, em seguida, adicionaremos dados de treinamento ao modelo não treinado para visualizar vários nós e categorias.
model.eval()
out = model(data.x, data.edge_index)
visualize(out, color=data.y)
Treinamento GNN
Treinaremos nosso modelo em 100 épocas usando a otimização Adam e a função Cross-Entropy Loss.
Na função de trem, temos:
- Limpar o gradiente
- Realizou um único passe para frente
- Calcular a perda usando nós de treinamento
- Calcular o gradiente e atualizar os parâmetros
Na função de teste, temos:
- Classe de nó prevista
- Rótulo da classe extraída com a maior probabilidade
- Verificou quantos valores foram previstos corretamente
- Criar uma taxa de precisão usando uma soma de previsões corretas dividida por um número total de nós.
model = GCN(hidden_channels=16)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
criterion = torch.nn.CrossEntropyLoss()
def train():
model.train()
optimizer.zero_grad()
out = model(data.x, data.edge_index)
loss = criterion(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
return loss
def test():
model.eval()
out = model(data.x, data.edge_index)
pred = out.argmax(dim=1)
test_correct = pred[data.test_mask] == data.y[data.test_mask]
test_acc = int(test_correct.sum()) / int(data.test_mask.sum())
return test_acc
for epoch in range(1, 101):
loss = train()
print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}')
GAT(
(conv1): GATConv(1433, 8, heads=8)
(conv2): GATConv(64, 7, heads=8)
)
.. .. .. ..
.. .. .. ..
Epoch: 098, Loss: 0.5989
Epoch: 099, Loss: 0.6021
Epoch: 100, Loss: 0.5799
Avaliação do modelo
Agora, avaliaremos o modelo em um conjunto de dados não visto usando a função de teste e, como você pode ver, obtivemos resultados muito bons com 81,5% de precisão.
test_acc = test()
print(f'Test Accuracy: {test_acc:.4f}')
>>> Test Accuracy: 0.8150
Agora, visualizaremos a incorporação de saída de um modelo treinado para verificar os resultados.
model.eval()
out = model(data.x, data.edge_index)
visualize(out, color=data.y)
Como podemos ver, o modelo treinado produziu um melhor agrupamento de nós para a mesma categoria.
Treinamento do modelo GATConv
Na segunda, substituiremos as camadas GCNConv por GATConv. A Graph Attention Networks usa camadas autoatencionais mascaradas para resolver as desvantagens da GCNConv e obter resultados de última geração.
Você também pode experimentar outras camadas GNN e brincar com otimizações, desistências e um número de canais ocultos para obter melhor desempenho.
No código abaixo, acabamos de substituir GCNConv por GATConv com 8 cabeças de atenção na primeira camada e 1 na segunda camada.
Também definiremos:
- taxa de evasão escolar para 0,6
- canais ocultos para 8
- taxa de aprendizado 0,005
Modificamos a função de teste para encontrar a precisão de uma máscara específica (valid, test). Isso nos ajudará a imprimir as pontuações de validação e teste durante o treinamento do modelo. Também estamos armazenando a validação e os resultados dos testes em um gráfico de linhas posteriormente.
from torch_geometric.nn import GATConv
class GAT(torch.nn.Module):
def __init__(self, hidden_channels, heads):
super().__init__()
torch.manual_seed(1234567)
self.conv1 = GATConv(dataset.num_features, hidden_channels,heads)
self.conv2 = GATConv(heads*hidden_channels, dataset.num_classes,heads)
def forward(self, x, edge_index):
x = F.dropout(x, p=0.6, training=self.training)
x = self.conv1(x, edge_index)
x = F.elu(x)
x = F.dropout(x, p=0.6, training=self.training)
x = self.conv2(x, edge_index)
return x
model = GAT(hidden_channels=8, heads=8)
print(model)
optimizer = torch.optim.Adam(model.parameters(), lr=0.005, weight_decay=5e-4)
criterion = torch.nn.CrossEntropyLoss()
def train():
model.train()
optimizer.zero_grad()
out = model(data.x, data.edge_index)
loss = criterion(out[data.train_mask], data.y[data.train_mask])
loss.backward()
optimizer.step()
return loss
def test(mask):
model.eval()
out = model(data.x, data.edge_index)
pred = out.argmax(dim=1)
correct = pred[mask] == data.y[mask]
acc = int(correct.sum()) / int(mask.sum())
return acc
val_acc_all = []
test_acc_all = []
for epoch in range(1, 101):
loss = train()
val_acc = test(data.val_mask)
test_acc = test(data.test_mask)
val_acc_all.append(val_acc)
test_acc_all.append(test_acc)
print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}, Val: {val_acc:.4f}, Test: {test_acc:.4f}')
.. .. .. ..
.. .. .. ..
Epoch: 098, Loss: 1.1283, Val: 0.7960, Test: 0.8030
Epoch: 099, Loss: 1.1352, Val: 0.7940, Test: 0.8050
Epoch: 100, Loss: 1.1053, Val: 0.7960, Test: 0.8040
Como podemos observar, nosso modelo não teve um desempenho melhor do que o GCNConv. Ele requer otimização de hiperparâmetros ou mais épocas para obter resultados de última geração.
Avaliação do modelo
Na parte de avaliação, visualizamos as pontuações de validação e teste usando o gráfico de linhas do matplotlib.pyplot .
import numpy as np
plt.figure(figsize=(12,8))
plt.plot(np.arange(1, len(val_acc_all) + 1), val_acc_all, label='Validation accuracy', c='blue')
plt.plot(np.arange(1, len(test_acc_all) + 1), test_acc_all, label='Testing accuracy', c='red')
plt.xlabel('Epochs')
plt.ylabel('Accurarcy')
plt.title('GATConv')
plt.legend(loc='lower right', fontsize='x-large')
plt.savefig('gat_loss.png')
plt.show()
Após 60 épocas, a precisão da validação e do teste alcançou um valor estável de 0,8+/-0,02.
Novamente, vamos visualizar o agrupamento de nós do modelo GATConv.
model.eval()
out = model(data.x, data.edge_index)
visualize(out, color=data.y)
Como podemos ver, a camada GATConv produziu os mesmos resultados no agrupamento da mesma categoria de nós.
Podemos reduzir o excesso de ajuste adicionando um segundo conjunto de dados de validação e melhorar o desempenho do modelo experimentando várias camadas GCN do pytoch_geometric.
O código-fonte do tutorial está disponível no DataCamp Workspace. Você só precisa clicar no botão Copy & Edit e executar o Jupyter Notebook.
Adicione a habilidade de aprendizagem profunda ao seu currículo fazendo o curso de habilidades de aprendizagem profunda em Python. Ele apresentará a você os algoritmos de aprendizagem profunda, o Keras, o Pytorch e a estrutura do Tensorflow.
Perguntas frequentes
Para que são usadas as Graph Neural Networks?
As Graph Neural Networks são aplicadas diretamente a conjuntos de dados de gráficos e você pode treiná-las para prever nós, bordas e tarefas relacionadas a gráficos. Ele é usado para classificação de gráficos e nós, previsões de links, agrupamento e geração de gráficos e classificação de imagens e textos.
O que é um gráfico em uma rede neural de gráficos?
Um gráfico é uma estrutura de dados que consiste em nós e as conexões entre os nós são chamadas de bordas. As bordas podem ser direcionadas e não direcionadas. Ele tem formas dinâmicas e estruturas multidimensionais. Por exemplo, nas mídias sociais, os nós são as pessoas do seu grupo de amigos, e as bordas são os relacionamentos entre vocês e os outros.
Qual é o poder das redes neurais de grafos?
As redes neurais de grafos superam as redes neurais convolucionais típicas (CNN) na classificação de imagens e nós. Muitas variantes de GNN obtiveram resultados de última geração em tarefas de classificação de nós e gráficos - openreview.net.
As redes neurais usam a teoria dos grafos?
Sim, as redes neurais estão intimamente relacionadas à teoria dos gráficos, que foi projetada para trabalhar com dados não euclidianos. Alguns deles são os próprios gráficos ou geram o gráfico.
O que são redes convolucionais de grafos?
As redes convolucionais de grafos são semelhantes às redes neurais convolucionais que funcionam com conjuntos de dados de grafos. Ele consiste em convolução gráfica, camada linear e ativação não linear. Os GNNs passam filtros pelo gráfico, inspecionando nós e bordas que podem ser usados para classificar nós dentro dos dados.
O que é um gráfico na aprendizagem profunda?
A aprendizagem profunda de gráficos é conhecida como aprendizagem profunda geométrica. Ele usa várias camadas de rede neural para obter melhor desempenho. É uma área de pesquisa ativa em que os cientistas estão tentando aumentar o número de camadas sem comprometer o desempenho.
Cursos de Python
Course
Recurrent Neural Networks (RNNs) for Language Modeling with Keras
Course
Introduction to Deep Learning with PyTorch
blog
O que são redes neurais?
tutorial
Uma introdução às redes neurais convolucionais (CNNs)
tutorial
Introdução às redes neurais profundas
tutorial
Criação de modelos de redes neurais (NN) em R
tutorial
Dominando a retropropagação: Um guia abrangente para redes neurais
tutorial