GAT(graph attention networks)

在这里插入图片描述预备知识:
inductive learning :测试集不参与训练
transductive learning :测试集参与训练
大部分算法都是inductive learning

GAT代码:

https://github.com/PetarV-/GAT.

动机

提出图注意力对图邻域的不同节点进行了权重指定,而且无需任何相近的矩阵操作(像转置),或者依赖之前的图结构知识。并且处理了几个基于谱的图卷积网络问题,让我们的模型可以处理归纳式以及直推式的问题。

模型

预备:

  • 输入: h = { h ⃗ 1 , h ⃗ 2 , . . . h ⃗ N } , h ⃗ i ∈ R F \mathbf{h}=\{\vec{h}_1,\vec{h}_2,...\vec{h}_N\},\vec{h}_i\in \mathbb{R}^{F} h={h 1,h 2,...h N},h iRF,N是节点数量
  • 输出: h ′ = { h ′ ⃗ 1 , h ′ ⃗ 2 , . . . h ′ ⃗ N } , h ′ ⃗ i ∈ R F ′ \mathbf{h'}=\{\vec{h'}_1,\vec{h'}_2,...\vec{h'}_N\},\vec{h'}_i\in \mathbb{R}^{F'} h={h 1,h 2,...h N},h iRF,
    为了计算attention系数,参数化了一个权重矩阵 W ∈ R F ′ × F \mathbf{W}\in \mathbb{R}^{F'\times F} WRF×F再用一个共享注意力机制(其实就是个泛函) a : R F ′ × R F ′ ⟶ R a:\mathbb{R}^{F'}\times \mathbb{R}^{F'}\longrightarrow \mathbb{R} a:RF×RFR
    在这里插入图片描述表示第 j 个节点的特征对第 i 个节点的重要性。

然后再归一化
在这里插入图片描述我们这里的注意力机制 a a a采用的还是单层的前馈型网络,相当于加权平均 ,权重向量为 a ⃗ ∈ R 2 F ′ \vec{a}\in \mathbb{R}^{2F'} a R2F,然后用LeakyRelu非线性激活函数(取斜率 α = 0.2 \alpha=0.2 α=0.2),最后系数计算的表示式为
在这里插入图片描述

  • ||是串接操作
  • N i \mathcal{N}_i Ni表示 i 的邻域
    在这里插入图片描述
    当正则化的系数被计算出来之后,用于计算相对应的节点特征输出
    在这里插入图片描述
    为了使self-attention的学习更加稳定,这里采用了多头注意力,K个独立的像上式的注意力机制被执行,其实就是用不同的参数W去进行变换,得到多个不同的权重表示,最后输出为
    在这里插入图片描述
  • ||为concatenation,
  • α i j k \alpha^{k}_{ij} αijk是第k个头的注意力系数
    最后的输出不是 F ′ F' F个维度,而是 K F ′ KF' KF,因为是K个拼接起来。
    特别地,当其用在最后一层是,用concatenatioin是不合理的
    (最后一层的输出一般为了结点分类),所以我们采用不同attention的和的平均
    在这里插入图片描述在这里插入图片描述

实验:

数据集

在这里插入图片描述

Transductive learning

在这里插入图片描述

Inductive learning

PPI:protein protein interaction
在这里插入图片描述

attention可视化

线的厚度表示attention的规则化后的系数大小。
在这里插入图片描述

代码分析

在cora数据集上(一个图,节点类型预测,2708个节点,每个节点1433个特征)单个 attention层代码:

class GraphAttentionLayer(nn.Module):
    """
    Simple GAT layer, similar to https://arxiv.org/abs/1710.10903
    """

    def __init__(self, in_features, out_features, dropout, alpha, concat=True):
        super(GraphAttentionLayer, self).__init__()
        self.dropout = dropout # 0.6
        self.in_features = in_features # 1433
        self.out_features = out_features # 8
        self.alpha = alpha # 0.2
        self.concat = concat

        self.W = nn.Parameter(torch.zeros(size=(in_features, out_features)))
        nn.init.xavier_uniform_(self.W.data, gain=1.414)
        self.a = nn.Parameter(torch.zeros(size=(2*out_features, 1))) #[16,1]
        nn.init.xavier_uniform_(self.a.data, gain=1.414)

        self.leakyrelu = nn.LeakyReLU(self.alpha)

    def forward(self, input, adj):
        h = torch.mm(input, self.W) #[2708,1433]*[1433,8]
        N = h.size()[0]
        # h.repeat(1, N).view(N * N, -1) 0~(N-1)行相同,N~2N-1行相同,以此类推。[2708*2708,8]
        # h.repeat(N, 1) 这个是[0:2708,:]==[2708:2*2708,:],---,  [2708*2708,8]
        a_input = torch.cat([h.repeat(1, N).view(N * N, -1), h.repeat(N, 1)], dim=1).view(N, -1, 2 * self.out_features) #[2708, 2708, 16]
        e = self.leakyrelu(torch.matmul(a_input, self.a).squeeze(2)) # [2708,2708,16]*[16,1].squeeze()=[2708,2708]torch.matmul用于高维的矩阵乘法

        zero_vec = -9e15*torch.ones_like(e)
        attention = torch.where(adj > 0, e, zero_vec) #大于0的位置取e,小于0的取-9e15
        attention = F.softmax(attention, dim=1)
        attention = F.dropout(attention, self.dropout, training=self.training)
        h_prime = torch.matmul(attention, h) # 对单个节点的信息用相邻的节点信息去聚合,apha_ij*W*h [2708,8]

        if self.concat:
            return F.elu(h_prime)
        else:
            return h_prime

    def __repr__(self):
        return self.__class__.__name__ + ' (' + str(self.in_features) + ' -> ' + str(self.out_features) + ')'
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值