图神经网络基础--基于图神经网络的节点表征学习

article/2025/9/21 20:29:19

图神经网络基础–基于图神经网络的节点表征学习

引言

在图节点预测或边预测任务中,首先需要生成节点表征(Node Representation)。我们使用图神经网络来生成节点表征,并通过基于监督学习的对图神经网络的训练,使得图神经网络学会产生高质量的节点表征高质量的节点表征能够用于衡量节点的相似性,同时高质量的节点表征也是准确分类节点的前提。

本节中,我们将学习实现多层图神经网络的方法,并以节点分类任务为例,学习训练图神经网络的一般过程。我们将以Cora 数据集为例子进行说明,Cora 是一个论文引用网络,节点代表论文,如果两篇论文存在引用关系,则对应的两个节点之间存在边,各节点的属性都是一个1433维的词包特征向量。我们的任务是预测各篇论文的类别(共7类)。我们还将对MLP和GCN, GAT(两个知名度很高的图神经网络)三类神经网络在节点分类任务中的表现进行比较分析,以此来展现图神经网络的强大和论证图神经网络强于普通深度神经网络的原因。

此节内容安排如下:

  1. 首先,我们要做一些准备工作,即获取并分析数据集构建一个方法用于分析节点表征的分布
  2. 然后,我们考察MLP神经网络用于节点分类的表现,并观察基于MLP神经网络学习到的节点表征的分布
  3. 接着,我们逐一介绍GCN, GAT这两个图神经网络的理论、对比它们在节点分类任务中的表现以及它们学习到的节点表征的质量
  4. 最后,我们比较三者在节点表征学习能力上的差异

准备工作

获取并分析数据集

from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeaturesdataset = Planetoid(root='dataset', name='Cora', transform=NormalizeFeatures())print()
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()
print(data)
print('======================')# Gather some statistics about the graph.
print(f'Number of nodes: {data.num_nodes}')
print(f'Number of edges: {data.num_edges}')
print(f'Average node degree: {data.num_edges / data.num_nodes:.2f}')
print(f'Number of training nodes: {data.train_mask.sum()}')
print(f'Training node label rate: {int(data.train_mask.sum()) / data.num_nodes:.2f}')
print(f'Contains isolated nodes: {data.contains_isolated_nodes()}')
print(f'Contains self-loops: {data.contains_self_loops()}')
print(f'Is undirected: {data.is_undirected()}')

我们可以看到,Cora图拥有2,708个节点和10,556条边,平均节点度为3.9,训练集仅使用了140个节点,占整体的5%。我们还可以看到,这个图是无向图,不存在孤立的节点。

数据转换(transform)在将数据输入到神经网络之前修改数据,这一功能可用于实现数据规范化或数据增强。在此例子中,我们使用NormalizeFeatures进行节点特征归一化,使各节点特征总和为1。其他的数据转换方法请参阅torch-geometric-transforms。

可视化节点表征分布的方法

import matplotlib.pyplot as plt
from sklearn.manifold import TSNEdef 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()

我们先利用TSNE方法将高维的节点表征映射到二维平面空间,然后在二维平面画出节点,这样我们就实现了节点表征分布的可视化。

使用MLP神经网络进行节点分类

理论上,我们应该能够仅根据文章的内容,即它的词包特征表征(bag-of-words feature representation)来推断文章的类别,而无需考虑文章之间的任何关系信息。接下来,让我们通过构建一个简单的MLP神经网络来验证这一点。此神经网络只对输入节点的表征做变换,它在所有节点之间共享权重。

MLP神经网络的构造

import torch
from torch.nn import Linear
import torch.nn.functional as Fclass MLP(torch.nn.Module):def __init__(self, hidden_channels):super(MLP, self).__init__()torch.manual_seed(12345)self.lin1 = Linear(dataset.num_features, hidden_channels)self.lin2 = Linear(hidden_channels, dataset.num_classes)def forward(self, x):x = self.lin1(x)x = x.relu()x = F.dropout(x, p=0.5, training=self.training)x = self.lin2(x)return xmodel = MLP(hidden_channels=16)
print(model)

我们的MLP由两个线性层、一个ReLU非线性层和一个dropout操作组成。第一个线性层将1433维的节点表征嵌入(embedding)到低维空间中(hidden_channels=16),第二个线性层将节点表征嵌入到类别空间中(num_classes=7)。

MLP神经网络的训练

我们利用交叉熵损失Adam优化器来训练这个简单的MLP神经网络。

model = MLP(hidden_channels=16)
criterion = torch.nn.CrossEntropyLoss()  # Define loss criterion.
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)  # Define optimizer.def train():model.train()optimizer.zero_grad()  # Clear gradients.out = model(data.x)  # Perform a single forward pass.loss = criterion(out[data.train_mask], data.y[data.train_mask])  # Compute the loss solely based on the training nodes.loss.backward()  # Derive gradients.optimizer.step()  # Update parameters based on gradients.return lossfor epoch in range(1, 201):loss = train()print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}')

MLP神经网络的测试

训练完模型后,我们可以通过测试来检验这个简单的MLP神经网络在测试集上的表现。

def test():model.eval()out = model(data.x)pred = out.argmax(dim=1)  # Use the class with highest probability.test_correct = pred[data.test_mask] == data.y[data.test_mask]  # Check against ground-truth labels.test_acc = int(test_correct.sum()) / int(data.test_mask.sum())  # Derive ratio of correct predictions.return test_acctest_acc = test()
print(f'Test Accuracy: {test_acc:.4f}')

正如我们所看到的,我们的MLP表现相当糟糕,只有大约59%的测试准确性。

**为什么MLP没有表现得更好呢?**其中一个重要原因是,用于训练此神经网络的有标签节点数量过少,此神经网络被过拟合,它对未见过的节点泛化能力很差。

卷积图神经网络(GCN)

GCN的定义

GCN 来源于论文“Semi-supervised Classification with Graph Convolutional Network”,其数学定义为,
X ′ = D ^ − 1 / 2 A ^ D ^ − 1 / 2 X Θ , \mathbf{X}^{\prime} = \mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2} \mathbf{X} \mathbf{\Theta}, X=D^1/2A^D^1/2,
其中 A ^ = A + I \mathbf{\hat{A}} = \mathbf{A} + \mathbf{I} A^=A+I表示插入自环的邻接矩阵(使得每一个节点都有一条边连接到自身), D ^ i i = ∑ j = 0 A ^ i j \hat{D}_{ii} = \sum_{j=0} \hat{A}_{ij} D^ii=j=0A^ij表示 A ^ \mathbf{\hat{A}} A^的对角线度矩阵(对角线元素为对应节点的度,其余元素为0)。邻接矩阵可以包括不为 1 1 1的值,当邻接矩阵不为{0,1}值时,表示邻接矩阵存储的是边的权重。 D ^ − 1 / 2 A ^ D ^ − 1 / 2 \mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2} D^1/2A^D^1/2是对称归一化矩阵,它的节点式表述为:
x i ′ = Θ ∑ j ∈ N ( v ) ∪ { i } e j , i d ^ j d ^ i x j \mathbf{x}^{\prime}_i = \mathbf{\Theta} \sum_{j \in \mathcal{N}(v) \cup \{ i \}} \frac{e_{j,i}}{\sqrt{\hat{d}_j \hat{d}_i}} \mathbf{x}_j xi=ΘjN(v){i}d^jd^i ej,ixj
其中, d ^ i = 1 + ∑ j ∈ N ( i ) e j , i \hat{d}_i = 1 + \sum_{j \in \mathcal{N}(i)} e_{j,i} d^i=1+jN(i)ej,i e j , i e_{j,i} ej,i表示从源节点 j j j到目标节点 i i i的边的对称归一化系数(默认值为1.0)。

PyG中GCNConv 模块说明

GCNConv构造函数接口:

GCNConv(in_channels: int, out_channels: int, improved: bool = False, cached: bool = False, add_self_loops: bool = True, normalize: bool = True, bias: bool = True, **kwargs)

其中:

  • in_channels :输入数据维度;
  • out_channels :输出数据维度;
  • improved :如果为true A ^ = A + 2 I \mathbf{\hat{A}} = \mathbf{A} + 2\mathbf{I} A^=A+2I,其目的在于增强中心节点自身信息;
  • cached :是否存储 D ^ − 1 / 2 A ^ D ^ − 1 / 2 \mathbf{\hat{D}}^{-1/2} \mathbf{\hat{A}} \mathbf{\hat{D}}^{-1/2} D^1/2A^D^1/2的计算结果以便后续使用,这个参数只应在归纳学习(transductive learning)的场景中设置为true(归纳学习可以简单理解为在训练、验证、测试、推理(inference)四个阶段都只使用一个数据集);
  • add_self_loops :是否在邻接矩阵中增加自环边;
  • normalize :是否添加自环边并在运行中计算对称归一化系数;
  • bias :是否包含偏置项。

详细内容请大家参阅GCNConv官方文档。

GCN图神经网络的构造

将上面例子中的torch.nn.Linear替换成torch_geometric.nn.GCNConv,我们就可以得到一个GCN图神经网络,如下方代码所示:

from torch_geometric.nn import GCNConvclass GCN(torch.nn.Module):def __init__(self, hidden_channels):super(GCN, self).__init__()torch.manual_seed(12345)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 xmodel = GCN(hidden_channels=16)
print(model)

可视化由未经训练的GCN图神经网络生成的节点表征

代码如下所示:

model = GCN(hidden_channels=16)
model.eval()out = model(data.x, data.edge_index)
visualize(out, color=data.y)

经过visualize函数的处理,7维特征的节点被映射到2维的平面上。我们会惊喜地看到“同类节点群聚”的现象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MOloJMUW-1664209005403)(images/image-20210526214252415.png)]

GCN图神经网络的训练

通过下方的代码我们可实现GCN图神经网络的训练:

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()  # Clear gradients.out = model(data.x, data.edge_index)  # Perform a single forward pass.loss = criterion(out[data.train_mask], data.y[data.train_mask])  # Compute the loss solely based on the training nodes.loss.backward()  # Derive gradients.optimizer.step()  # Update parameters based on gradients.return lossfor epoch in range(1, 201):loss = train()print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}')

GCN图神经网络的测试

在训练过程结束后,我们检测GCN图神经网络在测试集上的准确性:

def test():model.eval()out = model(data.x, data.edge_index)pred = out.argmax(dim=1)  # Use the class with highest probability.test_correct = pred[data.test_mask] == data.y[data.test_mask]  # Check against ground-truth labels.test_acc = int(test_correct.sum()) / int(data.test_mask.sum())  # Derive ratio of correct predictions.return test_acctest_acc = test()
print(f'Test Accuracy: {test_acc:.4f}')

通过简单地将torch.nn.Linear替换成torch_geometric.nn.GCNConv,我们可以取得81.4%的测试准确率!与前面的仅获得59%的测试准确率的MLP图神经网络相比,GCN图神经网络准确性要高得多。这表明节点的邻接信息在取得更好的准确率方面起着关键作用

可视化由训练后的GCN图神经网络生成的节点表征

最后我们可视化训练后的GCN图神经网络生成的节点表征,我们会发现“同类节点群聚”的现象更加明显了。这意味着在训练后,GCN图神经网络生成的节点表征质量更高了。

model.eval()out = model(data.x, data.edge_index)
visualize(out, color=data.y)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NHavBfzP-1664209005404)(images/image-20210526214436051.png)]

图注意力神经网络(GAT)

GAT的定义

图注意神经网络(GAT)来源于论文 Graph Attention Networks。其数学定义为,
x i ′ = α i , i Θ x i + ∑ j ∈ N ( i ) α i , j Θ x j , \mathbf{x}^{\prime}_i = \alpha_{i,i}\mathbf{\Theta}\mathbf{x}_{i} + \sum_{j \in \mathcal{N}(i)} \alpha_{i,j}\mathbf{\Theta}\mathbf{x}_{j}, xi=αi,iΘxi+jN(i)αi,jΘxj,
其中注意力系数 α i , j \alpha_{i,j} αi,j的计算方法为,
α i , j = exp ⁡ ( L e a k y R e L U ( a ⊤ [ Θ x i ∥ Θ x j ] ) ) ∑ k ∈ N ( i ) ∪ { i } exp ⁡ ( L e a k y R e L U ( a ⊤ [ Θ x i ∥ Θ x k ] ) ) . \alpha_{i,j} = \frac{ \exp\left(\mathrm{LeakyReLU}\left(\mathbf{a}^{\top} [\mathbf{\Theta}\mathbf{x}_i \, \Vert \, \mathbf{\Theta}\mathbf{x}_j] \right)\right)} {\sum_{k \in \mathcal{N}(i) \cup \{ i \}} \exp\left(\mathrm{LeakyReLU}\left(\mathbf{a}^{\top} [\mathbf{\Theta}\mathbf{x}_i \, \Vert \, \mathbf{\Theta}\mathbf{x}_k] \right)\right)}. αi,j=kN(i){i}exp(LeakyReLU(a[ΘxiΘxk]))exp(LeakyReLU(a[ΘxiΘxj])).

PyG中GATConv 模块说明

GATConv构造函数接口:

GATConv(in_channels: Union[int, Tuple[int, int]], out_channels: int, heads: int = 1, concat: bool = True, negative_slope: float = 0.2, dropout: float = 0.0, add_self_loops: bool = True, bias: bool = True, **kwargs)

其中:

  • in_channels :输入数据维度;
  • out_channels :输出数据维度;
  • heads :在GATConv使用多少个注意力模型(Number of multi-head-attentions);
  • concat :如为true,不同注意力模型得到的节点表征被拼接到一起(表征维度翻倍),否则对不同注意力模型得到的节点表征求均值;

详细内容请大家参阅GATConv官方文档

GAT图神经网络的构造

将MLP神经网络例子中的torch.nn.Linear替换成torch_geometric.nn.GATConv,来实现GAT图神经网络的构造,如下方代码所示:

import torch
from torch.nn import Linear
import torch.nn.functional as Ffrom torch_geometric.nn import GATConvclass GAT(torch.nn.Module):def __init__(self, hidden_channels):super(GAT, self).__init__()torch.manual_seed(12345)self.conv1 = GATConv(dataset.num_features, hidden_channels)self.conv2 = GATConv(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

基于GAT图神经网络的训练和测试,与基于GCN图神经网络的训练和测试相同,此处不再赘述。

结语

在节点表征的学习中,MLP神经网络只考虑了节点自身属性,忽略了节点之间的连接关系,它的结果是最差的;而GCN图神经网络与GAT图神经网络,同时考虑了节点自身信息与周围邻接节点的信息,因此它们的结果都优于MLP神经网络。也就是说,对周围邻接节点的信息的考虑,是图神经网络由于普通深度神经网络的原因。

GCN图神经网络与GAT图神经网络的相同点为:

  • 它们都遵循消息传递范式
  • 在邻接节点信息变换阶段,它们都对邻接节点做归一化和线性变换;
  • 在邻接节点信息聚合阶段,它们都将变换后的邻接节点信息做求和聚合;
  • 在中心节点信息变换阶段,它们都只是简单返回邻接节点信息聚合阶段的聚合结果。

GCN图神经网络与GAT图神经网络的区别在于采取的归一化方法不同

  • 前者根据中心节点与邻接节点的度计算归一化系数,后者根据中心节点与邻接节点的相似度计算归一化系数。
  • 前者的归一化方式依赖于图的拓扑结构:不同的节点会有不同的度,同时不同节点的邻接节点的度也不同,于是在一些应用中GCN图神经网络会表现出较差的泛化能力。
  • 后者的归一化方式依赖于中心节点与邻接节点的相似度,相似度是训练得到的,因此不受图的拓扑结构的影响,在不同的任务中都会有较好的泛化表现。

参考文献

  • PyG中内置的数据转换方法:torch-geometric-transforms
  • 一个可视化高纬数据的工具:t-distributed Stochastic Neighbor Embedding
  • 提出GCN的论文:Semi-supervised Classification with Graph Convolutional Network
  • GCNConv官方文档:torch_geometric.nn.conv.GCNConv
  • 提出GAT的论文: Graph Attention Networks

http://chatgpt.dhexx.cn/article/KhKsJX9f.shtml

相关文章

图神经网络(三):节点分类

节点分类问题 数据集:Cora 包含七类学术论文,论文与论文之间存在引用和被引用的关系 数据集导入 from torch_geometric.datasets import Planetoid from torch_geometric.transforms import NormalizeFeaturesdatasetPlanetoid(rootdataset,nameCora,…

基于图神经网络的节点表征

我们使用图神经网络来生成节点表征,并通过基于监督学习的对图神经网络的训练,使得图神经网络学会产生高质量的节点表征。高质量的节点表征能够用于衡量节点的相似性,同时高质量的节点表征也是准确分类节点的前提。 在节点预测任务中&#xf…

sg、xb分析

文章目录 流程分析远程调用本地调用分析结果 甚感欣慰,系统的写一下教程,希望能够帮助到大家。 流程分析 第一步,分析流程。 通过堆栈信息点到源码中并断点。 apply方法能劫持另外一个对象的方法,继承另外一个对象的属性 apply方…

Intel SGX入坑必读——《Intel SGX Explained》(个人翻译,持续更新中)

写在最前 入坑Intel SGX之前先打好基础。《Intel SGX Explained》就是入坑必读之一,有助于理解Intel SGX的原理。这里仅作个人翻译,便于加深理解,也方便感兴趣的小伙伴一起学习交流。 原文下载地址:《Intel SGX Explained》原文 …

Intel SGX入门(一)——背景篇

为什么要Intel SGX? 以云环境为例子,云租户会将自己的产品部署在云平台中,但是云平台现在普遍认为是一个不可信的地方,因为可能会有云平台管理者、同一云主机其他租户的恶意攻击,也可能云平台本身存在漏洞&#xff0c…

windows下使用SGX

前言: 这个是简单对于毫无经验的人的入门博客,杠精勿扰,大神离开。 我觉得每当下载一个新的工具的时候要先看一看他自己带的文档。 何谓SGX?不解释,您可以去看其介绍,百度搜搜即可。 win10如何下载SGX&a…

Intel SGX学习笔记(1):虚拟机Ubuntu20.04配置Intel SGX环境

写在前面 本教程仅仅适用虚拟机下的Ubuntu20.04配置Intel SGX环境,若是双系统下的Ubuntu系统,请看最后的参考连接。若是window10自带的ubuntu,也就是从微软商店下载的ubuntu系统,这个我到make preparation指令就开始疯狂报错&…

Windows10下使用Intel SGX功能(四):SGX技术分析

参考文献 Overview of Intel SGX - Part 1, SGX InternalsDeveloper Guide: Intel Software Guard Extensions (Intel SGX)(最新版)Overview of Intel SGX - Part 2, SGX Externals SGX 介绍 SGX 发展情况 SGX技术目前已经发展到SGX2。比如安全证明功…

可信启动、安全启动:SGX、TrustZone、SecureEnclave

最近在公众号上看到了一篇文章,算是又丰富了自己的安全方面的眼界。 最近看公众号取代了小视频、知乎这些东西。以前是真的不喜欢碎片化的东西,看什么学什么总是要找到书籍。但是这样的做法太过的极端,因为有时候有些事是两面性的。比如像安全…

Intel SGX 技术初探

最近公司需要开发一款使用intel 的移动终端,需要用到SGX技术,特此将调研和整理的相关资料放置于下,欢迎交流。 一、SGX技术背景 1.1 SGX技术定义 SGX全称Intel Software Guard Extensions,顾名思义,其是对因特尔体系…

Intel SGX入门(二)——SGX应用篇

大概了解SGX以后,SGX应用有哪些? 第一种,SGX应用于服务器端,云端 这一类个人觉得很需要结合代码、它们所描述的行业需求和以前的行业产品去考虑问题,毕竟是应用,不然可能体会不到精髓。 我对SGX应用的理解…

Intel SGX Explained

文章目录 SGX新增Abstract第一章 概括1.1 SGX简介1.2 大纲和问题发现 第二章 Intel体系架构背景知识2.1 Overview2.2 计算模型2.3 软件权限级别2.4 地址空间2.5 地址转换2.5.1 地址转换概念2.5.2 地址转换和虚拟化2.5.3 页表属性 2.6 执行上下文2.7 段寄存器2.8 特权级别转换2.…

sgx使用记录(Windows开发环境搭建以及sgx的简单介绍)1

sgx使用记录 相关代码仓库 ##sgx-sdk https://github.com/apache/incubator-teaclave-sgx-sdk.git##Teaclave:通用安全计算平台 https://github.com/apache/incubator-teaclave检测sgx运行环境是否支持 ##或使用cpuid命令 cpuid |grep -i sgx##或使用脚本测试 下…

Windows10下使用Intel SGX功能(一):环境搭建

文章目录 参考文献系统要求一、安装Open Enclave SDK 环境(一)什么是Open Enclave SDK(二)启动SGX功能方法一: BIOS启动方法二:软件方式启动 (三)安装必要环境(1&#xf…

Intel SGX 功能如何开启

Intel SGX 功能如何开启 我本身是 Windows10 系统, BIOS 是 ASUS 的,在想装 Ubuntu 双系统的时候,在启动 Ubuntu 安装 ISO 的时候提示说电脑的 SGX 没有开启,安装失败,安装界面都没有进去。 之后搜了下如何开启 SGX&a…

SGX的内部组件概述

导语:SGX是Intel开发的新的处理器技术,可以在计算平台上提供一个可信的空间,保障用户关键代码和数据的机密性和完整性。SGX全称Intel Software Guard Extensions,顾名思义,其是对因特尔体系(IA)…

SGX入门

如何设计SGX程序: SGX分为可信部分和不可信部分,可信部分由enclave组成(一个应用程序可以拥有一个或多个enclave),enclave存储在加密的内存中,受SGX保护,enclave一旦被建立就不能更改,所以通常…

SGX Enable

根据INTEl的官方建议, 目前的电脑主板在BIOS设置上只保留了Disabled和Software Controlled来开启和关闭SGX扩展 使用Software Controlled开关的原因官方文档有阐述,如下: 开启SGX扩展,首先需要满足以下要求: CPU具有…

Intel SGX技术详细解释(非常棒)

http://www.jos.org.cn/html/2018/9/5594.htm#b18 随着信息技术的迅速发展与广泛应用, 人类社会已经进入了一个崭新的互联网时代.一方面, 人们享受着互联网科技带来的便利; 另一方面, 由网络和信息系统构成的网络空间也面临着日益严峻的安全问题.信任是网络空间中安全交互的基…

SGX问答

0 前言 有些问题比较常见,在这里直接将问答内容贴出来,方便大家搜索。有空再重新组织文字。 (我会避免泄露私人信息) 1 内存地址翻译全部交给os,那中间经过cache也是全部交给os是嘛?这个cache这部分&…