GAT原理

GAT

一、图注意力网络概念

图注意力网络英文全称为Graph attention networks。按理来说,其缩写应该是GAN,可惜这个网名被生成式对抗网络先用了。无奈只能叫GAT,有点像山寨版的网络。但这丝毫不影响其作为一种强势GNN的存在。前面提到,GAT是一种空域的GNN。什么是空域(vertex domain),什么又是频域(spectral domain)

简单地说,空域是从空间上考虑图结构的模型,即考虑目标节点和其他节点的几何关系(有无连接)。频域的代表算法是GCN,它就会对图邻接矩阵做一些加工,然后对其进行特征分解,得到特征值,将特征向量看作常数,而卷积核作用在特征值上。在我看来,频域的好处之一是可以省很多参数,但其缺点是不太容易作用于动态图。比如,某个图在不同时刻可能会多或者少俩节点,多或者少俩连接,这样特征向量就会发生改变,所以频域GNN不太能很好适应。but,GAT这类的空域GNN能够完美应对动态图。

图形注意力网络(GAT),一种新型卷积式图形神经网络,不过它只处理一种节点或连接类型的非异构图。

二、图注意力层

GAT只需堆图注意力层就可以了,所以理解GAT只需理解图注意力层即可。

我们先了解一下图数据:一系列带连接的节点,每个节点还有自己的特征。举个栗子:

下面这个五饼状的东西就是一个无向连接的图数据了。我们把这个图叫作G,G含有5个节点(node),然后每个节点都有其邻节点(即节点之间有连接(edge)),除此之外,每个节点还有它的feature(可以是一个数值、向量或者矩阵)。 , 一共有5个节点,其中 代表的就是第i个节点的特征。

图注意力层,在文中描述为"Graph Attentional Layer"。我在下文中会简称为GAL。我们先理解何为注意力(attention),我们继续看这张图:

对于节点3,它的邻接节点只有节点2和节点4,但不代表这两个节点对节点3具有一样的重要性。这个“重要性”可以进行量化,更可以通过网络训练得出。这个“重要性”,在文中叫attention,可以通过训练得到。这便是GAT的核心创新点了

这个attention是不满足对称性(后面会证明),即节点2对节点3的attention与节点3对节点2的attention是不一样的,把每个连接(edge)当成桥的话,这个attention类似桥的宽度。当然,简化版的GAT中可以使这个attention变得对称。整个论文的数学讨论就在于如何训练attention,以及将attention融入图神经网络中。

先来看看每一层的输入与输出

我们直接看一个核心公式:

这个公式和论文中的公式(2)和公式(3)是对应的,我只是转化成了用更直观的形式。 表示节点i和节点j之间的attention系数,咱们由内向外看看这个公式:

首先权重矩阵 (为了得到相应的输入与输出的转换,我们需要根据输入的feature至少一次线性变换得到输出的feature,所以我们需要对所有节点训练一个权值矩阵:W,这个权值矩阵就是输入与输出的F个feature与输出的F'个feature之间的关系) ,是一个 尺寸的矩阵。 表示输入节点特征的维数,而 表示该层输出节点的维数。而其中的 和 表示,节点 和节点 的节点特征,如果这层GAL为输入层,那么节点特征直接就是图的原节点特征 。注意这里变量名为什么用 而不用 ,其想表达的是这个节点特征会随着层的堆叠而改变,所以用 来表示隐藏层特征hidden feature。通过前面的描述,应该不难看出 的维度是 吧。通过线代的知识,我们轻易知道 的维度为 。

公式2的内层函数是用来计算i和邻居节点j的相似度的。

重点是那个双竖线"||",这个符号在文中代表concatenate,表示张量的粘合。张量的粘合就是,[[1, 2], [3,4]]粘合[[5, 6], [7, 8]]变成[[1, 2], [3,4],[5, 6], [7, 8]]。这个栗子很形象吧,但是不同维度进行concatenate的效果是不一样的。
通过concat,我们把两个 的张量粘合成了 的大张量。然后乘以一个 的attention kernel: 。这样不就可以得到1个数么,这个数就是未加工的attention系数。用图来解释这个过程会非常直观,这里取 :

暂且用两种颜色表示 ,后面在代码中有所体现。 表示激活函数,这里用的是leaky ReLU(负倾斜率=0.2)。leaky relu不明白的百度一下,1分钟你就能明白。最后再加一层 ,不明白 的请戳《详解softmax

在这里我们思考一下,如果在上面公式中将节点 和节点 兑换位置,即 对于 的attention,是否会输出不同结果呢? 答案:是的。在论文中的attention是不满足对称性的。

看看keras代码实现,来自Daniele大神的代码(完整代码看上面提供的repo):

for head in range(self.attn_heads): 
    kernel = self.kernels[head]  # W in the paper (F x F')
    # kernels 是核函数
    attention_kernel = self.attn_kernels[head]  # Attention kernel a in the paper (2F' x 1)     # Compute inputs to attention network
    features = K.dot(X, kernel)  # (N x F')     # Compute feature combinations     # Note: [[a_1], [a_2]]^T [[Wh_i], [Wh_2]] = [a_1]^T [Wh_i] + [a_2]^T [Wh_j] 
    attn_for_self = K.dot(features, attention_kernel[0])    # (N x 1), [a_1]^T [Wh_i] 
    attn_for_neighs = K.dot(features, attention_kernel[1])  # (N x 1), [a_2]^T [Wh_j]     # Attention head a(Wh_i, Wh_j) = a^T [[Wh_i], [Wh_j]] 
    dense = attn_for_self + K.transpose(attn_for_neighs)  # (N x N) via broadcasting     # Add nonlinearty 
    dense = LeakyReLU(alpha=0.2)(dense)     # Mask values before activation (Vaswani et al., 2017)
    mask = -10e9 * (1.0 - A)     dense += mask     # Apply softmax to get attention coefficients 
    dense = K.softmax(dense)  # (N x N)

其实代码跟论文还是有些许不同的,主要是为了方便计算。我们看到这里有个for循环,表示attention heads,这个点我们先hold,我在后文中会讲这个attention heads。

在代码中:把一个 的attention kernel当作两个 的小kernel,一个负责自注意力,一个负责邻节点注意力。通过用这两个小kernel分别对 和 相乘,就能得到2个 的张量,即自注意力指标和邻注意力指标(本人定义的名字)。假设获得的自注意力指标 ,而获得的邻注意力指标 。将他们通过矩阵求和扩充到二维,即 ,可得到一张二维表格:

我们再用前面的邻接矩阵A,请看式(1),做一下mask进行过滤,即邻接矩阵A中元素为0的位置,将其注意力系数置为负无穷,我在这里简单用0代替:

这样mask一下,整个表格就会比较稀疏了。再将这个矩阵送入 ,就可以得到注意力系数矩阵了。

到此,我们可以看另一个核心公式了(得到注意力系数之后,就是对邻居节点的特征进行加权求和):

这个公式对应论文中的公式(4)。 表示这层GAL关于节点 的输出特征,图中的 表示节点i的邻接节点, 表示注意力系数,直接查注意力系数矩阵就可得到。这里的 依旧是激活函数的意思,代码中采用的是"elu",不明白elu百度一下,一分钟就可理解。其实明白了 的计算方式,这个公式很好理解吧。

看其在代码中的实现:(接着上面的,完整版请戳https://github.com/danielegrattarola/keras-gat)

			# Apply dropout to features and attention coefficients
            dropout_attn = Dropout(self.dropout_rate)(dense)  # (N x N)
            dropout_feat = Dropout(self.dropout_rate)(features)  # (N x F')

            # Linear combination with neighbors' features
            node_features = K.dot(dropout_attn, dropout_feat)  # (N x F')

            if self.use_bias:
                node_features = K.bias_add(node_features, self.biases[head])

            # Add output of attention head to final output
            outputs.append(node_features)

        # Aggregate the heads' output according to the reduction method
        if self.attn_heads_reduction == 'concat':
            output = K.concatenate(outputs)  # (N x KF')
        else:
            output = K.mean(K.stack(outputs), axis=0)  # N x F')

        output = self.activation(output)

代码中多加了一个dropout层,剩下没有解释的就是这个K了。接下来是另一个trick,上文hold的attention heads我在这里详细讲解一下。

attention heads,就是文章中的K。

对于GAL而言,它可以完全仿照CNN的操作:CNN中对于每一层特征图的卷积核,其实可以有多个,而且每个卷积核相互独立,从而使得输出特征图具有更多的channel。

GAT也可以这样操作!先看图:

上图表示K=3时的情况,这个3在哪里呢?看波浪线,每个节点到节点1都有3条波浪线。这3条波浪线就代表3个独立的attention系数,独立学习,并且有着独立的注意力系数矩阵。这也就解释了第一段代码中的那个for循环。

把公式(5)扩展到K大于1的情况(横向拼接的方式,这样聚合到的特征维度就是原来的K倍):

这个公式代表中间层的输出形式,这里的双竖线‖依旧表示concatenate

而下面公式则代表输出层的输出形式(把K个注意力机制得到的结果取平均值):

输出层的 用的是 。

以上,便是完整的清晰的GAT了。

优点

  • 引用了注意力机制,并且模型性能达到state of the art.
  • 运算相邻节点,更加具有鲁棒性,不需要整张图。
  • 更具有可解释性,公式也更直观。
  • 为邻接节点分配不同的权重,考虑到节点特征之间的相关性
  • 不需要事先得到整个图结构或所有顶点的特征(只需访问目标节点的领接节点)。
  • 能够运用于inductive任务中。

1.不需要整张Graph

引入注意力机制之后,只与相邻节点有关,即共享边的节点有关,无需得到整张graph的信息。

  • 即使丢失了i,j之间的链接,则不计算即可
  • 可以将模型运用于inductive learning,更好解释性,即使graph完全看不到completely unseen,也可以运行训练过程

算法复杂度低

2.算法复杂度低

GAT运算得到F'个特征需要的算法复杂度

F':为输出特征的个数

F:为输入特征的个数

|V| :节点的个数

|E|:节点之间连接的个数

并且引入K之后,对于每个head的运算都独立并且可以并行

3.更好鲁棒性

与GCN的不同在于,GAT针对不同的相邻节点的重要性进行预测,模型具有更好的性能并且对于扰动更加鲁棒。





 

实现

问题:

1.数据集如何准备,长什么样子

2.gat是异构图?为什么我理解的是,以一个id来构建图,但是每个节点有节点的特征,就是节点可能是一个1*n维的数组,

3.产出的是什么,几个类别吗?那如何确定需要产出多少个呢?

4.黄牛标签如何标注进来,还是产出结果在叠加标签分析?

附录:

参考文献如下:

1.图注意力网络GAT:【GNN】图注意力网络GAT(含代码) - 知乎

2.git例子:examples/gat.py · master · mirrors / danielegrattarola / keras-gat · GitCode

3.图注意力网络(Graph Attention Network, GAT) 模型解读与代码实现(tensorflow2.0)

图注意力网络(Graph Attention Network, GAT) 模型解读与代码实现(tensorflow2.0)_VariableX的博客-CSDN博客_tensorflow图注意力网络

4.图注意力网络(GAT) ICLR2018, Graph Attention Network论文详解 图注意力网络(GAT) ICLR2018, Graph Attention Network论文详解_祥瑞Coding的博客-CSDN博客_图注意力网络

5.Graph Attention Network (GAT) 的Tensorflow版代码解析 Graph Attention Network (GAT) 的Tensorflow版代码解析_酒酿小圆子~的博客-CSDN博客_gat tensorflow

6.Ker(A)——矩阵kernel Ker(A)——矩阵kernel_mutourend的博客-CSDN博客_kernel矩阵

7.异构图注意力网络 异构图注意力网络 - 知乎

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值