图神经网络简明教程【GNN】

2023-12-13 18:54:43

图神经网络(GNN)是一组在图领域工作的深度学习方法。 这些网络最近已应用于多个领域,包括: 组合优化、推荐系统、计算机视觉—仅举几例。 这些网络还可用于对大型系统进行建模,例如社交网络、蛋白质-蛋白质相互作用网络、知识图以及其他研究领域。 与图像等其他数据不同,图形数据在非欧几里得空间中工作。 因此,图分析的目标是节点分类、链接预测和聚类。

NSDT工具推荐:?Three.js AI纹理开发包?-?YOLO合成数据生成器?-?GLTF/GLB在线编辑?-?3D模型格式在线转换?-?可编程3D场景编辑器?-?REVIT导出3D模型插件?-?3D模型语义搜索引擎?

在本文中,我们将进一步探讨图神经网络(GNN)。

1、什么是图?

图(Graph)是包含节点和顶点的数据结构。 各个节点之间的关系由顶点定义。 如果在节点中指定了方向,则该图被称为有向图,否则,该图是无向图。

使用图表的一个很好的例子是对社交网络中不同人之间的联系进行建模。

2、图神经网络

图神经网络(GNN:Graph Neural Network)是一类特殊的神经网络,能够处理以图形形式表示的数据。 这些网络很大程度上受到卷积神经网络(CNN)和图嵌入的推动。 CNN 无法处理图数据,因为图中的节点不以任何顺序表示,而且两个节点之间的依赖信息由边表示。

3、使用 NetworkX处理图数据

让我们花一点时间看看如何使用 NetworkX处理图数据。 NetworkX 是一个可用于创建图的 Python 包。 以下是如何使用该包创建没有节点的空图:

import networkx as nx
G = nx.Graph()

然后,你可以使用?add_nodes函数向图中添加一些节点:

G.add_nodes_from([2, 3])

接下来,使用?add_edges_from函数向图中添加一些边:

edges = [(2,1),(2,2),(3,2),(4,3),(6,4),(7,5),(14,5)]
G.add_edges_from(edges)

可以使用 Matplotlib 可视化这个图。 这是通过调用?draw函数并使用 Matpotlib 显示图形来完成的。

nx.draw(G, with_labels=True, font_weight='bold')
import matplotlib.pyplot as plt
plt.show()

?

4、图神经网络如何工作?

图神经网络(GNN)的概念由 Franco Scarselli Bruna 等人于 2009 年首次提出。在他们名为“图神经网络模型”的论文中,他们提出了现有神经网络的扩展,用于处理以图结构表示的数据。 该模型可以处理非循环图、循环图、有向图和无向图。 GNN 的目标是学习封装每个节点邻域信息的状态嵌入。 该嵌入用于产生输出。 例如,输出可以是节点标签。

最初的 GNN 提案有一些限制:

  • 对于固定点来说,节点隐藏状态的更新效率低下
  • GNN 在每次迭代中使用相同的参数,而其他神经网络在每层中使用不同的参数
  • 对从边获得的信息特征进行建模很困难

5、传统的图分析方法

也可以使用传统方法来分析图表。 这些方法通常是算法,包括:

  • 最短路径算法,例如 Dijkstra 算法
  • 搜索算法,例如广度优先搜索算法
  • 生成树算法,例如 Prim 算法

这些方法的挑战是需要先验知识,因此它们不能用于图分类。

6、图神经网络的类型

图神经网络有多种类型。 让我们看一下其中的几个。

6.1 图卷积网络 (GCN)

图卷积网络 (GCN) 使用与普通卷积神经网络相同的卷积运算。 GCN 通过检查相邻节点来学习特征。 它们通常由图卷积、线性层和非线性激活组成。 GNN 的工作原理是聚合邻域中的向量,将结果传递到密集的神经网络层,最后应用非线性。

GNN 与 CNN 的不同之处在于,它们是为处理非欧几里德结构化数据而构建的。 GCN 主要有两种类型:

  • 空间卷积网络。 在这些网络中,相邻节点的特征被组合成中心节点。 特征的求和类似于普通的卷积运算。
  • 谱卷积网络:在谱网络中,卷积运算是通过计算在傅里叶域中定义的拉普拉斯特征分解完成。

6.2 图自动编码器网络

图自动编码器网络(GAE:Graph Auto-Encoder Networks)由编码器和解码器组成。 这两个网络通过瓶颈层连接起来。 编码通过使图特征通过卷积滤波器来获取图像特征。 解码器尝试重建输入。 众所周知,自动编码器模型可以处理链接预测问题中常见的极端类别不平衡问题。 因此,图自动编码器网络尝试学习图表示,然后使用解码器重新构建图。

6.3 图循环神经网络

图循环神经网络 (GRNN:Graph Recurrent Neural Network) 利用多关系图并使用基于图的正则化器来提高平滑度并减轻过度参数化。 由于邻域的确切大小并不总是已知,因此使用循环 GNN 层使网络更加灵活。 GRNN 可以学习适合数据的最佳扩散模式。 它还能够处理节点涉及多个关系的情况。 该网络的计算成本也很低,因为操作数量根据图边的数量线性缩放。

6.4 门控图神经网络(GGNN)

在具有长期依赖性的问题上,门控图神经网络(GGNN:Gated Graph Neural Network)比循环图神经网络表现更好。 长期依赖关系由节点和边缘门编码。 长期时间依赖性由时间门编码。 因此,门控图神经网络通过添加门控机制来改进循环图神经网络。 这些门负责不同状态下的信息记忆和遗忘。

7、GNN 应用列表

现在让我们花点时间看看 GNN 可以做什么:

  • 节点分类:这里的目标是通过考虑邻居的标签来预测节点的标签。
  • 链接预测:在这种情况下,目标是预测图中各个实体之间的关系。 例如,这可以应用于社交网络的预测连接。
  • 图聚类:这涉及将图的节点划分为簇。 可以基于边权重或边距离或通过将图视为对象并将相似对象分组在一起来完成划分。
  • 图分类:这需要将图分类为类别。 这可以应用于社交网络分析和自然语言处理中的文档分类。 NLP 中的其他应用包括文本分类、提取文本之间的语义关系和序列标记。
  • 计算机视觉:在计算机视觉领域,GNN 可用于生成目标检测的感兴趣区域。 它们还可以用于图像分类,从而生成场景图。 然后场景生成模型识别图像中的对象以及它们之间的语义关系。 该领域的其他应用包括交互检测和区域分类。

8、与 GNN 相关的问题

图神经网络是强大的网络。 然而,有一些与它们相关的已知问题:

  • 本质上是浅层的:传统的神经网络可以非常深入以获得更好的性能。 不幸的是,GNN 通常很浅,大多数只有三层。 深度 GNN 的创建仍然是一个活跃的研究领域。
  • 动态图:动态图的结构不断变化,因此难以建模。 动态 GNN 也是一个活跃的研究领域。
  • 缺乏标准的图生成方法:没有标准的图生成方法。 在某些应用程序中,使用完全连接的图,而在其他应用程序中,算法检测图节点。
  • 可扩展性:将 GNN 大规模应用于推荐系统和社交网络等应用中是一个挑战。 这里的主要障碍是这些方法的计算成本很高。

9、示例:使用 PyTorch 构建图神经网络

PyTorch 可以与 DGL 结合构建用于节点预测的图神经网络。 深度图库 (DGL) 是一个 Python 包,可用于通过 PyTorch 和 TensorFlow 实现 GNN。 官方文档提供了有关如何入门的示例。

让我们看一个 PyTorch 示例,展示如何在?Cora 数据集上为半监督节点分类模型构建 GNN。第一步是导入包并加载数据:

import dgl
import torch
import torch.nn as nn
import torch.nn.functional as F
import dgl.data
dataset = dgl.data.CoraGraphDataset()
g = dataset[0]

下一步是定义图卷积网络,该网络将使用邻域信息计算节点表示。 这是使用?dgl.nn.GraphConv完成的:

from dgl.nn import GraphConv
class GCN(nn.Module):
    def __init__(self, in_feats, h_feats, num_classes):
        super(GCN, self).__init__()
        self.conv1 = GraphConv(in_feats, h_feats)
        self.conv2 = GraphConv(h_feats, num_classes)

    def forward(self, g, in_feat):
        h = self.conv1(g, in_feat)
        h = F.relu(h)
        h = self.conv2(g, h)
        return h
# Create the model with given dimensions
model = GCN(g.ndata['feat'].shape[1], 16, dataset.num_classes)

下一步是训练神经网络。 训练的方式与在 PyTorch 或 TensorFlow 中进行训练的方式类似:

def train(g, model):
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
    best_val_acc = 0
    best_test_acc = 0

    features = g.ndata['feat']
    labels = g.ndata['label']
    train_mask = g.ndata['train_mask']
    val_mask = g.ndata['val_mask']
    test_mask = g.ndata['test_mask']
    for e in range(100):
        # Forward
        logits = model(g, features)

        # Compute prediction
        pred = logits.argmax(1)

        # Compute loss
        # Note that you should only compute the losses of the nodes in the training set.
        loss = F.cross_entropy(logits[train_mask], labels[train_mask])

        # Compute accuracy on training/validation/test
        train_acc = (pred[train_mask] == labels[train_mask]).float().mean()
        val_acc = (pred[val_mask] == labels[val_mask]).float().mean()
        test_acc = (pred[test_mask] == labels[test_mask]).float().mean()

        # Save the best validation accuracy and the corresponding test accuracy.
        if best_val_acc < val_acc:
            best_val_acc = val_acc
            best_test_acc = test_acc

        # Backward
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if e % 5 == 0:
            print('In epoch {}, loss: {:.3f}, val acc: {:.3f} (best {:.3f}), test acc: {:.3f} (best {:.3f})'.format(
                e, loss, val_acc, best_val_acc, test_acc, best_test_acc))
model = GCN(g.ndata['feat'].shape[1], 16, dataset.num_classes)
train(g, model)

输出如下:

你也可以将DPL与 TensorFlow 结合使用。 这将要求你在环境中设置环境变量?DGLBACKEND。 以下是如何在 Google Colab 上完成此操作:

!export DGLBACKEND tensorflow

10、在 TensorFlow 和 Keras 中实现图神经网络

这篇论文提出了基于TensorFlow和Keras的Keras图卷积神经网络Python包(kgcnn)。 它为图神经网络提供 Keras 层。 官方页面提供了大量如何使用该包的示例。 示例之一是如何使用 Cora 数据集使用 kgcnn 进行节点分类。 让我们看一下这个插图的一个片段。

第一步通常是加载所需的包:

from kgcnn.data.cora.cora import cora_graph
from kgcnn.literature.GCN import make_gcn
from kgcnn.utils.adj import precompute_adjacency_scaled, convert_scaled_adjacency_to_list, make_adjacency_undirected_logical_or
from kgcnn.utils.data import ragged_tensor_from_nested_numpy
from kgcnn.utils.learning import lr_lin_reduction

下一步是加载数据并将其转换为密集矩阵:

# Download and load Dataset
A_data, X_data, y_data = cora_graph()
# Make node features dense
nodes = X_data.todense()

下一步是预先计算缩放后的无向邻接矩阵,并将邻接矩阵映射到索引列表加上边权重。 之后,使用 NumPy 转换数组的形状:

# Precompute scaled and undirected (symmetric) adjacency matrix
A_scaled = precompute_adjacency_scaled(make_adjacency_undirected_logical_or(A_data))
# Use edge_indices and weights instead of adj_matrix
edge_index, edge_weight = convert_scaled_adjacency_to_list(A_scaled)
edge_weight = np.expand_dims(edge_weight, axis=-1)

接下来,one-hot 对标签进行编码:

# Change labels to one-hot-encoding
labels = np.expand_dims(y_data, axis=-1)
labels = np.array(labels == np.arange(70), dtype=np.float)

可以使用 make_gcn 函数定义模型。 该函数需要输入节点的形状、输入边的形状、深度等:

model = make_gcn(
    input_node_shape=[None, 8710],
    input_edge_shape=[None, 1],
    # Output
    output_embedd={"output_mode": 'node'},
    output_mlp={"use_bias": [True, True, False], "units": [140, 70, 70], "activation": ['relu', 'relu', 'softmax']},
    # model specs
    depth=3,
    gcn_args={"units": 140, "use_bias": True, "activation": "relu", "has_unconnected": True}
)

以下是该模型的摘要:

下一步是训练这个模型。 训练在 Google Colab 上进行 300 个 epoch 后结束:

# Training loop
trainlossall = []
testlossall = []
start = time.process_time()
for iepoch in range(0, epo, epostep):
    hist = model.fit(xtrain, ytrain,
                     epochs=iepoch + epostep,
                     initial_epoch=iepoch,
                     batch_size=1,
                     callbacks=[cbks],
                     verbose=1,
                     sample_weight=train_mask  # Important!!!
                     )

    trainlossall.append(hist.history)
    testlossall.append(model.evaluate(xtrain, ytrain, sample_weight=val_mask))
stop = time.process_time()
print("Print Time for taining: ", stop - start)

然后,可以通过使用 Matplotlib 绘制训练和测试损失来检查训练和测试损失:

plt.figure(figsize=(12,8))
plt.plot(np.arange(1, len(trainlossall) + 1), trainlossall, label='Training Loss', c='blue')
plt.plot(np.arange(epostep, epo + epostep, epostep), testlossall[:, 1], label='Test Loss', c='red')
plt.xlabel('Epochs')
plt.ylabel('Accurarcy')
plt.title('GCN')
plt.legend(loc='lower right', fontsize='x-large')
plt.savefig('gcn_loss.png')
plt.show()


原文链接:图神经网络入门 - BimAnt

文章来源:https://blog.csdn.net/shebao3333/article/details/134907447
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。