图注意力网络(GAT):参考答案

目录

\[ \begin{align}\begin{aligned}\newcommand{\ba}{\boldsymbol{a}} \newcommand{\bb}{\boldsymbol{b}} \newcommand{\be}{\boldsymbol{e}} \newcommand{\bq}{\boldsymbol{q}} \newcommand{\bk}{\boldsymbol{k}} \newcommand{\bw}{\boldsymbol{w}} \newcommand{\bx}{\boldsymbol{x}} \newcommand{\by}{\boldsymbol{y}} \newcommand{\bz}{\boldsymbol{z}} \newcommand{\bd}{\boldsymbol{d}} \newcommand{\bv}{\boldsymbol{v}} \newcommand{\bs}{\boldsymbol{s}}\\\newcommand{\btheta}{\boldsymbol{\theta}} \newcommand{\bbeta}{\boldsymbol{\beta}} \newcommand{\bgamma}{\boldsymbol{\gamma}} \newcommand{\bsigma}{\boldsymbol{\sigma}} \newcommand{\md}{\mbox{d}} \newcommand{\bmu}{\boldsymbol{\mu}} \newcommand{\bone}{\boldsymbol{1}} \newcommand{\bzero}{\boldsymbol{0}} \newcommand{\bepsilon}{\boldsymbol{\epsilon}} \newcommand{\bphi}{\boldsymbol{\phi}} \newcommand{\bh}{\boldsymbol{h}} \newcommand{\bc}{\boldsymbol{c}} \newcommand{\br}{\boldsymbol{r}} \newcommand{\bQ}{\boldsymbol{Q}} \newcommand{\bK}{\boldsymbol{K}} \newcommand{\bV}{\boldsymbol{V}} \newcommand{\bSigma}{\boldsymbol{\Sigma}} \newcommand{\bg}{\boldsymbol{g}} \newcommand{\bxi}{\boldsymbol{\xi}} \newcommand{\bvarepsilon}{\boldsymbol{\varepsilon}} \newcommand{\bdelta}{\boldsymbol{\delta}} \newcommand{\bq}{\boldsymbol{q}} \newcommand{\bk}{\boldsymbol{k}} \newcommand{\bJ}{\boldsymbol{J}} \newcommand{\bp}{\boldsymbol{p}} \newcommand{\bi}{\boldsymbol{i}} \newcommand{\bo}{\boldsymbol{o}} \newcommand{\bE}{\boldsymbol{E}} \newcommand{\bH}{\boldsymbol{H}} \newcommand{\bL}{\boldsymbol{L}} \newcommand{\bu}{\boldsymbol{u}} \newcommand{\bLambda}{\boldsymbol{\Lambda}} \newcommand{\trans}{^{\rm\scriptsize T}} \newcommand{\var}{\mathrm{var}}\\\newcommand{\bA}{\boldsymbol{A}} \newcommand{\bB}{\boldsymbol{B}} \newcommand{\bC}{\boldsymbol{C}} \newcommand{\bD}{\boldsymbol{D}} \newcommand{\bG}{\boldsymbol{G}} \newcommand{\bI}{\boldsymbol{I}} \newcommand{\bM}{\boldsymbol{M}} \newcommand{\bP}{\boldsymbol{P}} \newcommand{\bS}{\boldsymbol{S}} \newcommand{\bU}{\boldsymbol{U}} \newcommand{\bW}{\boldsymbol{W}} \newcommand{\bX}{\boldsymbol{X}} \newcommand{\bY}{\boldsymbol{Y}} \newcommand{\bZ}{\boldsymbol{Z}} \newcommand{\cotp}{\textcolor[RGB]{48,209,88}{TP}} \newcommand{\cotn}{\textcolor[RGB]{100,210,255}{TN}} \newcommand{\cofp}{\textcolor[RGB]{94,92,230}{FP}} \newcommand{\cofn}{\textcolor[RGB]{191,90,242}{FN}}\\\newcommand{\numcotp}{\textcolor[RGB]{48,209,88}{50}} \newcommand{\numcotn}{\textcolor[RGB]{100,210,255}{30}} \newcommand{\numcofp}{\textcolor[RGB]{94,92,230}{10}} \newcommand{\numcofn}{\textcolor[RGB]{191,90,242}{10}} \DeclareMathOperator*{\argmin}{arg\,min}\end{aligned}\end{align} \]

图注意力网络(GAT):参考答案#

返回正文练习 · 返回答案索引

说明#

以下答案与正文10道题逐题对应。前四题给出主要推导与计算;第 5--7 题给出可以运行的程序和检查方法;第 8--10 题说明比较时需要保持哪些条件相同,以及实验结果能够说明什么、不能说明什么。

  1. 分母为 \(\exp(0)+\exp(\log3)=1+3=4\)⁠,所以权重为 \(1/4\)\(3/4\)⁠。聚合结果为

    \[\frac14(2,0)+\frac34(0,4)=\left(\frac12,3\right).\]

    若全图 Softmax 还包含非邻居得分 \(e_{\mathrm{non}}\)⁠,两个邻居的分母会多出 \(\exp(e_{\mathrm{non}})\)⁠;事后清零不会重新放大剩余权重,其和小于 1。掩码必须在 Softmax 前进入归一化集合。

  2. 对固定接收节点 \(i\)⁠,有

    \[\alpha_{ij}= \frac{\exp(e_{ij})}{\sum_{k\in\mathcal N(i)\cup\{i\}}\exp(e_{ik})}.\]

    指数为正,所以权重非负,沿有效邻居求和等于 1。邻居置换只重排得分向量;Softmax 对应地重排权重,而 \(\sum_j\alpha_{ij}\bz_j\) 的配对项不变。同步置换全图节点时,每个旧邻域被映射到相应新邻域,共享投影和打分参数不变,因此节点输出按同一置换变化。若参数依赖节点编号或聚合包含存储顺序,结论不成立。

  3. 掩码后有效最大值为 1000,平移得分得到 \((0,-1,-\infty)\)⁠,因此

    \[\boldsymbol{\alpha} =\left(\frac{1}{1+e^{-1}}, \frac{e^{-1}}{1+e^{-1}},0\right) \approx(0.7311,0.2689,0).\]

    若所有有效得分加 \(c\)⁠,分子、分母同时乘 \(e^c\)⁠,比值不变。直接计算 \(e^{1000}\) 会溢出;先减最大值后最大的指数为 1,其余不超过 1。必须先掩码再寻找有效最大值,并保证每个分段至少有一条边。

  4. 每头 \(\bW_r\in\mathbb R^{16\times8}\)⁠、\(\ba_r\in\mathbb R^{16\times1}\)⁠,每头投影结果为 \(100\times8\)⁠,4 头拼接输出为 \(100\times32\)⁠。忽略偏置和额外输出投影,参数量为

    \[4(16)(8)+4(16)=512+64=576.\]

    加入 100 个自环后,每头处理 \(500+100=600\) 条边,4 头共计算 \(2400\) 个边得分。若输入的 500 条边已经含自环,程序应先确认并避免重复添加。

  5. 分段 Softmax 的 NumPy 参考实现可使用 maximum.atadd.at

    import numpy as np
    
    def segment_softmax(scores, receive, num_nodes):
        scores = np.asarray(scores, dtype=float)
        receive = np.asarray(receive, dtype=np.int64)
        if scores.ndim != 1 or receive.shape != scores.shape:
            raise ValueError("scores 与 receive 应为同形一维数组")
        if np.any((receive < 0) | (receive >= num_nodes)):
            raise IndexError("接收端点越界")
        count = np.zeros(num_nodes, dtype=np.int64)
        np.add.at(count, receive, 1)
        if np.any(count == 0):
            raise ValueError("每个节点至少需要一条入边或自环")
        maximum = np.full(num_nodes, -np.inf)
        np.maximum.at(maximum, receive, scores)
        numerator = np.exp(scores - maximum[receive])
        denominator = np.zeros(num_nodes, dtype=float)
        np.add.at(denominator, receive, numerator)
        return numerator / denominator[receive]
    

    重复边是不同的 Softmax 项,除非预处理明确合并。每个接收节点的返回权重应分别求和为 1。

  6. 单头实现先计算 z = x @ W再对每条边拼接 z[receive]z[send] 计算 Leaky ReLU 得分,调用 分段 Softmax⁠,最后按 receivealpha[:, None] * z[send]index_add多头可在头轴批量计算;隐藏层拼接头轴,输出层可平均头轴。逐节点循环版必须采用相同自环、边方向和 Leaky ReLU 斜率。

    使用 float64 小图逐项比较投影、得分、权重和输出,再比较输入、\(\bW\)\(\ba\) 的梯度。若对接框架库,还要对齐注意力 Dropout、偏置和多头输出约定。相同最终输出不能排除边权恰好抵消,因此应比较中间量。

  7. 置换测试同步改写边端点和节点行;邻居顺序测试只打乱同一接收节点的边次序;平移测试给一个分段得分加常数;分段和、非边和相同值测试按正文性质断言。全空邻域必须报错,极大得分仍应有限;无向边若只存一个方向,应有意得到不同邻域,用于暴露存储错误。还可构造两个接收节点,若错误地对所有边做一个全局 Softmax,分段和测试必然失败。

  8. 两个模型使用相同的数据划分、特征、随机种子、近似参数量和最大更新次数,并使用同一个验证集和相同标准选择模型;模型和训练方法确定后,测试集只使用一次。报告准确率或 macro-F1⁠、训练时间、固定图批量预测时间、峰值内存、参数量、实际边得分数和图层运行次数。

    GAT 根据数据学习邻居权重,可能提高预测质量,但也会增加每条边的打分计算和多头存储;GCN 可以作为使用固定邻居权重的对照模型。单个注意力权重较大并不能直接说明模型作出预测的原因,模型比较也不能只使用一个随机种子。

  9. 第一组比较保持总输出宽度不变,例如令每个注意力头的宽度为 \(d/K\)⁠;第二组比较保持每个头的宽度不变,此时总宽度、参数量和计算成本会随 \(K\) 增长。各组使用相同的数据划分、随机种子、层数、更新次数与评价程序;在同一个验证集上尝试相同的一组学习率,并按照相同标准选择。报告测试指标、训练时间、固定批量预测时间、峰值内存、参数量、边得分数和图层运行次数。

    在总宽度固定时,头数改变子空间分解而非简单增加容量;在每头宽度固定时,性能变化混合了头数和容量。两组结果不能合并成“头越多越好”的结论。

  10. 均匀权重版本令每个接收节点的有效边权为其入度倒数,并保留与 GAT 相同的投影、层数和宽度。三种模型共享划分、种子集合、更新次数、优化器与评价程序;报告测试指标、训练和固定批量预测时间、峰值内存、边得分数及层调用次数。稠密实现只在小图上核验数值,正式规模使用稀疏实现。

    若学习权重优于均匀权重,说明该设置下数据依赖混合有帮助;若差异很小,不能据此断言注意力“没有作用”,还需考虑优化、头宽和数据同质性。稠密与稀疏实现结果应一致,但效率结论必须按实际实现分别报告。