1.GAT简介
GAT(Graph Attention Network)模型是一种用于图数据的深度学习模型,由Veličković等人在2018年提出。它通过自适应地在图中计算节点之间的注意力来学习节点之间的关系,并在节点表示中捕捉全局和局部信息。
GAT模型的核心思想是通过注意力机制,对图中的节点进行加权聚合。与传统的图卷积网络(GCN)模型不同,GAT不仅考虑节点本身的特征信息,还考虑了节点与其邻居节点之间的关系。每个节点在聚合邻居节点的特征时,会分配不同的注意力权重,以捕捉不同邻居节点对该节点的贡献程度。
GAT模型具有以下特点和优势:
- 自适应学习的注意力机制:GAT模型能够根据数据自动学习节点之间的注意力权重,从而捕捉到不同节点之间的重要性和关系。
- 并行计算效率高:由于注意力权重是节点间独立计算的,可以高效地并行计算,适用于大规模图数据。
- 稀疏性:GAT模型引入了注意力系数,可以将注意力集中在有用的邻居节点上,减小计算量和存储需求。
- 灵活性:GAT模型可以根据任务需求设计不同的注意力权重计算方式,适应不同的图学习任务。
2.代码实战
模型架构分为两部分:GAT主体部分,GAT的注意力计算部分
注意力机制:首先输入参数为(节点的特征表示hi,邻接矩阵),注意这个hi可以来源于上一层,也可以是原始的;先计算每个节点到中心节点的权值,也可以称为权重或者系数,然后对所有的权值进行归一化,最后对每个邻居节点与对应的权值相乘,然后相加就得到了中心节点的最终表示,注意求权值的时候是要考虑中心节点本身的;
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class GATLayer(nn.Module):
def __init__(self, in_features, out_features, dropout, alpha, concat=True):
super(GATLayer, self).__init__()
self.in_features = in_features
self.out_features = out_features
self.dropout = dropout
self.alpha = alpha
self.concat = concat
self.W = nn.Linear(in_features, out_features)
self.a = nn.Linear(2*out_features, 1)
def forward(self, h, adj):
Wh = self.W(h) # W*h
N = h.size()[0] # Number of nodes
a_input = torch.cat([Wh.repeat(1, N).view(N*N, -1), Wh.repeat(N, 1)], dim=1).view(N, -1, 2*self.out_features)
e = F.leaky_relu(self.a(a_input).squeeze(2), negative_slope=self.alpha)
zero_vec = -9e15*torch.ones_like(e)
attention = torch.where(adj > 0, e, zero_vec)
attention = F.softmax(attention, dim=1)
attention = F.dropout(attention, p=self.dropout, training=self.training)
h_prime = torch.matmul(attention, Wh)
if self.concat:
return F.elu(h_prime)
else:
return h_prime
class GAT(nn.Module):
def __init__(self, nfeat, nhid, nclass, dropout, alpha, nheads):
super(GAT, self).__init__()
self.dropout = dropout
self.hidden = nn.ModuleList([GATLayer(nfeat, nhid, dropout, alpha, concat=True) for _ in range(nheads)])
self.out_att = GATLayer(nhid*nheads, nclass, dropout, alpha, concat=False)
def forward(self, x, adj):
x = F.dropout(x, self.dropout, training=self.training)
x = torch.cat([att(x, adj) for att in self.hidden], dim=1)
x = F.dropout(x, self.dropout, training=self.training)
x = F.sigmoid(self.out_att(x, adj))
return F.log_softmax(x, dim=1)
# 创建示例数据和邻接矩阵
adj = torch.tensor([[0, 1, 1, 0],
[1, 0, 1, 1],
[1, 1, 0, 1],
[0, 1, 1, 0]]) # 邻接矩阵
features = torch.randn(4, 5) # 特征矩阵
# 创建GAT模型
model = GAT(nfeat=5, nhid=8, nclass=2, dropout=0.6, alpha=0.2, nheads=2)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 训练模型
for epoch in range(100):
optimizer.zero_grad()
output = model(features, adj)
# 假设这里有标签数据y
y = torch.LongTensor([0, 1, 0, 1]) # 标签
loss = criterion(output, y)
loss.backward()
optimizer.step()
# 测试模型
output = model(features, adj)
_, predictions = output.max(dim=1)
correct = (predictions == y).sum().item()
accuracy = correct / len(y)
print("准确率:", accuracy)