【图神经网络】GAT

Graph attention network
论文链接:https://arxiv.org/abs/1710.10903
图注意力:图上的某一个节点A和其他的节点去做了attention计算来更新A的特征。
在这里插入图片描述
global graph attention
计算节点A与其他所有节点的attention ,但是会丢失图的结构特征,并且造成计算量很大。

为什么会丢失结构特征?因为节点A与外围节点不是直接相连的。A的一阶连接节点其实只有橘黄色的节点,但是global graph attention还是会计算A与空白节点的关系,那我们只需要A与橘黄色节点的attention,该怎么办?
mask graph attention
只计算A节点与一阶邻居节点的 attention,此时获取到的就是关于节点A 的局部结构特征,大大减少了计算量。
在这里插入图片描述

论文中说到,共享的可训练权重矩阵W的用处是为了将输入特征转换成高维特征以此获取足够的表达能力,这个权重矩阵是作用在每个节点上的。a是共享的注意力系数,就是说每个节点的注意力系数都一样。在节点上做self-attention。这个公式的输出表示节点j对节点i的重要性。在这里,允许节点彼此学习,丢弃所有结构信息,毕竟self-attention本身也不会学习位置信息。
在这里插入图片描述

论文中说到,公式1中的注意力机制a是一个单层的前馈神经网络,由权重向量参数化
作者将图结构引入注意力机制中,只计算节点i的一阶邻居节点。

在这里插入图片描述

论文中说到,softmax的目的是为了方便在不同的节点之间比较系数。

在这里插入图片描述
以节点1为例,计算节点2对节点1的影响,节点3对节点1的影响,并更新节点1,下述代码只用于理解公式:

import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
leaky_relu = nn.LeakyReLU(negative_slope=0.2)

node_1 = np.array([[1., 2., 3., 4., 5.]])
node_1_tensor = torch.from_numpy(node_1)  # N x dim:N是节点数量,这里是1,dim是节点维度,这里是5
node_2 = np.array([[3., 4., 5., 6., 7.]])
node_2_tensor = torch.from_numpy(node_2)  # N x dim:N是节点数量,这里是1,dim是节点维度,这里是5
node_3 = np.array([[4., 5., 6., 7., 8.]])
node_3_tensor = torch.from_numpy(node_3)  # N x dim:N是节点数量,这里是1,dim是节点维度,这里是5
node_w = np.array([[1., 2., 3., 4., 5., 6.],
              [4., 5., 6., 7., 8., 7.],
              [7., 8., 9., 10., 11., 8.],
              [7., 8., 9., 10., 11., 9.],
              [7., 8., 9., 10., 11., 10.]])   # 5 x 6:假设6为最后输出的维度
node_w_tensor = torch.from_numpy(node_w)  # torch.Size([3, 5])
node_a = np.array([[1., 2., 3., 4., 5., 6., 1., 2., 3., 4., 5., 6.]])  # 2倍的F撇 torch.Size([1, 10])
node_a_tensor = torch.from_numpy(node_a)

# 线性变换
w_h1 = torch.mm(node_1_tensor, node_w_tensor)   # tensor([[ 93., 108., 123., 138., 153., 130.]], dtype=torch.float64)
w_h2 = torch.mm(node_2_tensor, node_w_tensor)   # tensor([[145., 170., 195., 220., 245., 210.]], dtype=torch.float64)
w_h1_w_h2 = torch.concat((w_h1, w_h2), dim=1)   # tensor([[ 93., 108., 123., 138., 153., 130., 145., 170., 195., 220., 245., 210.]], dtype=torch.float64)
e_1_2 = torch.matmul(w_h1_w_h2, node_a_tensor.T).squeeze()   # tensor(7210., dtype=torch.float64) 节点2对节点1的重要性

w_h1 = torch.mm(node_1_tensor, node_w_tensor)   # tensor([[ 93., 108., 123., 138., 153., 130.]], dtype=torch.float64)
w_h3 = torch.mm(node_3_tensor, node_w_tensor)  # tensor([[171., 201., 231., 261., 291., 250.]], dtype=torch.float64)
w_h1_w_h3 = torch.concat((w_h1, w_h3), dim=1)   # tensor([[ 93., 108., 123., 138., 153., 130., 171., 201., 231., 261., 291., 250.]], dtype=torch.float64)
e_1_3 = torch.matmul(w_h1_w_h3, node_a_tensor.T).squeeze()   # tensor(8040., dtype=torch.float64) 节点3对节点1的重要性

e_1_2_e_1_3 = torch.stack([leaky_relu(e_1_2), leaky_relu(e_1_3)])  # tensor([7210., 8040.], dtype=torch.float64)
a_1_2_a_1_3 = F.softmax(e_1_2_e_1_3, dim=0) # tensor([0., 1.], dtype=torch.float64) 获得归一化注意力系数a_1_2_a_1_3 

w_h1_2_w_h1_3 = torch.stack([w_h2, w_h3]).squeeze()   # torch.Size([2, 5])
# 更新了节点1的特征,该张量包含了节点2对节点1的影响和节点3对节点1的影响
node_1_tensor = F.sigmoid(torch.matmul(a_1_2_a_1_3.unsqueeze(0), w_h1_2_w_h1_3)) # torch.Size([1, 6])

Tips:
如有问题,麻烦指正,谢谢各位!
如有疑问,请留言,谢谢!
持续更新…

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Miss.wei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值