图注意力网络(GAT)
一句话概述
图注意力网络(Graph Attention Network, GAT)将注意力机制引入图神经网络,让模型自动学习不同邻居对目标节点的重要性权重。与GCN中邻居权重固定(由图的度决定)不同,GAT的注意力权重是动态计算的——根据目标节点和邻居节点的特征,通过可学习的注意力函数计算相关性分数。GAT的核心计算过程为:首先对每个邻居对(i,j)计算注意力系数e_{ij}=LeakyReLU(a^T[Wh_i || Wh_j]),然后通过softmax归一化得到注意力权重α_{ij},最后对邻居特征加权求和h_i'=σ(Σ_j α_{ij}Wh_j)。多头注意力机制进一步增强了GAT的稳定性和表达能力。GAT不需要预先知道图结构,且可以处理有向图和归纳学习场景。
💡 核心要点:①GAT通过注意力机制动态计算邻居权重,而非GCN的固定归一化权重 ②注意力系数通过可学习的a向量和特征拼接计算 ③多头注意力(Multi-head)增强稳定性和表达能力 ④GAT可以处理有向图和归纳学习,不需要全局图结构
教学与演示
一、GAT的注意力机制:动态邻居权重
是什么(定义):GAT(Graph Attention Network)由Petar Veličković等人于2018年提出。其核心创新是将注意力机制引入邻居聚合:每个邻居j对目标节点i的重要性不是固定的(如GCN中的1/√(d_i·d_j)),而是通过一个可学习的注意力函数动态计算。GAT的注意力计算包含三个步骤:①线性变换Wh(共享权重矩阵),②拼接Wh_i和Wh_j后计算注意力分数e_{ij}=a^T[Wh_i||Wh_j],③LeakyReLU激活+softmax归一化得到最终权重α_{ij}。
大白话 GAT就像是"有选择地听朋友意见"。GCN是"所有朋友的意见平均对待"——不管你朋友说什么,都按相同的权重采纳。GAT是"重点听靠谱的朋友说"——对于每个朋友,你会根据"你们俩的相似度"(注意力分数)来决定听多少。比如你要决定买什么手机,科技达人的意见权重很高,而从不研究手机的朋友的意见权重很低。这个"谁更重要"的判断不是固定的,而是根据具体内容动态变化的。
为什么(原理):GAT的注意力机制解决了GCN的三个核心局限:①GCN的邻居权重是固定的(由度决定),无法适应不同任务;②GCN假设图是无向的,注意力可以自然处理有向图(e_{ij}≠e_{ji});③GCN需要全局图结构,GAT的注意力只依赖邻居特征,可以用于归纳学习。GAT的注意力本质上是"self-attention on graphs"——在邻居集合上计算注意力,而非在整个序列上。
import numpy as np
# GAT注意力机制的核心实现
# 演示如何动态计算邻居权重
class GATLayer:
def __init__(self, d_in=4, d_out=3):
np.random.seed(42)
# 共享的线性变换权重矩阵 W
self.W = np.random.randn(d_in, d_out) * 0.3
# 注意力向量 a(用于计算注意力分数)
# 注意:a需要2*d_out维,因为要拼接两个向量
self.a = np.random.randn(2 * d_out, 1) * 0.1
def attention_score(self, h_i, h_j):
"""计算节点i对邻居j的注意力分数"""
# 步骤1:拼接两个节点的特征
concat = np.concatenate([h_i, h_j]) # 形状: (2*d_out,)
# 步骤2:计算原始注意力分数 e_{ij} = a^T [Wh_i || Wh_j]
e_ij = concat @ self.a # 标量
return e_ij[0]
def forward_one_node(self, X, A, node_idx):
"""对单个节点执行GAT消息传递"""
# 变换当前节点特征
h_i = X[node_idx] @ self.W # Wh_i
# 找到邻居(包括自身)
neighbors = np.where(A[node_idx] == 1)[0]
neighbors = np.append(neighbors, node_idx) # 添加自环
# 计算所有邻居的注意力分数
attention_scores = []
neighbor_features = []
for nbr in neighbors:
h_j = X[nbr] @ self.W # Wh_j
e_ij = self.attention_score(h_i, h_j)
attention_scores.append(e_ij)
neighbor_features.append(h_j)
attention_scores = np.array(attention_scores)
neighbor_features = np.array(neighbor_features)
# LeakyReLU激活
attention_scores = np.where(attention_scores > 0, attention_scores, 0.2 * attention_scores)
# Softmax归一化得到注意力权重
scores = attention_scores - np.max(attention_scores)
alpha = np.exp(scores) / np.sum(np.exp(scores))
# 加权求和
h_i_new = np.sum(alpha.reshape(-1, 1) * neighbor_features, axis=0)
return h_i_new, alpha, neighbors
def forward_all(self, X, A):
"""对所有节点计算GAT"""
n = X.shape[0]
d_out = self.W.shape[1]
new_X = np.zeros((n, d_out))
all_alpha = []
for i in range(n):
new_X[i], alpha, _ = self.forward_one_node(X, A, i)
all_alpha.append(alpha)
return new_X, all_alpha
# 创建示例图
A = np.array([
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 1],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
])
X = np.array([
[0.5, 0.2, 0.1, 0.8],
[0.1, 0.9, 0.3, 0.2],
[0.3, 0.1, 0.7, 0.1],
[0.8, 0.1, 0.2, 0.5],
[0.2, 0.6, 0.1, 0.3],
])
gat = GATLayer(d_in=4, d_out=3)
# 分析节点0的注意力
print("=== GAT注意力机制演示 ===\n")
print("节点0的邻居:1和3(加上自身0)\n")
h_new, alpha, neighbors = gat.forward_one_node(X, A, 0)
print(f"节点0的注意力权重:")
for i, (nbr, a) in enumerate(zip(neighbors, alpha)):
print(f" 邻居{nbr}: α = {a:.4f}")
print(f"\n→ 节点0对邻居3的关注度({alpha[2]:.4f})高于邻居1({alpha[1]:.4f})")
print("→ 这是因为节点0和3的特征更相似(通过注意力函数计算)")
print("→ 而GCN中,两者的权重都是固定的1/√(d_0·d_nbr)")
# 全图GAT
new_X, all_alpha = gat.forward_all(X, A)
print(f"\n\n=== 全图GAT输出 ===")
print(f"输入形状: {X.shape} → 输出形状: {new_X.shape}")
for i in range(5):
print(f" 节点{i}: {np.round(new_X[i], 3)}")
大白话 GAT的注意力计算就是"打分+归一化"。先给每个邻居打分——分数取决于"你是什么样的"和"邻居是什么样的"(拼接Wh_i和Wh_j),然后通过一个可学习的评分器(a向量)给出分数。接着用softmax把分数变成百分比——所有邻居的百分比加起来等于100%。最后用这个百分比来决定每个邻居的意见采纳多少。LeakyReLU确保即使分数为负,也有一个小梯度,防止"零梯度"问题。
什么用(应用):GAT在多个图基准上超越了GCN。在Cora节点分类上,GAT(多注意力头)达到了约83%的准确率(vs GCN的81%)。GAT的注意力权重具有可解释性——可以可视化哪些邻居对分类决策最重要。GAT特别适合异质图(节点特征差异大)和需要归纳学习的场景(如动态社交网络中的新用户)。
哪些坑(缺点):GAT的计算复杂度高于GCN——每个节点需要与每个邻居独立计算注意力分数,复杂度为O(|V|·F·F' + |E|·F'),其中F和F'是输入输出维度。对于稠密图(边数接近n²),计算开销很大。此外,GAT的注意力只考虑节点特征,没有利用边特征(如边的类型、权重),GATv2通过修改注意力计算顺序解决了原版GAT的"静态注意力"问题。
二、多头注意力:稳定训练与增强表达
是什么(定义):GAT引入多头注意力(Multi-head Attention)来增强模型稳定性。具体做法是:并行计算K个独立的注意力头(每个头有独立的W^k和a^k),然后将K个头的输出进行拼接(concat)或平均(average)。对于中间层(除最后一层外),使用拼接:h_i' = ||{k=1}^K σ(Σ_j α{ij}^k W^k h_j)。对于最后一层(预测层),使用平均:h_i' = σ(1/K Σ_k Σ_j α_{ij}^k W^k h_j)。
大白话 多头注意力就是"多个专家同时打分"。一个专家(单头)打分可能不稳定——这次给邻居A打分高,下次给邻居B打分高。多个专家(多头)各自独立打分,最后把意见汇总(拼接或平均),结果更稳定、更全面。就像面试时多个面试官各自打分,最后综合评定——比一个面试官说了算更公平、更可靠。
为什么(原理):多头注意力的有效性来自两个方面。第一,稳定性——多个头的平均减少了单个头的方差,类似于集成学习(ensemble)。第二,多样性——不同的头可能学习到不同的注意力模式(有的头关注局部结构,有的关注全局特征),拼接后融合了多视角信息。原GAT论文使用K=8个头,实验表明多头显著提升了性能。
import numpy as np
# GAT多头注意力实现
# 演示多头如何增强稳定性和表达能力
class MultiHeadGATLayer:
def __init__(self, d_in=4, d_out=3, num_heads=3):
np.random.seed(42)
self.num_heads = num_heads
self.d_out = d_out
# 为每个头创建独立的权重矩阵和注意力向量
self.W = [np.random.randn(d_in, d_out) * 0.3 for _ in range(num_heads)]
self.a = [np.random.randn(2 * d_out, 1) * 0.1 for _ in range(num_heads)]
def single_head_attention(self, X, A, node_idx, head_idx):
"""单个注意力头的计算"""
W = self.W[head_idx]
a = self.a[head_idx]
h_i = X[node_idx] @ W
neighbors = np.where(A[node_idx] == 1)[0]
neighbors = np.append(neighbors, node_idx)
scores = []
features = []
for nbr in neighbors:
h_j = X[nbr] @ W
concat = np.concatenate([h_i, h_j])
e_ij = concat @ a
e_ij = np.where(e_ij > 0, e_ij, 0.2 * e_ij)[0]
scores.append(e_ij)
features.append(h_j)
scores = np.array(scores)
features = np.array(features)
# Softmax
scores = scores - np.max(scores)
alpha = np.exp(scores) / np.sum(np.exp(scores))
# 加权求和
output = np.sum(alpha.reshape(-1, 1) * features, axis=0)
return output, alpha
def forward(self, X, A, concat=True):
"""多头GAT前向传播"""
n = X.shape[0]
all_head_outputs = []
all_attentions = []
for h in range(self.num_heads):
head_outputs = np.zeros((n, self.d_out))
head_attn = []
for i in range(n):
head_outputs[i], alpha = self.single_head_attention(X, A, i, h)
head_attn.append(alpha)
all_head_outputs.append(head_outputs)
all_attentions.append(head_attn)
if concat:
# 拼接多头输出
output = np.hstack(all_head_outputs) # (n, num_heads*d_out)
else:
# 平均多头输出(最后一层)
output = np.mean(all_head_outputs, axis=0) # (n, d_out)
return output, all_attentions
# 演示多头GAT
X = np.array([
[0.5, 0.2, 0.1, 0.8],
[0.1, 0.9, 0.3, 0.2],
[0.3, 0.1, 0.7, 0.1],
[0.8, 0.1, 0.2, 0.5],
[0.2, 0.6, 0.1, 0.3],
])
A = np.array([
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 1],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
])
gat_mh = MultiHeadGATLayer(d_in=4, d_out=3, num_heads=3)
# 拼接模式(中间层)
output_concat, attns = gat_mh.forward(X, A, concat=True)
print("=== GAT多头注意力 ===\n")
print(f"头数: {gat_mh.num_heads}")
print(f"拼接输出形状: {output_concat.shape} ({X.shape[0]}个节点, {3*3}维)")
print("→ 每个头输出3维,3个头拼接后9维")
# 展示不同头的注意力差异
print("\n不同注意力头对节点0的邻居权重:")
for h in range(3):
print(f" 头{h+1}: {np.round(attns[h][0], 3)}")
print("\n观察:不同头给邻居分配了不同的权重")
print("→ 头1可能更关注邻居1,头2更关注邻居3")
print("→ 多头融合了多种注意力模式,比单头更稳定、更全面")
大白话 多头GAT的中间层用"拼接"(把所有专家的意见放在一起),最后一层用"平均"(综合所有专家的意见给出最终答案)。中间层拼接是因为需要保留更多信息给下一层处理;最后一层平均是因为输出维度需要和类别数一致,平均是最自然的融合方式。
什么用(应用):多头GAT在PPI(蛋白质相互作用)数据集上达到了当时最优的归纳学习结果(micro-F1=0.973)。GAT的注意力机制启发了后续许多工作——GATv2修复了静态注意力问题,HAN(异构图注意力网络)扩展到异构图,MAGNN处理元路径。GAT的注意力可解释性也被用于药物发现中识别关键分子子结构。
哪些坑(缺点):原版GAT存在"静态注意力"问题——注意力分数的排序对所有节点是相同的(即如果节点j对节点i最重要,那么j对所有节点的注意力排名都是第一)。GATv2通过交换W和a的顺序(先计算Wh_i和Wh_j,再分别乘a的前半和后半)解决了这个问题。此外,多头注意力的计算开销是单头的K倍,对于大图需要权衡头数和效率。
三、GAT vs GCN:归纳学习与动态权重
是什么(定义):GAT相比GCN的核心优势在于:①动态权重——注意力权重依赖节点特征,而非固定图结构;②归纳学习(Inductive Learning)——可以处理训练时未见过的节点和图,因为注意力计算只依赖局部邻居特征;③自然处理有向图——注意力分数e_{ij}≠e_{ji},天然支持有向边。GCN则需要整个图的邻接矩阵进行归一化,无法直接泛化到新图。
大白话 GAT和GCN的区别就像"关系找人"和"自己判断"。GCN是"关系找人"——你信任谁取决于你们的社交关系(共同朋友数、度),这是固定的。GAT是"自己判断"——你信任谁取决于你们说了什么(特征),这是动态的。一个新朋友来了,GCN需要重新计算整个图的归一化,GAT可以直接根据特征计算注意力,立即可用。
为什么(原理):GAT的归纳学习能力源于其"局部性"——注意力计算只涉及目标节点和邻居节点的特征,不需要全局图信息(如度矩阵)。因此,GAT的参数(W和a)训练好后,可以直接应用于新的图结构。而GCN的归一化依赖全局度矩阵,新图需要重新计算。这使得GAT在动态图、异构图、跨图迁移等场景中更加灵活。
import numpy as np
# GAT vs GCN:归纳学习能力对比
# 演示GAT如何直接应用于新图而GCN需要重新归一化
class GATvsGCN:
def __init__(self):
pass
def gcn_normalize(self, A):
"""GCN归一化:需要全局图信息"""
A_tilde = A + np.eye(A.shape[0])
D_tilde = np.diag(np.sum(A_tilde, axis=1))
D_inv_sqrt = np.diag(1.0 / np.sqrt(np.diag(D_tilde)))
return D_inv_sqrt @ A_tilde @ D_inv_sqrt
def demonstrate(self):
print("=== GAT vs GCN:归纳学习能力 ===\n")
# 训练时的图
A_train = np.array([
[0, 1, 0, 1],
[1, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0],
])
print("训练图(4个节点):")
print(A_train)
A_norm_train = self.gcn_normalize(A_train)
print(f"\nGCN:训练时计算的归一化矩阵(4×4):")
print(np.round(A_norm_train, 3))
# 测试时的新图(不同大小)
A_test = np.array([
[0, 1, 1],
[1, 0, 0],
[1, 0, 0],
])
print(f"\n新图(3个节点,训练时未见):")
print(A_test)
print(f"\nGCN:训练时的归一化矩阵是4×4的,无法应用于3×3的新图!")
print(" → 需要重新计算归一化(且需要重新训练)")
print(" → 这是GCN的转导学习限制")
print(f"\nGAT:注意力计算只依赖邻居特征,不依赖全局图结构")
print(" → W和a训练好后,可以直接应用于任意大小的新图")
print(" → 只需要计算新节点与邻居的注意力分数")
print(" → 这就是GAT的归纳学习能力!")
print("\n\n总结:")
print("┌──────────┬──────────────┬──────────────┐")
print("│ 特性 │ GCN │ GAT │")
print("├──────────┼──────────────┼──────────────┤")
print("│ 邻居权重 │ 固定(度) │ 动态(注意力)│")
print("│ 归纳学习 │ 否 │ 是 │")
print("│ 有向图 │ 需特殊处理 │ 自然支持 │")
print("│ 计算效率 │ 高 │ 中 │")
print("│ 可解释性 │ 低 │ 高(注意力权重)│")
print("└──────────┴──────────────┴──────────────┘")
GATvsGCN().demonstrate()
大白话 GAT就像一个"学会了看人"的社交达人——无论加入哪个新圈子,他都能根据每个人的特质(特征)来判断谁值得深交(注意力),不需要重新学习。GCN就像一个"按资排辈"的组织——每个人的地位由他在组织中的位置决定(度),换一个组织就得重新排。这就是GAT的归纳学习能力——学到的是"如何判断",而不是"谁是谁"。
什么用(应用):GAT的归纳学习能力在动态图场景中特别有价值。在社交网络中,新用户不断加入,GAT可以直接为新用户生成高质量嵌入。在药物发现中,训练好的GAT可以直接应用于新分子(新图结构),预测其性质。在知识图谱中,新实体不断出现,GAT可以灵活处理。
哪些坑(缺点):GAT的归纳学习虽然灵活,但完全依赖节点特征——如果新节点的特征分布与训练数据差异很大,注意力权重可能不准确。此外,GAT在小图上可能过拟合(注意力参数多),需要正则化。GAT的计算复杂度高于GCN,在大规模图上需要采样策略(如结合GraphSAGE的采样方法)。
概念关系图谱
| 概念 | 核心含义 | 与AI的关系 | 关联概念 |
|---|---|---|---|
| 图注意力(Graph Attention) | 动态计算邻居重要性的注意力机制 | GAT的核心创新,替代GCN的固定权重 | 多头注意力、自注意力 |
| 注意力系数(α_{ij}) | 节点i对邻居j的归一化注意力权重 | 决定邻居信息在聚合中的贡献 | Softmax、权重 |
| 多头注意力 | 并行使用多个注意力头,拼接或平均输出 | 增强GAT稳定性和表达能力 | 集成学习、多样性 |
| 归纳学习 | 可以处理训练时未见过的节点和图 | GAT相比GCN的核心优势 | 转导学习、泛化 |
| 静态注意力问题 | 注意力排序对所有节点相同 | 原版GAT的局限,GATv2修复 | 动态注意力 |
重点答疑
Q1: GAT的注意力与Transformer的自注意力有什么区别?
两者都使用Q、K、V的框架,但关键区别:①Transformer的自注意力是在整个序列上计算(所有位置两两比较),GAT的注意力只在邻居集合上计算;②Transformer有独立的Q、K、V变换,GAT使用共享的W变换后拼接Wh_i和Wh_j;③GAT的注意力引入了LeakyReLU,而Transformer使用缩放点积。本质上,GAT是"图上的自注意力",只关注邻居而不是所有节点。
Q2: 什么是GAT的静态注意力问题?
原版GAT中,注意力分数的排序对所有节点是相同的——如果节点j对节点i的注意力最高,那么j对所有其他节点的注意力排名也是第一。这意味着注意力不是真正"动态"的,而是由节点特征决定的一个全局排序。GATv2通过交换计算顺序解决了这个问题:先分别计算Wh_i和Wh_j的注意力贡献,再相加,使得注意力排序真正依赖于目标节点i。
Q3: GAT和GraphSAGE的主要区别是什么?
两者都支持归纳学习,但聚合方式不同:GraphSAGE使用固定的聚合函数(平均、LSTM、池化),GAT使用学习的注意力权重。GAT的注意力权重具有可解释性(可以可视化重要邻居),但计算开销更大。GraphSAGE支持邻居采样(处理大图),GAT通常需要额外引入采样。实践中,GAT在小到中型图上效果更好,GraphSAGE在大图上更实用。
章节单词汇总
| 英文 | 音标 | 术语/释义 |
|---|---|---|
| Graph Attention Network (GAT) | /ɡræf əˈtenʃən ˈnetwɜːrk/ | 图注意力网络,通过注意力动态计算邻居权重 |
| Attention Coefficient | /əˈtenʃən ˌkoʊɪˈfɪʃənt/ | 注意力系数,α_{ij},邻居j对节点i的权重 |
| LeakyReLU | /ˈliːki rɛluː/ | 带泄漏的ReLU,负区间有小的斜率(0.2) |
| Multi-head Attention | /ˈmʌlti hed əˈtenʃən/ | 多头注意力,并行多个注意力头 |
| Inductive Learning | /ɪnˈdʌktɪv ˈlɜːrnɪŋ/ | 归纳学习,可泛化到未见过的节点/图 |
| Static Attention | /ˈstætɪk əˈtenʃən/ | 静态注意力,注意力排序不依赖目标节点 |
| Dynamic Attention | /daɪˈnæmɪk əˈtenʃən/ | 动态注意力,注意力真正依赖目标节点 |
| Concatenation | /kənˌkætɪˈneɪʃən/ | 拼接,将多头输出连接起来 |
面试练习
Q1 [单选] GAT中注意力分数e_{ij}是如何计算的?
- A. e_{ij} = h_i^T h_j
- B. e_{ij} = LeakyReLU(a^T [Wh_i || Wh_j])
- C. e_{ij} = softmax(h_i^T h_j)
- D. e_{ij} = 1/√(d_i·d_j)
解答:GAT的注意力分数为e_{ij} = LeakyReLU(a^T[Wh_i||Wh_j]),其中Wh_i和Wh_j拼接后与可学习的注意力向量a做点积。
Q2 [单选] GAT相比GCN的核心优势是什么?
- A. 计算速度更快
- B. 动态注意力权重和归纳学习能力
- C. 更少的参数量
- D. 不需要邻居信息
解答:GAT的核心优势是动态注意力权重(根据特征计算,而非固定度归一化)和归纳学习能力(可处理新节点/图)。GCN的权重是固定的,且是转导模型。
Q3 [单选] 原GAT论文中使用了多少个注意力头?
- A. 2
- B. 4
- C. 8
- D. 16
解答:原GAT论文使用K=8个注意力头。中间层拼接输出(8×d_out维),最后一层(预测层)使用平均。
Q4 [多选] 关于GAT,以下哪些说法是正确的?
- A. 注意力权重是动态计算的,依赖节点特征
- B. GAT可以处理有向图
- C. GAT支持归纳学习
- D. GAT的注意力计算不需要任何参数
- E. 多头注意力可以增强GAT的稳定性
解答:GAT的注意力权重动态计算,支持有向图,支持归纳学习,多头增强稳定性。注意力计算需要可学习的W和a参数。
Q5 [单选] GAT的LeakyReLU中,负斜率通常取多少?
- A. 0.0
- B. 0.2
- C. 0.5
- D. 1.0
解答:GAT使用LeakyReLU,负斜率通常取0.2。这确保了即使注意力分数为负,也有一个小梯度,防止梯度消失。
Q6 [单选] GAT的注意力计算复杂度与什么相关?
- A. 仅与节点数有关
- B. 与节点数和边数都有关
- C. 仅与边数有关
- D. 与图的大小无关
解答:GAT需要为每条边计算注意力分数,复杂度为O(|V|·F·F' + |E|·F')。对于稠密图(|E|≈|V|²),复杂度接近O(|V|²)。
Q7 [多选] 关于GAT的多头注意力,以下哪些是正确的?
- A. 中间层使用拼接(concat)合并多头输出
- B. 最后一层使用平均(average)合并多头输出
- C. 所有层都使用拼接
- D. 所有层都使用平均
- E. 每个头有独立的W和a参数
解答:GAT中间层用拼接(保留更多信息),最后一层用平均(输出维度与类别数匹配)。每个头有独立的参数。
Q8 [单选] GAT的静态注意力问题是指什么?
- A. 注意力权重永远不变
- B. 注意力分数的排序对所有目标节点是相同的
- C. 注意力计算速度太慢
- D. 注意力权重总是0
解答:静态注意力指注意力分数排序不依赖目标节点——如果j对i最重要,那么j对所有节点的注意力排名都是第一。GATv2通过修改计算顺序解决了这个问题。
Q9 [多选] 以下哪些场景适合使用GAT?
- A. 动态社交网络中的节点分类
- B. 需要归纳学习的分子性质预测
- C. 需要可解释邻居重要性的场景
- D. 超大规模图(数十亿节点)的实时推理
- E. 有向图上的节点分类
解答:GAT适合动态图、归纳学习、需要可解释性、有向图场景。超大规模图(数十亿节点)需要结合采样策略,原生GAT效率不够。
Q10 [单选] GAT的注意力权重α_{ij}的取值范围是什么?
- A. [-1, 1]
- B. [0, 1],且Σ_j α_{ij} = 1
- C. [0, ∞)
- D. 任意实数
解答:经过softmax归一化后,α_{ij}∈[0,1],且对每个节点i,所有邻居的注意力权重之和为1(概率分布)。