DeepLearning | 图注意力网络Graph Attention Network(GAT)论文、模型、代码解析

本篇博客是对论文 Velikovi, Petar, Cucurull, Guillem, Casanova, Arantxa,et al. Graph Attention Networks, 2018, ICLR的解读与python复现, 全文阅读约10分钟。

博主关于图神经网络的文章 DeepLearning | 图卷积神经网络(GCN)解析(论文、算法、代码)

一、Graph Attention Network

1.1 GAT的优点

图注意力网络(GAT)是作者对图卷积网络(GCN)的改进。它的主要创新点在于利用了注意力机制(Attention Mechanism)来自动的学习和优化节点间的连接关系,这一作法有以下几个优点:

  1. 克服了GCN只适用于直推式学习的缺陷(在训练期间需要测试时的图数据),可以应用于我们熟悉的归纳式学习任务(在训练期间不需要测试时的图数据)。
  2. 使用注意力权重代替了原先非0即1的节点连接关系,即两个节点间的关系可以被优化为连续数值,从而获得更丰富的表达
  3. 由于attention值的计算是可以在节点间并行进行的,网络的计算相当高效

1.2 Graph Attention layer的输入输出

作为一层网络,图注意力层的输入为

h = { h 1 , . . . , h N } , h i R F h=\{h_{1},...,h_{N}\}, h_{i} \in \mathbb{R}^{F}
这里的 N N 是图的节点个数, h i h_{i} 表示节点的特征向量, F F 表示特征维度。
图注意力层的输出为
h = { h 1 , . . . , h N } , h i R F {h}'=\{{h}'_{1},...,{h}'_{N}\}, {h}'_{i} \in \mathbb{R}^{{F}'}

同样的, F {F}' 表示输出的特征维度。
从图注意力层的输入输出可以看出,其本质上也是对特征的一种变换,和其余的网络层功能是类似的。

1.3 Graph Attention layer的attention机制

首先需要定义一个特征变换矩阵 W R F × F W \in \mathbb{R}^{F \times {F}'} 用于每一个节点从输入到输出的变换。

  1. GAT中的attention机制被称为self-attention,记为 f f ,其功能如下:

    e i j = f ( W h i , W h j ) e_{ij}=f(Wh_{i},Wh_{j})

    如图所示,该式表示了self-attention利用节点 i i 和节点 j j 的特征作为输入计算出了 e i j e_{ij} , 而 e i j e_{ij} 则表示了节点 j j 对于节点 i i 的重要性。
    在这里插入图片描述

  2. 需要说明的是,这里的节点 j j 是节点 i i 的近邻,而节点 i i 可能是拥有多个近邻的,因此就有了下面的 s o f t m a x softmax 归一化操

    a i j = s o f t m a x ( e i j ) = e x p ( e i j ) k χ i e x p ( e i k ) a_{ij}=softmax(e_{ij})=\frac{exp(e_{ij})}{\sum_{k \in \chi_{i} }exp(e_{ik})}
    χ i \chi_{i} 是节点 i i 的近邻集合。

  3. 那么说了这么久,这个self-attention机制,也就是我们一开始提到的 a ( W h i , W h j ) a(Wh_{i},Wh_{j}) 是怎么计算的呢?其实也很简单

    f ( W h i , W h j ) = L e a k y R e L U ( a [ W h i W h j ] ) f(Wh_{i},Wh_{j}) = LeakyReLU(a[Wh_{i} || Wh_{j}])

    这里的 a R 2 F a \in \mathbb{R}^{2{F}'} 表示需要训练的网络参数, || 表示的是矩阵拼接操作, L e a r k y R e L u LearkyReLu 则是一种激活函数,是 R e L u ReLu 的一种改进。

  4. 最后给出图感知层的定义,即

    h i = σ ( j χ i a i j W h j ) {h}'_{i}=\sigma(\sum_{j \in \chi_{i}}a_{ij}Wh_{j})

上面就是GAT的attention计算方法了,其中会有两个知识点会影响理解

  1. self-attention机制为什么可以表示节点间的重要性
  2. L e a r k y R e L u LearkyReLu 的定义

对于上面这两点,如果知道的话,再结合对GCN的理解,可以很容易的get到GAT的点和含义,如果不清楚的话可能会有点迷糊。

  1. attention机制实际上是在有监督的训练下计算两个向量的匹配程度,从而揭示其重要性和影响,由于本篇博客不是专门介绍attention的,这里不做多余的解释,日后会补上相应的博客。
  2. L e a r k y R e L u LearkyReLu 的定义如下:
    y = { x i f x > = 0 a x e l s e y=\left\{\begin{matrix} x & if x >=0 \\ ax & else \end{matrix}\right.
    即引入了一个系数 a a 来取消 R e L U ReLU 的死区。

1.4 多头attention机制

  1. 为了稳定self−attention的学习过程,GAT还采用了一种多头机制,即独立的计算K个attention,然后将其获得的特征拼接起来,获得一个更全面的表述,表示如下
    h i = k = 1 K σ ( j χ i a i j k W k h j ) {h}'_{i}=||^{K}_{k=1} \sigma(\sum_{j \in \chi_{i}}a^{k}_{ij}W^{k}h_{j})
    这里的 || 表示矩阵拼接的操作,其余的符号和上面描述的一致。
  2. 同时,考虑到在网络的最后一层输出层如果还采用这种拼接的方式扩大特征维度,可能不合理,因此,GAT又为输出层定义了平均的操作
    h i = σ ( 1 K k = 1 K j χ i a i j k W k h j ) {h}'_{i}= \sigma(\frac{1}{K}\sum^{K}_{k=1}\sum_{j \in \chi_{i}}a^{k}_{ij}W^{k}h_{j})

多头attention机制如图所示
在这里插入图片描述

二、GAN的python复现

模型的核心代码如下

import numpy as np
import tensorflow as tf

from utils import layers
from models.base_gattn import BaseGAttN

class GAT(BaseGAttN):
    def inference(inputs, nb_classes, nb_nodes, training, attn_drop, ffd_drop,
            bias_mat, hid_units, n_heads, activation=tf.nn.elu, residual=False):
        attns = []
        for _ in range(n_heads[0]):
            attns.append(layers.attn_head(inputs, bias_mat=bias_mat,
                out_sz=hid_units[0], activation=activation,
                in_drop=ffd_drop, coef_drop=attn_drop, residual=False))
        h_1 = tf.concat(attns, axis=-1)
        for i in range(1, len(hid_units)):
            h_old = h_1
            attns = []
            for _ in range(n_heads[i]):
                attns.append(layers.attn_head(h_1, bias_mat=bias_mat,
                    out_sz=hid_units[i], activation=activation,
                    in_drop=ffd_drop, coef_drop=attn_drop, residual=residual))
            h_1 = tf.concat(attns, axis=-1)
        out = []
        for i in range(n_heads[-1]):
            out.append(layers.attn_head(h_1, bias_mat=bias_mat,
                out_sz=nb_classes, activation=lambda x: x,
                in_drop=ffd_drop, coef_drop=attn_drop, residual=False))
        logits = tf.add_n(out) / n_heads[-1]
    
        return logits

三、GAT代码、论文、数据集下载

微信搜索“老和山算法指南”获取下载链接与技术交流群
在这里插入图片描述
有问题可以私信博主,点赞关注的一般都会回复,一起努力,谢谢支持。

发布了74 篇原创文章 · 获赞 269 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/Liangjun_Feng/article/details/105417981