前言
回顾之前的Node Embedding:
将图中的节点嵌入到d维空间,并确保图中相似的节点能够嵌在一起。
即学习一个编码器ENCENCENC确保图的节点嵌入到embedding space依然能够描述原空间节点之间的相似性。
在Node Embedding中,我们需要设计:
-
Encoder:将每个节点映射到一个低维向量
-
Similarity function:指定向量空间中的关系如何映射到原始网络中的关系
该方法的缺点:
- O(∣V∣)O(|V|)O(∣V∣)的参数
- 节点之间不共享参数
- 每个节点都有自己独特的嵌入
- 不能为训练期间未看到的节点生成嵌入
- 不合并节点特性
本文将讨论基于图神经网络(GNNs)的深度学习方法,用于节点的嵌入。
通过GNNsGNNsGNNs,可以基于图结构的多层非线性转换来学习到一个Deep Graph Encoders,完成节点到嵌入向量的映射。
如下图,我们的输入是一张复杂的图,通过多次图卷积层、激活函数后,有GNNs自动完成节点、或者子图的嵌入。
完成嵌入后,我们可以完成以下任务:
- 节点分类:
- 预测给定节点的类型
- 链接预测:
- 预测两个节点是否相连
- 社区检测:
- 识别紧密相连的节点集群
- 网络相似度:
- 两个(子)网络的相似度
二、Deep Learning for Graphs
假设我们有一张图GGG:
- VVV是顶点集
- AAA是邻接矩阵
- 节点特征矩阵X∈Rm×∣V∣X∈R^{m\times |V|}X∈Rm×∣V∣
- vvv:顶点集VVV中的一个顶点;
- N(v)N(v)N(v):vvv的邻居节点集
什么是顶点的feature?
就是描述顶点的一组向量
- 对于社交网络,node feature可以是用户配置文件,用户图像
- 对于生物网络,node feature可以是基因表达谱,基因功能信息
- 如果数据中没有feature,可以使用one-hot向量或者全为1的常数向量。
如何将feature输入到神经网络中?
一个简单的想法:连接邻接矩阵和特征,把它们一起输入深层神经网络:
该想法的缺点:
- 参数个数过多,O(∣V∣)O(|V|)O(∣V∣)数量级;训练不稳定且容易过拟合
- 不适用于不同大小的图,因为神经网络的输入节点是固定的
- 对节点排序敏感,同一张图有多种表示方式,不同表示方式对应不同的输入,从而导致不同的输入,对结果有影响。
想法:
将网格上的卷积神经网络泛化到图上,并应用到节点特征数据。
但是在现实世界中,CNN中所谓的卷积窗口在图上难以定义:
- 图上没有固定的局部或滑动窗口的概念
- 节点的顺序不是固定的
在CNN的卷积中,可以看作中间的节点和上下左右八个方向的邻居作为一个集合进行卷积操作。
类似的,在图中可以将一个节点和它的邻居作为一个集合进行卷积操作。
因此,在图中,根据节点的邻域定义一个计算图;即一个节点的信息由其邻居的feature和自身的feature聚合而来:
图卷积神经网络如何工作?
想法是节点的领域定义了神经网络架构,即感兴趣节点的周围节点定义了神经网络的结构。
如想对上图的红色节点进行预测,想法是从它的邻居那里获取信息,邻居将从邻居那里获取信息。
接下来需要考虑如何沿着边传播这些信息,如何沿着网络边缘转换它,如何聚合信息。
可以认为图神经网络的方式是一个两步过程:
1、确定节点计算图
2、传播节点信息,在计算图上传播和转换它
这个计算图定义了底层神经网络的架构和结构
以下图六个节点的小图为例子:
目标节点是A,基于A节点的本地网络邻域生成一个计算图用于学习节点嵌入。计算图如上图右侧所示,计算图就是一个Neural networks。
在计算图中,需要去学习如何沿着边缘的消息转换符(如何将节点嵌入沿着边进行传播)和聚合运算符(如何将从不同边收到的信息进行聚合)。
网络邻域定义了各节点的计算图,所以每个节点都有不一样的计算图。如下所示;
还需要定义计算图的层数,而不是像之前的PageRank一样一直运行直到收敛。这里的层数可以理解为跳数(hop),以几跳的邻居构成各节点的计算图。下图是以2跳作为计算图的层数,生成节点的嵌入;
Layer-k embedding可以理解成从k跳之外的节点获取信息。观察上图还能发现,计算图中每个节点在每一层的嵌入向量都不一样。
Layer-0表示的是各节点的feature,Layer-1是各节点转化汇聚邻域节点所得到的信息,不同于Layer-0的feature。
第一个问题:Neighborhood aggregation
如何聚合来自不同边的节点的信息?即下图中的box应该做些什么
其实就是确定聚合函数,聚合函数需要满足排列不变性。即函数输出的结果不会因为输入节点的次序改变而改变。
基本方法:平均邻居信息并应用神经网络
计算公式如下:
- Wk:W_k:Wk:对邻居节点的信息进行转化的矩阵
- Bk:B_k:Bk:对本节点的信息进行转化的矩阵
- Wk、BkW_k、B_kWk、Bk是所有节点都共享的参数
上面的公式做了两件事情:
- 信息转换
WkW_kWk将上一层的邻居节点的信息进行线性转换,BkB_kBk将上一层的本届点信息进行线性转换。- 信息聚合
∑\sum∑表示将邻居节点以求平均的方式进行聚合
矩阵化(向量化)
对各节点单独使用上面的聚合函数,工作量很大。向量化使用矩阵乘法可以加快运算速度。
在GNN中,许多聚合函数可以通过(稀疏)矩阵运算有效地执行:
-
令H(K)=[h1(k)⋯h∣V∣(k)]TH^{(K)}=[h_1^{(k)}\cdots h_{|V|}^{(k)}]^TH(K)=[h1(k)⋯h∣V∣(k)]T
-
A表示邻接矩阵,Av,:A_{v,:}Av,:表示第vvv行的所有列
-
然后:∑u∈Nvhu(k)=Av,:H(k)\sum _{u∈N_v}h^{(k)}_u=A_{v,:}H^{(k)}∑u∈Nvhu(k)=Av,:H(k)
-
令D表示一个对角矩阵:Dv,v=Deg(v)=∣N(v)∣D_{v,v}=Deg(v)=|N(v)|Dv,v=Deg(v)=∣N(v)∣
-
因此,
上图向量化表示为:
第二个问题:Training the Model
如何训练GCN去生成embeddings?
首先需要确定一个损失函数:
- 将最后一层的输出zv=hv(K)z_v=h_v^{(K)}zv=hv(K)作为节点的最终的embedding
- 可以将这些嵌入到任何损失函数中,并运行SGD来训练权重参数
这里需要训练的权重参数是:WkW_kWk和BkB_kBk。
监督学习:
在监督学习中,我们想要最小化损失函数LLL:
- yyy:节点的真实标签
- f(zv)f(z_v)f(zv):根据节点embedding预测的标签
- LLL:损失函数可以定义为L2范式,在分类任务中可以是交叉熵;
交叉熵损失函数形式如下:
无监督学习:
在无监督学习中没有节点标签可用,但使用图形结构作为监督。
-
如节点的相似性(“相似”节点具有相似的嵌入)
- 这里就是前面设定随机游走策略,然后处于同一游走路径上的节点内积要大一些