图神经网络入门与实战:从图嵌入(GE)到图神经网络(GNN)

目录

一. 图的基本概念(Graph)

1.1 图的定义

1.2 图表示的基本概念

1.3 图的应用场景

1.4 图的分类

二. 图嵌入(Graph Embedding)

2.1 图嵌入的基本概念

2.2 图嵌入方法分类

2.3 图嵌入和图神经网络的区别

三. 图神经网络(Graph Neural Network)

3.1 图神经网络的基本概念

3.2 图神经网络的预测目标

3.3 图神经网络分类

3.4 图神经网络训练方式

四. 图神经网络应用实战

4.1 数据构造

4.2 代码实战

五. 参考文献(进阶学习)


一. 图的基本概念(Graph)

1.1 图的定义

图论(Graph theory)是对图(Graph)的数学研究,是理解复杂系统和关系的基本工具。图是节点(Node)和连接这些节点的(Edge)的集合的直观表示,图提供了表示实体及其关系的结构,如下图所示。

1.2 图表示的基本概念

(1)邻接矩阵(Adjacency matrix)

(2)度矩阵( Degree matrix)

1.3 图的应用场景

图可以将复杂系统表示为具有交互作用的实体网络,可以分析它们之间的关系,从而更深入地了解其基本结构和模式。图在各个领域都具有广泛用途:

  • 计算机科学:图可以用来模拟计算机程序的结构,从而更容易理解系统中不同组件之间是如何相互作用的
  • 物理学:图可用于模拟物理系统及其相互作用,例如粒子之间的关系及其属性
  • 生物学:图可以用来模拟生物系统,如将新陈代谢途径作为一个由相互关联的实体组成的网络
  • 社会学:图可用于研究和理解复杂的社交网络,包括社区中个体之间的关系
  • 金融学:图可用于分析股票市场趋势和不同金融工具之间的关系
  • 工程学:图可用于模拟和分析复杂系统,如交通网络和电网

这些领域内在的包含某种关系结构。例如,图是社交网络的自然表征:节点是用户,边代表用户与用户之间的联系。除此之外,图的用途非常广泛,也可以应用于关系结构并不那么自然的领域,例如,图像可以用图来表示,如下图所示。每个像素都是一个节点,边代表相邻像素之间的关系。这样就可以将基于图的算法应用到图像处理和计算机视觉任务中。

同样,一个句子也可以转换成一个图,其中节点是单词,边代表相邻单词之间的关系。这种方法在自然语言处理和信息检索任务中非常有用,因为在这些任务中单词的上下文和含义至关重要。

与文本和图像不同,图没有固定的结构,这种灵活性也使图的处理更具挑战性。没有固定的结构意味着它们可以有任意数量的节点和边,没有特定的排序。此外,图还可以表示动态数据,动态数据的实体之间的联系会随着时间的推移而发生变化。例如,用户和产品之间的关系会随着它们之间的互动而改变。在这种情况下,节点和边会被更新,以反映现实世界中的变化,如新用户、新产品和新关系。

1.4 图的分类

  • 根据图的节点间是否有方向,可将图分为无向图与有向图
  • 根据图的边是否有权重,可以将图分为无权图和有权图
  • 根据图的边和点是否具有多种类型,可以将图分为同构图和异构图

二. 图嵌入(Graph Embedding)

2.1 图嵌入的基本概念

Graph Embedding做的事情是将图表示成为低维向量,类似与nlp将词、句子等embedding。distributed representation的一体化过程,万物皆可embedding。

  • 将图中的节点表示成低维、实值、稠密的向量形式,使得得到的向量形式可以在向量空间中具有表示以及推理的能力,这样的向量可以用于下游的具体任务中。例如用户社交网络得到节点表示就是每个用户的表示向量,再用于节点分类等;
  • 将整个图表示成低维、实值、稠密的向量形式,用来对整个图结构进行分类;

图嵌入的目标是发现高维图的低维向量表示,而获取图中每个节点的向量表示是十分困难的,并且具有几个挑战,这些挑战一直在推动本领域的研究:

  • 属性选择:节点的“良好”向量表示应保留图的结构和单个节点之间的连接。第一个挑战是选择嵌入应该保留的图形属性。考虑到图中所定义的距离度量和属性过多,这种选择可能很困难,性能可能取决于实际的应用场景。
  • 可扩展性:大多数真实网络都很大,包含大量节点和边。嵌入方法应具有可扩展性,能够处理大型图。定义一个可扩展的模型具有挑战性,尤其是当该模型旨在保持网络的全局属性时。
  • 嵌入的维数:实际嵌入时很难找到表示的最佳维数。例如,较高的维数可能会提高重建精度,但具有较高的时间和空间复杂性。较低的维度虽然时间、空间复杂度低,但无疑会损失很多图中原有的信息。

2.2 图嵌入方法分类

  • 基于因式分解的方法:基于因式分解的算法以矩阵的形式表示节点之间的连接,并对该矩阵进行因式分解以获得嵌入。用于表示连接的矩阵包括邻接矩阵、拉普拉斯矩阵、节点转换转移矩阵和Katz相似矩阵等。矩阵分解方法因矩阵特性不同而不同。如果得到的矩阵是正半定的,例如拉普拉斯矩阵,可以使用特征值分解。对于非结构矩阵,可以使用梯度下降方法来获得线性时间内的嵌入。虽然矩阵分解被证明是有效的,但现有的分解方法存在计算和存储成本高的问题

  • 基于随机游走的方法:基于随机游走的方法是采用适当的抽样方法来逼近图的许多性质,如节点之间的相似性和节点的中心性。当图的信息太大,或者人们不能直接观察整个图的信息时,基于随机行走的方法可以显示出很大的优势,使用不同的邻居采样策略获得节点嵌入,典型的模型是node2vec模型和deepwalk模型。

  • 基于深度学习的方法:由于深度自动编码器能够在数据中建模非线性结构,因此被用于降维。比如SDNE, DNGR利用深度自编码器的这种能力来生成一个可以捕获图中的非线性的嵌入模型。深度学习模型的权重矩阵图上的所有节点映射到低维空间保持图像在低维空间信息。这种想法可以建模非线性结构图表数据,通过图形信息表示为一个(或一群)低维向量。然后利用节点间正向传播和梯度下降算法对设计的目标函数进行优化,得到节点嵌入。

2.3 图嵌入和图神经网络的区别
  • 图嵌入(Graph Embedding):将图节点或子图以向量的形式表达,供给现有的机器学习模型直接使用(索引、分类、回归和聚类等)。图嵌入可以使用GNN来训练得到。
  • 图神经网络(GNN):直接在图上定义一套学习机制,直接对问题建模。

举个形象的例子

图嵌入就像词嵌入,而图神经网络就像全连接神经网络。词嵌入就是词的向量表达,可以供给一个分类模型做分类。全连接神经网络可以直接对一些问题做分类。同时全连接神经网络可以帮助训练词嵌入(word2vec),同样的,图神经网络也可以帮助训练图嵌入。

这里看到了另一种解释,我觉得说的很好

图嵌入是为了把现实中的图数据映射(嵌入)到数学上的某一特征空间中,这样我们就可以用概率分布来描述这个图数据的信息,这个概率分布就是嵌入向量,它 融合了图的结构信息和节点的特征信息图嵌入是图数据挖掘的中间任务之一,比如我们要做节点分类,那就要先对图做嵌入,也就是要先拿到节点的嵌入特征向量(也就是embedding向量)后,这样才能将概率分布形式的节点输入分类器或者其他下游任务模型。

早期的图嵌入算法,就好像学一个 非常复杂的大型映射函数,是一个独立的过程,如deepwalk、line等,只是拿到独立的可以表征图数据的嵌入向量。

而图神经网络是一个 端到端(End-to-End)的过程,比如直接通过模型进行节点分类,节点的嵌入向量只是前向过程中得到的隐藏层向量 h,而且这些向量是根据特定下游任务训练出来的。我们可以通过图神经网络针对某一任务做图嵌入,比如对于节点分类任务,训练网络得到适用于节点分类的所有节点嵌入向量。

三. 图神经网络(Graph Neural Network)

3.1 图神经网络的基本概念

图神经网络的核心思想是通过消息传递机制(message-passing mechanism)聚合节点的邻居信息,并更新节点的特征表示。这个过程通常会进行多轮迭代,以便捕获图中更远距离的信息。最终,每个节点的特征表示将包含其邻居和更远节点的信息。

图神经网络的基本组成部分包括:

  • 节点特征矩阵:用于表示图中每个节点的初始特征
  • 邻接矩阵:用于表示图中节点之间的连接关系
  • 图卷积层:用于聚合邻居节点的信息并更新节点特征
  • 输出层:根据任务需求设计的输出层,用于输出预测结果
3.2 图神经网络的预测目标

  • 节点分类 (Node classification):预测图中节点类别,模型在一组已标注节点及其属性的基础上进行训练,并利用这些信息来预测未标注节点的类别。例如,它可以根据在线用户或产品的特征对其进行分类

  • 链接预测 (Link prediction):预测图中节点对之间的缺失链接。常用于知识图谱补全,补全的目标是补全实体及其关系。例如,它可用于根据人与人之间的社交网络连接来预测人与人之间的关系

  • 图分类 (Graph classification):将不同的图归入预定义类别,模型在一组标注过的图及其属性上进行训练,并利用这些信息对未见过的图进行分类。例如,分子生物学中,分子结构可以表示为图,目标是预测它们的特性,以便进行药物设计

3.3 图神经网络分类
  • Recurrent graph neural networks (RecGNNs) :递归图神经网络(Recurrent graph neural networks, RecGNNs)是图神经网络的先驱工作。RecGNNs旨在用递归神经架构学习节点表示。它们假设图中的一个节点不断地与其邻居交换信息/消息,直到稳定均衡。RecGNNs在概念上很重要,并启发了后来对卷积图神经网络的研究。特别是,基于空间的卷积图神经网络继承了消息传递的思想。

  • Convolutional graph neural networks (ConvGNNs):卷积图神经网络(Convolutional graph neural networks, ConvGNNs)将卷积操作从网格数据推广到图数据。其主要思想是通过聚合节点自身的特征xv和邻居的特征xu来生成节点v的表示,其中u∈N(v)。与RecGNNs不同,ConvGNNs通过堆叠多个图卷积层来提取高层节点表示。卷积神经网络在构建许多其他复杂的GNN模型中发挥着核心作用。基于谱的方法通过从图信号处理的角度引入滤波器来定义图卷积,其中图卷积操作被解释为从图信号中去除噪声。基于空间的方法继承了recgnn的思想,通过信息传播来定义图卷积。由于GCN弥补了基于频谱的方法和基于空间的方法之间的差距,基于空间的方法由于其具有吸引力的效率、灵活性和通用性,近年来发展迅速。

  • Graph autoencoders (GAEs) :图自动编码器(GAEs)是一种无监督学习框架,它将节点/图编码到潜在向量空间中,并从编码信息中重构图数据。GAEs用于学习网络嵌入和图生成分布。对于网络嵌入,GAEs通过重建图结构信息(如图邻接矩阵)来学习潜在节点表示。对于图的生成,有些方法是逐步生成图的节点和边,而有些方法是一次性输出一个图。

  • Spatial-temporal graph neural networks (STGNNs):时空图神经网络(STGNNs)旨在从时空图中学习隐藏的模式,这些模式在各种应用中变得越来越重要,如交通速度预测,驾驶员动作预测,人类行为识别。STGNNs的关键思想是同时考虑空间依赖和时间依赖。目前许多方法将图卷积与RNNs或cnn集成以捕获空间依赖关系,以建模时间依赖关系。

3.4 图神经网络训练方式

许多GNN(例如,ConvGNN)可以在端到端学习框架内以(半)监督或纯无监督的方式进行训练,这取决于学习任务和手边可用的标签信息。

  • 节点级分类的半监督学习。给定一个部分节点被标记而其他节点未标记的单个网络,ConvGNNs可以学习一个鲁棒的模型,该模型可以有效地识别未标记节点的类标签。为此,可以通过堆叠两个图卷积层,然后使用softmax层进行多类分类来构建端到端框架。
  • 图级分类的监督学习。图级分类旨在预测整个图的类标签。此任务的端到端学习可以通过图卷积层,图池化层和/或读出层的组合来实现。图卷积层负责精确的高层节点表示,图池化层发挥下采样的作用,每次都将每个图粗化为子结构。读出层将每个图的节点表示折叠为图表示。通过将多层感知器和softmax层应用于图表示,我们可以构建一个端到端的图分类框架。
  • 图嵌入的无监督学习。当图中没有类标签时,我们可以在端到端框架中以纯无监督的方式学习图嵌入。这些算法通过两种方式利用边级信息。一种简单的方法是采用自编码器框架,其中编码器采用图卷积层将图嵌入到潜在表示中,解码器用于重建图结构。另一种热门的方式是利用负抽样方法,抽取一部分节点对作为负抽样,而图中已有的有链接的节点对为正抽样。然后应用逻辑回归层来区分正对和负对。

四. 图神经网络应用实战

接下来借助pytorch-geometric库介绍如何构造图神经网络数据集和模型。

4.1 数据构造

图用于建模对象(节点)之间的成对关系(边)。PyG中的单个图形由torch_geometry .data的一个实例描述,Data实例默认包含以下属性:

import torch 
from torch_geometric.data import Data
edge_index=torch.tensor([[0,1], #下标从0开始
                         [1,0],
                         [1,2],
                         [2,1]],dtype=torch.long)
x=torch.tensor([[-1],[0],[1]],dtype=torch.float)

data=Data(x=x,edge_index=edge_index.t().contiguous())
>>>Data(edge_index=[2,4],x=[3,1])

import torch 
from torch_geometric.data import Data
edge_index=torch.tensor([[0,1], #下标从0开始
                         [1,0],
                         [1,2],
                         [2,1]],dtype=torch.long)
x=torch.tensor([[-1],[0],[1]],dtype=torch.float)

data=Data(x=x,edge_index=edge_index.t().contiguous())
>>>Data(edge_index=[2,4],x=[3,1])

除了持有一些节点级、边级或图级属性外,Data还提供了一些有用的实用函数,例如:

print(data.keys())
>>>['x','edge_index']

print(data['x'])
>>>tensor([[-1.0],
            [0.0],
            [1.0]])

for key,item in data:
    print(f'{key} found in data')
>>>x found in data
>>>edge_index found in data
 
'edge_attr' in data
>>>False

data.num_nodes
>>>3

data.num_edges
>>>4

data.num_node_features
>>>1

data.has_isolated_nodes()
>>>False

data.has_self_loops()
>>>False

data.is_directed()
>>>False

# Transfer data object to GPU.
device=torch.device('cuda')
data=data.to(device)
4.2 代码实战

 PYG提供了线上入门教程,可以在线跑图神经网络的代码:Colab Notebooks and Video Tutorials

接下来基于Cora数据集构造一个简单的GCN并训练,Cora是半监督图节点分类的基准数据集:图数据集之cora数据集介绍 --- 适用于GCN任务

下面这个模块的在线代码:https://colab.research.google.com/drive/14OvFnAXggxB8vM4e8vSURUp1TaKnovzX?usp=sharing

# 加载数据
from torch_geometric.datasets import Planetoid
dataset = Planetoid(root='/tmp/Cora',name='Cora')

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

# 定义两层GCN
class GCN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = GCNConv(dataset.num_node_features, 16)
        self.conv2 = GCNConv(16, dataset.num_classes)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index

        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)

        return F.log_softmax(x, dim=1)

# 模型训练
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = GCN().to(device)
data = dataset[0].to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

model.train()
for epoch in range(200):
    optimizer.zero_grad()
    out = model(data)
    loss = F.nll_loss(out[data.train_mask], data.y[data.train_mask])
    loss.backward()
    optimizer.step()
model.eval()
pred = model(data).argmax(dim=1)
correct = (pred[data.test_mask]==data.y[data.test_mask]).sum()
acc = int(correct)/int(data.test_mask.sum())
print(f'Accuracy: {acc:.4f}')
>>>Accuracy:0.8150

五. 参考文献(进阶学习)

博客:

Paper:

官网:

视频:


  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值