4.5 图神经网络 (Graph Neural Networks - GNNs)


文档摘要

4.5 图神经网络 (Graph Neural Networks - GNNs) 第四章:PyTorch 高级主题:4.5 图神经网络 (Graph Neural Networks - GNNs) 详解与实践 在深度学习领域中,图神经网络 (Graph Neural Networks, GNNs) 作为一种新兴且强大的模型,正受到越来越多的关注。与传统深度学习模型处理网格结构数据(如图像、文本)不同,GNNs 专注于处理非欧几里得空间中的图结构数据。图结构数据广泛存在于社交网络、生物信息学、化学分子、知识图谱等领域,GNNs 的出现为这些复杂数据的分析和建模提供了强有力的工具。 4.5.1 图神经网络概述 4.5.1.

4.5 图神经网络 (Graph Neural Networks - GNNs)

第四章:PyTorch 高级主题:4.5 图神经网络 (Graph Neural Networks - GNNs) 详解与实践

在深度学习领域中,图神经网络 (Graph Neural Networks, GNNs) 作为一种新兴且强大的模型,正受到越来越多的关注。与传统深度学习模型处理网格结构数据(如图像、文本)不同,GNNs 专注于处理非欧几里得空间中的图结构数据。图结构数据广泛存在于社交网络、生物信息学、化学分子、知识图谱等领域,GNNs 的出现为这些复杂数据的分析和建模提供了强有力的工具。

4.5.1 图神经网络概述

4.5.1.1 图结构数据的魅力

传统的深度学习模型,如卷积神经网络 (CNNs) 和循环神经网络 (RNNs),在处理图像、文本等具有规则网格结构的数据时表现出色。然而,现实世界中存在大量非欧几里得空间的数据,它们以图 (Graph) 的形式呈现。图由节点 (Nodes) 和边 (Edges) 构成,节点表示实体,边表示实体之间的关系。

图结构数据的优势在于其强大的表达能力:

  • 关系建模: 图结构能够显式地建模实体之间的复杂关系,例如社交网络中用户之间的朋友关系、分子结构中原子之间的化学键、知识图谱中实体之间的语义关系。

  • 灵活性: 图结构可以表示各种不同类型的数据,包括社交网络、生物网络、交通网络、推荐系统等。

  • 非欧几里得空间: 图结构天然地适应非欧几里得空间,无需像传统模型那样将数据强行转换为网格结构。

mermaid 示例图:简单的社交网络

4.5.1.2 图神经网络的崛起

图神经网络 (GNNs) 是一类专门用于处理图结构数据的神经网络。GNNs 的核心思想是消息传递 (Message Passing)图卷积 (Graph Convolution)。通过在图上迭代地聚合邻居节点的信息,GNNs 能够学习到节点的表示向量,这些向量能够捕捉节点自身的特征以及其在图结构中的上下文信息。

GNNs 的关键优势:

  • 图结构感知: GNNs 天然地能够处理图结构数据,利用图的拓扑结构信息进行学习。

  • 节点表示学习: GNNs 能够学习到高质量的节点表示向量,用于节点分类、链接预测、图分类等下游任务。

  • 端到端学习: GNNs 可以与其他深度学习模型结合,进行端到端的图数据分析和挖掘。

GNNs 的应用领域:

  • 社交网络分析: 用户分类、社区检测、推荐系统、恶意用户识别。

  • 生物信息学: 蛋白质结构预测、药物发现、基因功能预测、疾病传播建模。

  • 化学信息学: 分子性质预测、药物设计、材料发现。

  • 知识图谱: 知识图谱补全、实体关系抽取、问答系统。

  • 推荐系统: 基于图的推荐算法、社交推荐。

  • 自然语言处理: 句子依赖关系解析、文本分类、知识图谱增强的 NLP 任务。

4.5.1.3 GNNs 的基本原理:消息传递

大多数 GNNs 都遵循消息传递机制。其核心思想是:节点的表示向量通过聚合其邻居节点的信息进行更新。 这个过程可以迭代多次,使得每个节点最终能够融合来自更远邻居的信息。

消息传递过程主要包含三个步骤:

  1. 消息传递 (Message Passing): 每个节点根据其自身的表示向量和邻居节点的表示向量,生成发送给邻居节点的消息。

  2. 消息聚合 (Aggregation): 每个节点聚合来自所有邻居节点的消息。

  3. 节点更新 (Node Update): 每个节点根据聚合后的消息和自身当前的表示向量,更新自身的表示向量。

mermaid 示例图:消息传递过程

通过多次消息传递迭代,节点可以有效地聚合来自其图邻域的信息,从而学习到更丰富的表示向量。不同的 GNN 模型在消息传递、聚合和更新的具体方式上有所不同,例如图卷积网络 (GCN)、图注意力网络 (GAT) 等。

4.5.2 PyTorch Geometric (PyG) 简介

PyTorch Geometric (PyG) 是一个基于 PyTorch 的图神经网络库,它提供了丰富的功能,方便研究人员和开发者构建和训练 GNNs。PyG 具有以下特点:

  • 易用性: PyG 提供了简洁的 API,使得图数据的处理和 GNN 模型的构建变得简单直观。

  • 高效性: PyG 底层使用 PyTorch 优化过的张量操作,保证了 GNNs 训练的效率。

  • 可扩展性: PyG 支持自定义 GNN 层和模型,方便研究人员进行算法创新。

  • 丰富的图数据集和模型: PyG 内置了大量的图数据集和常用的 GNN 模型,方便用户快速上手。

4.5.2.1 PyG 的核心数据结构:torch_geometric.data.Data

PyG 中最核心的数据结构是 torch_geometric.data.Data 对象,用于表示图数据。一个 Data 对象主要包含以下属性:

  • x: 节点特征矩阵,形状为 [num_nodes, num_node_features]

  • edge_index: 边索引矩阵,形状为 [2, num_edges],表示图中边的连接关系。

  • edge_attr: 边特征矩阵 (可选),形状为 [num_edges, num_edge_features]

  • y: 节点或图的标签 (可选),形状取决于任务类型。

  • pos: 节点位置矩阵 (可选),用于图可视化或其他任务。

代码示例:创建 Data 对象

import torch from torch_geometric.data import Data # 节点特征矩阵 x = torch.tensor([[1], [2], [3], [4]], dtype=torch.float) # 边索引矩阵 (COO 格式) edge_index = torch.tensor([[0, 1, 2, 0, 3], [1, 0, 1, 2, 2]], dtype=torch.long) # 创建 Data 对象 data = Data(x=x, edge_index=edge_index) print(data)

输出:

Data(x=[4, 1], edge_index=[2, 5])

edge_index 使用 COO (Coordinate) 格式表示边,其中每一列 [u, v] 表示存在一条从节点 u 到节点 v 的边。

4.5.2.2 PyG 的常用模块

PyG 提供了丰富的模块,方便构建各种 GNN 模型:

  • torch_geometric.nn: 包含了各种常用的 GNN 层,例如 GCNConv, GATConv, SAGEConv 等。

  • torch_geometric.datasets: 包含了大量的图数据集,例如 Cora, CiteSeer, PubMed, Planetoid 等。

  • torch_geometric.transforms: 提供了各种图数据预处理方法,例如数据增强、图划分等。

  • torch_geometric.utils: 包含各种图操作工具函数,例如邻接矩阵转换、图可视化等。

4.5.3 图卷积网络 (Graph Convolutional Networks - GCNs)

图卷积网络 (GCNs) 是最早且最经典的 GNN 模型之一。GCNs 基于谱图理论,通过图卷积操作实现消息传递。

4.5.3.1 GCN 层的原理

GCN 层的核心思想是: 聚合邻居节点的特征信息,并结合节点自身的特征信息,更新节点的表示向量。

GCN 层的数学公式可以表示为:

\mathbf{H}^{(l+1)} = \sigma \left( \tilde{\mathbf{D}}^{-\frac{1}{2}} \tilde{\mathbf{A}} \tilde{\mathbf{D}}^{-\frac{1}{2}} \mathbf{H}^{(l)} \mathbf{W}^{(l)} \right)

其中:

  • \mathbf{H}^{(l)} 是第 l 层节点的表示矩阵,\mathbf{H}^{(0)} = \mathbf{X} (节点特征矩阵)。

  • \mathbf{W}^{(l)} 是第 l 层的权重矩阵。

  • \tilde{\mathbf{A}} = \mathbf{A} + \mathbf{I} 是添加了自环的邻接矩阵,\mathbf{A} 是邻接矩阵,\mathbf{I} 是单位矩阵。

  • \tilde{\mathbf{D}}\tilde{\mathbf{A}} 的度矩阵,\tilde{D}_{ii} = \sum_{j} \tilde{A}_{ij}

  • \sigma 是激活函数,例如 ReLU。

公式解读:

  1. 添加自环 (\tilde{\mathbf{A}} = \mathbf{A} + \mathbf{I}): 确保在聚合邻居信息时,节点自身的信息也被考虑进去。

  2. 对称归一化 (\tilde{\mathbf{D}}^{-\frac{1}{2}} \tilde{\mathbf{A}} \tilde{\mathbf{D}}^{-\frac{1}{2}}): 对邻接矩阵进行归一化,避免度大的节点对聚合结果产生过大的影响,稳定训练过程。

  3. 线性变换 (\mathbf{H}^{(l)} \mathbf{W}^{(l)}): 对节点表示进行线性变换,学习更丰富的特征。

  4. 非线性激活 (\sigma): 引入非线性,增强模型的表达能力。

mermaid 示例图:GCN 消息传递

4.5.3.2 使用 PyG 实现 GCN 层

PyG 提供了 torch_geometric.nn.GCNConv 类,方便实现 GCN 层。

代码示例:GCN 层实现

import torch import torch.nn.functional as F from torch_geometric.nn import GCNConv class GCN(torch.nn.Module): def __init__(self, num_node_features, hidden_channels, num_classes): super(GCN, self).__init__() torch.manual_seed(12345) self.conv1 = GCNConv(num_node_features, hidden_channels) self.conv2 = GCNConv(hidden_channels, 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(num_node_features=1, hidden_channels=16, num_classes=2) print(model)

代码解释:

  • GCN 类继承自 torch.nn.Module,定义了一个简单的两层 GCN 模型。

  • __init__ 方法中,实例化了两个 GCNConv 层。

    • GCNConv(num_node_features, hidden_channels): 第一层 GCN,将输入特征维度 num_node_features 转换为隐藏层维度 hidden_channels

    • GCNConv(hidden_channels, num_classes): 第二层 GCN,将隐藏层维度 hidden_channels 转换为输出类别数 num_classes

  • forward 方法定义了模型的前向传播过程:

    • x = self.conv1(x, edge_index): 第一层 GCN 卷积操作。

    • x = x.relu(): ReLU 激活函数。

    • x = F.dropout(x, p=0.5, training=self.training): Dropout 正则化,防止过拟合。

    • x = self.conv2(x, edge_index): 第二层 GCN 卷积操作。

    • return x: 返回最终的节点表示。

4.5.3.3 GCN 的应用:节点分类

GCN 常用于节点分类任务。例如,在社交网络中,可以使用 GCN 对用户进行分类,预测用户的兴趣爱好、政治倾向等。

代码示例:使用 GCN 进行节点分类

from torch_geometric.datasets import Planetoid from torch_geometric.transforms import NormalizeFeatures # 加载 Cora 数据集 dataset = Planetoid(root='data/Cora', name='Cora', transform=NormalizeFeatures()) data = dataset[0] # 模型实例化 (使用之前定义的 GCN 模型) model = GCN(num_node_features=dataset.num_node_features, hidden_channels=16, num_classes=dataset.num_classes) # 优化器 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 # 测试 @torch.no_grad() def test(): model.eval() out = model(data.x, data.edge_index) pred = out.argmax(dim=-1) correct = pred[data.test_mask] == data.y[data.test_mask] acc = int(correct.sum()) / int(data.test_mask.sum()) return acc # 训练循环 for epoch in range(201): loss = train() if epoch % 10 == 0: acc = test() print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}, Test Acc: {acc:.4f}')

代码解释:

  • 加载 Cora 数据集: 使用 Planetoid 数据集加载 Cora 数据集,NormalizeFeatures 对节点特征进行归一化。

  • 模型实例化: 使用之前定义的 GCN 模型,输入特征维度、隐藏层维度和输出类别数由数据集信息确定。

  • 优化器和损失函数: 使用 Adam 优化器和交叉熵损失函数。

  • train 函数: 定义训练过程,计算损失,反向传播,更新参数。

  • test 函数: 定义测试过程,计算测试集上的准确率。

  • 训练循环: 迭代训练模型,每 10 个 epoch 测试一次模型性能。

运行代码后,可以看到 GCN 在 Cora 数据集上取得了较高的节点分类准确率。

4.5.4 图注意力网络 (Graph Attention Networks - GATs)

图注意力网络 (GATs) 是另一种重要的 GNN 模型。与 GCN 不同,GAT 引入了注意力机制,使得节点在聚合邻居信息时能够区分不同邻居的重要性。

4.5.4.1 GAT 层的原理

GAT 层的核心思想是: 使用注意力机制计算节点与其邻居节点之间的注意力权重,然后根据注意力权重聚合邻居节点的特征信息。

GAT 层的数学公式可以表示为:

e_{ij} = a(\mathbf{W} \mathbf{h}_i, \mathbf{W} \mathbf{h}_j)
\alpha_{ij} = \frac{\exp(e_{ij})}{\sum_{k \in \mathcal{N}_i} \exp(e_{ik})}
\mathbf{h}_i' = \sigma \left( \sum_{j \in \mathcal{N}_i} \alpha_{ij} \mathbf{W} \mathbf{h}_j \right)

其中:

  • \mathbf{h}_i\mathbf{h}_j 分别是节点 i 和节点 j 的表示向量。

  • \mathbf{W} 是权重矩阵,用于线性变换节点表示。

  • a 是注意力机制函数,例如单层前馈神经网络。

  • e_{ij} 是节点 j 对节点 i 的未归一化注意力系数。

  • \alpha_{ij} 是节点 j 对节点 i 的归一化注意力系数,表示邻居节点 j 对节点 i 的重要性。

  • \mathcal{N}_i 是节点 i 的邻居节点集合。

  • \sigma 是激活函数,例如 ReLU。

公式解读:

  1. 线性变换 (\mathbf{W} \mathbf{h}_i, \mathbf{W} \mathbf{h}_j): 对节点表示进行线性变换,为计算注意力系数做准备。

  2. 注意力系数计算 (e_{ij} = a(\mathbf{W} \mathbf{h}_i, \mathbf{W} \mathbf{h}_j)): 使用注意力机制函数 a 计算节点 i 和节点 j 之间的注意力系数。注意力系数可以理解为节点 j 对节点 i 的重要性程度。

  3. 注意力系数归一化 (\alpha_{ij} = \frac{\exp(e_{ij})}{\sum_{k \in \mathcal{N}_i} \exp(e_{ik})}): 使用 Softmax 函数对注意力系数进行归一化,使得每个节点的邻居节点的注意力系数之和为 1。

  4. 加权聚合 (\mathbf{h}_i' = \sigma \left( \sum_{j \in \mathcal{N}_i} \alpha_{ij} \mathbf{W} \mathbf{h}_j \right)): 根据归一化注意力系数,对邻居节点的特征信息进行加权聚合,得到节点 i 的更新后的表示向量。

mermaid 示例图:GAT 注意力机制

4.5.4.2 使用 PyG 实现 GAT 层

PyG 提供了 torch_geometric.nn.GATConv 类,方便实现 GAT 层。

代码示例:GAT 层实现

import torch import torch.nn.functional as F from torch_geometric.nn import GATConv class GAT(torch.nn.Module): def __init__(self, num_node_features, hidden_channels, num_classes, heads): super(GAT, self).__init__() torch.manual_seed(12345) self.conv1 = GATConv(num_node_features, hidden_channels, heads=heads) self.conv2 = GATConv(hidden_channels * heads, num_classes, heads=1) 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) # ELU 激活函数 x = F.dropout(x, p=0.6, training=self.training) x = self.conv2(x, edge_index) return x # 模型实例化 model_gat = GAT(num_node_features=1, hidden_channels=8, num_classes=2, heads=8) print(model_gat)

代码解释:

  • GAT 类继承自 torch.nn.Module,定义了一个简单的两层 GAT 模型。

  • __init__ 方法中,实例化了两个 GATConv 层。

    • GATConv(num_node_features, hidden_channels, heads=heads): 第一层 GAT,使用多头注意力机制,将输入特征维度 num_node_features 转换为隐藏层维度 hidden_channels * headsheads 参数指定注意力头的数量。

    • GATConv(hidden_channels * heads, num_classes, heads=1): 第二层 GAT,将隐藏层维度 hidden_channels * heads 转换为输出类别数 num_classes,这里使用单头注意力。

  • forward 方法定义了模型的前向传播过程:

    • x = F.dropout(x, p=0.6, training=self.training): Dropout 正则化。

    • x = self.conv1(x, edge_index): 第一层 GAT 卷积操作。

    • x = F.elu(x): ELU 激活函数,GAT 论文中推荐使用 ELU。

    • x = F.dropout(x, p=0.6, training=self.training): Dropout 正则化。

    • x = self.conv2(x, edge_index): 第二层 GAT 卷积操作。

    • return x: 返回最终的节点表示。

4.5.4.3 GAT 的应用:节点分类 (对比 GCN)

GAT 同样可以用于节点分类任务,并且通常在一些数据集上能够取得比 GCN 更好的性能,因为注意力机制使得 GAT 能够更灵活地处理不同邻居节点的重要性。

代码示例:使用 GAT 进行节点分类 (修改之前的 GCN 节点分类代码)

只需要将之前的 GCN 节点分类代码中的 model = GCN(...) 替换为 model = GAT(...) 即可,并根据 GAT 模型的参数调整 model = GAT(num_node_features=dataset.num_node_features, hidden_channels=8, num_classes=dataset.num_classes, heads=8)。其他代码部分保持不变。

运行修改后的代码,可以看到 GAT 在 Cora 数据集上的节点分类准确率,并可以与 GCN 的结果进行比较。通常情况下,GAT 在一些图数据集上能够取得更好的性能。

4.5.5 GNNs 的其他变体和应用拓展

除了 GCN 和 GAT,还有许多其他的 GNN 模型,例如:

  • GraphSAGE (Graph Sample and Aggregate): GraphSAGE 采样邻居节点,并使用聚合函数 (例如 MeanAggregator, MaxPoolAggregator, LSTMAggregator) 聚合邻居信息,适用于大规模图数据。

  • GIN (Graph Isomorphism Network): GIN 旨在解决 GCN 在图同构性测试中的不足,通过使用更强大的聚合函数 (例如 SumAggregator) 和多层感知机 (MLP) 进行节点更新,能够更好地区分不同的图结构。

  • GatedGCN: 引入门控机制到 GCN 中,控制消息传递过程,增强模型表达能力。

  • RGCN (Relational Graph Convolutional Network): 针对知识图谱等异构图数据,考虑边的类型 (关系类型),进行关系感知的消息传递。

GNNs 应用拓展:

  • 图分类 (Graph Classification): 预测整个图的类别或属性。可以使用图池化 (Graph Pooling) 操作将节点表示聚合为图表示,然后进行分类。

  • 链接预测 (Link Prediction): 预测图中节点之间是否存在边。可以使用节点表示计算节点对之间的相似度,然后进行边预测。

  • 图生成 (Graph Generation): 生成新的图结构。可以使用生成模型 (例如 GAN, VAE) 生成图的邻接矩阵和节点特征。

4.5.6 总结与展望

图神经网络 (GNNs) 作为处理图结构数据的强大工具,在各个领域展现出巨大的潜力。本节深入探讨了 GNNs 的基本原理,重点介绍了两种经典的 GNN 模型:图卷积网络 (GCN) 和图注意力网络 (GAT),并结合 PyTorch Geometric (PyG) 进行了代码实践。

总结:

  • 图神经网络 (GNNs) 能够有效处理图结构数据,利用图的拓扑结构信息进行学习。

  • 消息传递机制是 GNNs 的核心思想,通过迭代聚合邻居节点的信息更新节点表示。

  • PyTorch Geometric (PyG) 是一个基于 PyTorch 的图神经网络库,提供了丰富的功能和易用的 API。

  • GCN 和 GAT 是两种经典的 GNN 模型,分别基于图卷积和注意力机制实现消息传递。

  • GNNs 在节点分类、链接预测、图分类等任务中表现出色,应用领域广泛。

展望:

  • 更深层次的 GNN 模型: 研究更深层次的 GNN 模型,增强模型的表达能力和学习能力。

  • 动态图神经网络: 处理动态变化的图数据,例如社交网络演化、交通网络流量变化等。

  • 可解释性 GNNs: 提高 GNN 模型的透明度和可解释性,理解 GNN 的决策过程。

  • GNNs 与其他深度学习模型的结合: 将 GNNs 与 CNNs, RNNs 等其他深度学习模型结合,解决更复杂的问题。

  • GNNs 在新领域的应用: 探索 GNNs 在更多新兴领域的应用,例如推荐系统、自然语言处理、计算机视觉、机器人等。

随着图数据规模的不断增长和应用场景的不断拓展,图神经网络将会在未来深度学习领域扮演越来越重要的角色。掌握 GNNs 的理论和实践技能,对于应对日益复杂的图数据分析挑战至关重要。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U