假设你是一家大公司的 CEO,要给整个公司做一次「组织结构画像」。员工是个人贡献者,员工之间的协作关系是边。传统做法是直接给所有员工发一份问卷,把所有评分加总成一张表——看似简单,却把「谁在哪个部门、部门之间怎么协作」的结构信息全丢了。DiffPool 的做法完全不同:它像一位擅长组织重组的咨询顾问,先让每个员工按照履历与协作关系,软性地选择加入哪个新部门;部门再合并成事业群,事业群再合并成集团。每一层合并都由数据自动学习,而不是人工拍脑袋。这篇文章我们就用「公司重组」这个故事,把 DiffPool 如何做层次化图池化讲清楚。

岗位关联

如果你在工业界做图分类、分子性质预测或社区分析,DiffPool 是让模型「看见图的层次」的关键工具;掌握它,你就能为图级任务设计可学习、可落地的池化方案。

目录
  1. 可视化演示
  2. 图分类难题
  3. 软分配思想
  4. 分配矩阵学习
  5. 层次凝聚操作
  6. 池化比率控制
  7. 联合损失优化
  8. 复杂度与扩展
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示ID3算法构建决策树的过程,以信息增益为分裂准则,逐层选择最优特征进行分裂,直到所有样本分类一致或特征耗尽。

本节配有交互动效(进入视口后自动加载,约 3KB)。

ID3决策树 - 信息增益分裂 计算每个特征的信息增益,选择增益最大的特征分裂 递归分裂子集,直到纯度为1或无特征可用 Gain(S,A) = Ent(S) - Σ|Sv|/|S|·Ent(Sv) ID3偏好取值多的特征,C4.5改用增益率修正此偏差。

图分类难题

想象你是一家投资机构的分析师,要快速判断一家公司值不值得投。只看员工总数和平均工资,你很难区分技术驱动的公司与销售驱动的公司;你还必须了解研发、产品、市场之间如何协作,也就是公司的组织结构。图分类任务也面临同样的问题:一个分子、一个社交网络、一张程序依赖图,最终都只需要一个类别标签,但标签往往由局部结构和层次组合决定。

在 GNN 中,节点经过若干层消息传递后得到嵌入向量,但最终还需要一个图级向量来完成分类。最简单的平坦池化会把所有节点向量取平均,相当于把所有员工扔进一个麻袋,组织关系完全打乱。DiffPool 则提出层次池化:逐层把节点聚合成超级节点,再对超级节点做最终读取,像先把员工归到部门、再把部门归到事业群。

所以 DiffPool 的定位,相当于 CNN 里从像素到目标再到场景的逐步抽象;在 GNN 里,它把“节点—子图—整图”的层次结构端到端学出来。只看最终平均值,永远无法还原一个组织的真正骨架。

hG=Readout(H(L))=1N∑i=1Nhi(L)h_G = \mathrm{Readout}(H^{(L)}) = \frac{1}{N}\sum_{i=1}^{N} h_i^{(L)}
通俗说:这个公式就是“把最后所有员工的表现平均一下,当作整个公司的画像”。
  1. 节点表示矩阵 $H^{(L)}$第 $L$ 层 GNN 输出 $N$ 个节点向量,每个向量 $d$ 维,构成 $N \times d$ 矩阵。
    H(L)∈RN×dH^{(L)} \in \mathbb{R}^{N \times d}
  2. 图读取函数 Readout把节点向量聚合成一个图级向量 $h_G$,传统做法是对节点向量做平均。
    hG=Readout({hi(L)})h_G = \mathrm{Readout}\left(\{h_i^{(L)}\}\right)
  3. 全局平均项将每个节点向量逐维相加,再除以节点数 $N$;公式里的 $\frac{1}{N}\sum_{i=1}^{N}$ 就是平均运算。
    1N∑i=1Nhi(L)\frac{1}{N}\sum_{i=1}^{N} h_i^{(L)}

软分配思想

接管组织设计后,咨询顾问并不直接宣布谁去哪个部门,而是先做一张“归属倾向表”。张三可能 80% 去算法部、20% 去中台;李四可能 70% 去产品部、30% 去运营。每个人都不必孤单地属于某一个部门,而是携带一个概率分布。

DiffPool 的分配矩阵 $S$ 就是这张表。第 $i$ 行对应原图第 $i$ 个节点,第 $j$ 列对应下一层的第 $j$ 个超级节点;$S_{ij}$ 表示节点 $i$ 对超级节点 $j$ 的隶属度。因为下一层超级节点是若干个旧节点的加权组合,而不是简单挑选一个人,模型可以表达更丰富的层次关系。多层堆叠后,底层超级节点继续聚合,最终得到整图的层次表示。

这张“归属倾向表”不是 HR 拍脑袋,而是后面要说的两个 GNN 自动学出来的——这正是 DiffPool 区别于手工图粗化的核心。

Sij(l)=exp⁡(S~ij(l))∑k=1nl+1exp⁡(S~ik(l))S^{(l)}_{ij} = \frac{\exp(\tilde S^{(l)}_{ij})}{\sum_{k=1}^{n_{l+1}} \exp(\tilde S^{(l)}_{ik})}
简单说:每个员工对每个新部门的倾向分数做归一化,让所有倾向加起来等于 1;一个部门就是一个“超级员工”。
  1. 未归一化分数 $\tilde S^{(l)}$第 $l$ 层的池化 GNN 为每个节点输出 $n_{l+1}$ 个分数,代表它属于不同超级节点的倾向。
    S~(l)∈Rnl×nl+1\tilde S^{(l)} \in \mathbb{R}^{n_l \times n_{l+1}}
  2. 指数运算 $\exp$把分数变成非负数,同时放大分数差距,让高倾向更突出。
    exp⁡(S~ij(l))\exp(\tilde S^{(l)}_{ij})
  3. 分母归一化对第 $i$ 行所有 $k$ 的指数值求和,再用它除每个分子,使每一行和为 1。
    ∑k=1nl+1exp⁡(S~ik(l))\sum_{k=1}^{n_{l+1}} \exp(\tilde S^{(l)}_{ik})

分配矩阵学习

为了让归属表更合理,顾问用了两份测评:一份测员工能力雷达图,另一份测员工对各个新部门的倾向。两份测评都基于同一个员工档案,但考核维度完全独立。DiffPool 同样使用两个 GNN:$\mathrm{GNN}_{\mathrm{embed}}$ 读取节点特征与邻接矩阵,生成用于表达的节点嵌入 $Z$;$\mathrm{GNN}_{\mathrm{pool}}$ 读取同样的输入,生成未归一化的分配分数 $\tilde S$。

然后对 $\tilde S$ 的每一行做 Softmax,得到行和为 1 的 $S$。注意两个 GNN 参数不共享,避免“既当运动员又当裁判”,让表达与分组各司其职。在训练初期,$S$ 几乎均匀;随着损失函数不断反馈,归属倾向会越来越有结构,这就是“可学习”二字的含义。

如果把嵌入 GNN 比作“能力雷达图”,池化 GNN 就是“部门归属问卷”;两份结果合在一起,才构成一份完整的员工档案。

Z(l)=GNNembed(l)(A(l),X(l)),S~(l)=GNNpool(l)(A(l),X(l))Z^{(l)} = \mathrm{GNN}_{\mathrm{embed}}^{(l)}\left(A^{(l)}, X^{(l)}\right), \qquad \tilde S^{(l)} = \mathrm{GNN}_{\mathrm{pool}}^{(l)}\left(A^{(l)}, X^{(l)}\right)
一个 GNN 负责把员工履历变成能力向量,另一个 GNN 负责把同一份履历变成归属倾向分数,两者分工不同。
  1. 嵌入 GNN 的计算输入第 $l$ 层邻接矩阵 $A^{(l)}$ 与节点特征 $X^{(l)}$,输出每个节点的嵌入 $Z^{(l)}$,用于描述节点“是什么”。
    Z(l)=GNNembed(l)(A(l),X(l))Z^{(l)} = \mathrm{GNN}_{\mathrm{embed}}^{(l)}\left(A^{(l)}, X^{(l)}\right)
  2. 池化 GNN 的计算输入同样的一份图数据,输出未归一化分配分数 $\tilde S^{(l)}$,用于决定节点“要去哪”。
    S~(l)=GNNpool(l)(A(l),X(l))\tilde S^{(l)} = \mathrm{GNN}_{\mathrm{pool}}^{(l)}\left(A^{(l)}, X^{(l)}\right)
  3. 共享输入但不共享参数两个 GNN 读取相同图,却拥有不同的权重矩阵,所以表达和分组可以各自优化。
    GNNembed≠GNNpool\mathrm{GNN}_{\mathrm{embed}} \neq \mathrm{GNN}_{\mathrm{pool}}

层次凝聚操作

归属表敲定后,新部门该拥有什么能力、部门之间怎么协作,需要从旧组织中汇总。顾问把每个员工的技能按倾向比例带入新部门,再把旧协作关系按“两个员工是否进入同一个新部门”叠加起来。DiffPool 的池化操作正是两次矩阵运算:特征凝聚和邻接凝聚。

得到的新邻接矩阵每个元素不再只是 0 或 1,而是超级节点之间的协作强度。这样的池化可以堆叠多层,形成从细粒度到粗粒度的层次结构,就像十几个小队合并成三个大组后,新大组之间的协作关系由原来队与队的合作历史加权得到。

X(l+1)=S(l)⊤Z(l),A(l+1)=S(l)⊤A(l)S(l)X^{(l+1)} = S^{(l)\top} Z^{(l)}, \qquad A^{(l+1)} = S^{(l)\top} A^{(l)} S^{(l)}
这相当于用旧部门的协作关系和员工能力,加权汇总出每个新部门的能力画像与新部门之间的协作强度。
  1. 特征凝聚 $X^{(l+1)} = S^{(l)\top} Z^{(l)}$$S^{(l)\top}$ 的形状是 $n_{l+1} \times n_l$,把 $n_l$ 个旧节点嵌入按概率加权求和,得到 $n_{l+1}$ 个超级节点的特征矩阵。
    X(l+1)∈Rnl+1×dX^{(l+1)} \in \mathbb{R}^{n_{l+1} \times d}
  2. 邻接凝聚的内层乘法 $A^{(l)} S^{(l)}$先让每条边的“起点”映射到超级节点,得到中间结果。
    A(l)S(l)∈Rnl×nl+1A^{(l)} S^{(l)} \in \mathbb{R}^{n_l \times n_{l+1}}
  3. 邻接凝聚的外层乘法 $S^{(l)\top}\left(A^{(l)} S^{(l)}\right)$再把“终点”也映射到超级节点,最终得到 $n_{l+1} \times n_{l+1}$ 的新邻接矩阵,元素代表超级节点之间的连接强度。
    A(l+1)∈Rnl+1×nl+1A^{(l+1)} \in \mathbb{R}^{n_{l+1} \times n_{l+1}}

池化比率控制

新组织该保留多少个部门?如果保留 50 个,细节充分但冗余;如果只保留 2 个,信息高度抽象但可能模糊掉关键差异。DiffPool 中下一层超级节点数 $n_{l+1}$ 是人为设定的超参数,等价于控制压缩比 $r$。在实现中,通常直接指定 $n_{l+1}$;也可以用压缩比描述层次变得多快。

由于分配矩阵是稠密的,$n_{l+1}$ 过大会带来内存和计算压力,需要权衡。和 Top-k 池化不同,DiffPool 不是“裁掉低分员工”,而是让所有人以不同权重进入新部门,因此压缩比的控制更平滑。

r=nl+1nl,0<r≤1r = \frac{n_{l+1}}{n_l}, \quad 0 < r \le 1
通俗说:压缩比 $r$ 是下一层超级节点数占当前节点数的比例,$r$ 越小,图被压缩得越狠。
  1. 当前层节点数 $n_l$池化前图里有 $n_l$ 个节点,也就是 $n_l$ 个“旧部门”。
    nl=∣V(l)∣n_l = |\mathcal{V}^{(l)}|
  2. 下一层节点数 $n_{l+1}$池化后保留或合并成 $n_{l+1}$ 个超级节点,也就是“新部门数”。
    nl+1≤nln_{l+1} \le n_l
  3. 比率 $r$ 的含义$r$ 越接近 1,层次越平缓,计算量越大;$r$ 越小,每个超级节点覆盖越多原始节点,最终图向量越全局。
    r=nl+1nlr = \frac{n_{l+1}}{n_l}

联合损失优化

一份重组方案好不好,不能只看新公司年底业绩。顾问还会检查:原来的跨部门协作有没有被保留?每个员工是不是被明确地归到某个部门,而不是平均分到所有部门?DiffPool 的训练也包含三类损失:任务损失、链接预测损失、熵正则化。

任务损失负责分类正确;链接预测损失用 $\|A - SS^\top\|_F^2$ 迫使分配矩阵尽量保留原图邻接结构;熵正则化则惩罚 $S$ 行分布过于平均。总损失是这三项的加权和,链接预测与熵正则都只作用于分配矩阵,帮助 GNN_pool 学到更合理的分组。

如果说任务损失是“业绩”,链接预测是“协作保留”,熵正则就是“岗位归属清晰度”;三者缺一,重组方案都可能失衡。

L=Ltask+λ1∥A(l)−S(l)S(l)⊤∥F2+λ21n∑i=1nH(Si(l))\mathcal{L} = \mathcal{L}_{\mathrm{task}} + \lambda_1 \left\|A^{(l)} - S^{(l)}S^{(l)\top}\right\|_F^2 + \lambda_2 \frac{1}{n}\sum_{i=1}^{n}H(S^{(l)}_i)
最终损失是三类约束的加权和:业务目标、协作保留、归属明确。
  1. 任务损失 $\mathcal{L}_{\mathrm{task}}$下游分类器计算预测标签与真实标签之间的误差,例如交叉熵。
    Ltask=CrossEntropy(y^,y)\mathcal{L}_{\mathrm{task}} = \mathrm{CrossEntropy}\left(\hat y, y\right)
  2. 链接预测损失比较原始邻接矩阵 $A^{(l)}$ 与 $S^{(l)}S^{(l)\top}$,让相似节点的分配向量尽可能一致。
    ∥A(l)−S(l)S(l)⊤∥F2\left\|A^{(l)} - S^{(l)}S^{(l)\top}\right\|_F^2
  3. 熵正则化$H(S^{(l)}_i)$ 是第 $i$ 行分配向量的信息熵,熵越小说明这一行越接近 one-hot 分布,归属越明确。
    H(Si)=−∑j=1nl+1Sijlog⁡SijH(S_i) = -\sum_{j=1}^{n_{l+1}} S_{ij}\log S_{ij}

复杂度与扩展

组织重组如果要求每个部门与其他所有部门都做一次详细对接,代价会随部门数量平方级增长。DiffPool 的稠密实现正是如此。计算 GNN 嵌入时,$AX$ 涉及 $O(n^2 d)$;计算 $S^\top A S$ 时,密集矩阵乘法约 $O(n^2 k)$。当图规模达到几万节点时,内存和耗时都很可观。

工业落地时可以选择稀疏邻接矩阵、图采样、分块处理,或者改用结构更轻的池化层,例如 SAGPool 的 Top-k 选择。但 DiffPool 提供的层次框架依然是理解此类方法的重要基线,也提醒我们:层次池化不是免费午餐,能力越强,计算账单也越高。

T=O(n2d+n2k),k=nl+1T = O\left(n^2 d + n^2 k\right), \quad k = n_{l+1}
通俗说:如果公司有 $n$ 个部门,Dense DiffPool 要算大约 $n^2$ 次两两关系,规模一大就非常吃力。
  1. 邻接矩阵乘法 $O(n^2 d)$GNN 层计算 $A X$ 时,每个节点都要聚合所有邻居,稠密矩阵乘法带来 $n^2$ 次操作。
    AX:O(n2d)AX: O(n^2 d)
  2. 池化邻接 $O(n^2 k)$计算 $S^\top A S$ 时,先算 $A S$ 再算 $S^\top(AS)$,主导项与 $n^2 k$ 成正比。
    S⊤AS:O(n2k)S^{\top}AS: O(n^2 k)
  3. 扩展策略当 $k$ 远小于 $n$ 并且邻接矩阵稀疏时,可以用稀疏矩阵乘法把 $n^2$ 项降为与边数 $m$ 相关,配合图采样进一步扩展。
    O(md+mk+nk2)O(m d + m k + n k^2)

AI 应用场景

蛋白质功能预测

阶段:图表示学习 / 图分类

解决的问题:蛋白质结构图有大量残基节点,功能往往由多个亚结构组合决定。传统全局平均池化容易丢失结合位点的层次信息,DiffPool 将残基逐层聚合为功能域超级节点,让下游分类器利用层次结构判断功能类别。

具体案例:在酶功能分类任务中,用 AlphaFold 预测结构构建残基接触图,再用 DiffPool 提取二级结构聚合表示,预测酶的 EC 编号。

脑网络疾病辅助诊断

阶段:医学图分类

解决的问题:脑区连接矩阵是高维图,疾病影响通常不是单一脑区,而是多个脑功能网络模块。DiffPool 能学习把脑区软分配成若干功能网络,再对层次表示分类,帮助医生定位异常模式。

具体案例:基于 fMRI 构建 90 个脑区的连接图,使用 DiffPool 将脑区聚合为默认网络、突显网络等超级节点,辅助识别精神分裂症患者与健康对照。

电商用户行为图分类

阶段:用户行为建模 / 推荐系统

解决的问题:用户浏览、加购、购买等行为可以建模为行为图,DiffPool 能逐层聚合行为节点,刻画从商品到品类再到购买决策的层次,传统手工特征难以捕捉这种跨层级模式。

具体案例:电商平台为每个用户构建 30 天内的行为图,用 DiffPool 预测高价值用户,为精准营销提供依据。

Python 演示

python56 行
import torchimport torch.nn as nnimport torch.nn.functional as F  class GNNLayer(nn.Module):    def __init__(self, in_dim, out_dim):        super(GNNLayer, self).__init__()        self.linear = nn.Linear(in_dim, out_dim)     def forward(self, A, X):        return F.relu(self.linear(A.matmul(X)))  class DiffPoolBlock(nn.Module):    def __init__(self, in_dim, hidden_dim, pool_nodes):        super(DiffPoolBlock, self).__init__()        self.embed = GNNLayer(in_dim, hidden_dim)        self.assign = GNNLayer(in_dim, pool_nodes)        self.pool_nodes = pool_nodes     def forward(self, A, X):        Z = self.embed(A, X)        S = F.softmax(self.assign(A, X), dim=1)        X_next = torch.matmul(S.t(), Z)        A_next = torch.matmul(torch.matmul(S.t(), A), S)        return A_next, X_next, S  def main():    torch.manual_seed(42)    A = torch.tensor([[1, 1, 0, 0],                      [1, 1, 1, 0],                      [0, 1, 1, 1],                      [0, 0, 1, 1]], dtype=torch.float32)    X = torch.randn(4, 8)    model = DiffPoolBlock(8, 16, 2)    opt = torch.optim.Adam(model.parameters(), lr=0.01)     for epoch in range(100):        opt.zero_grad()        A2, X2, S = model(A, X)        lp_loss = F.mse_loss(S.matmul(S.t()), A)        ent_loss = -(S * torch.log(S + 1e-10)).sum(dim=1).mean()        loss = lp_loss + 0.5 * ent_loss        loss.backward()        opt.step()        if epoch % 20 == 0:            print("epoch", epoch, "loss", round(loss.item(), 3),                  "entropy", round(ent_loss.item(), 3))     print("learned assignment S:\n", S.detach().numpy())  if __name__ == "__main__":    main()
目的:实现一个简化版的 DiffPool 块,在 4 节点小图上展示可学习分配矩阵、特征凝聚、邻接凝聚以及两个辅助损失。
  1. S = F.softmax(self.assign(A, X), dim=1)对池化 GNN 的输出按行做 Softmax,得到行和为 1 的软分配矩阵。
  2. X_next = torch.matmul(S.t(), Z)用分配矩阵的转置加权聚合嵌入矩阵,生成超级节点特征。
  3. A_next = torch.matmul(torch.matmul(S.t(), A), S)对邻接矩阵做两次投影,得到超级节点之间的新邻接关系。
  4. lp_loss = F.mse_loss(S.matmul(S.t()), A)链接预测损失,强制分配矩阵保留原图连通结构。
  5. ent_loss = -(S * torch.log(S + 1e-10)).sum(dim=1).mean()计算每行分配向量的平均熵,引导归属更明确。

常见误区

误区我以为 DiffPool 会先对节点做 K-Means 聚类,再把聚类结果当成分配矩阵 S,最后接一个分类器。

正解不是。S 来自 GNN_pool 的输出,是端到端训练的一部分。训练前 S 几乎是均匀的;训练时任务损失和辅助损失会同时调整 GNN 参数,让 S 逐渐学会合理分组。就像 HR 一开始只能乱分,经过业务反馈后归属表才越来越合理。

为何常见:因为 S 看起来像聚类隶属矩阵,而且很多教材用“软聚类”引入,容易被误以为是无监督聚类。

误区都是池化,DiffPool 应该就是把每层得分最高的前 k 个节点留下来。

正解DiffPool 是软分配,所有节点都参与;Top-k 是硬选择,直接丢弃低分节点。DiffPool 的 S 是 $n \times k$ 的概率矩阵,新节点是旧节点的加权组合;Top-k 保留的依旧是原图子集。两者思想不同,DiffPool 能表达更丰富的合并,但计算也更贵。

为何常见:很多工程库把不同池化层都封装成 pool_nodes(n),接口相似导致概念混淆。

误区图越大,就应该堆更多 DiffPool 层,反正能学到层次结构。

正解每层都做软分配和邻接凝聚,信息会不断被压缩;过深会让 S 的学习变得困难、梯度消失、超级节点失去可解释性。实际使用一般 2-3 层,就像公司层级太多会导致信息层层失真。

为何常见:GNN 层数越多感受野越大,类比到池化层上就误以为越深越好。

误区因为 DiffPool 用 GNN,把邻接矩阵换成稀疏存储就能上亿级大图。

正解分配矩阵 S 是稠密的,$S^\top A S$ 涉及大量稠密矩阵乘法,复杂度约 $O(n^2 d + n^2 k)$。原始 DiffPool 更适合中等规模图;大规模场景需要图采样、与 GraphSAGE 结合或改用稀疏化方法。

为何常见:GNN 常用稀疏邻接矩阵,让新手误以为所有图操作都是稀疏线性的,没注意到分配矩阵本身就是稠密的。

面试题

Q1. DiffPool 中分配矩阵 S 的每一行进行什么归一化?

单选题 · easy

  • A.列归一化,使每列和为 1
  • B.行 Softmax,使每行和为 1← 正确答案
  • C.全局归一化,使所有元素和为 1
  • D.随机归一化,使每行和为 1

答案:B。DiffPool 的分配矩阵每一行代表一个原始节点到各个超级节点的归属概率,所以需要行 Softmax 使每行和为 1。A 说的是列归一化,C 是全局归一化,D 是随机化,都不是正确操作。

Q2. DiffPool 池化后新特征矩阵 X_new 的计算方式?

单选题 · easy

  • A.X_new = S^T Z← 正确答案
  • B.X_new = A S^T
  • C.X_new = S Z^T
  • D.X_new = S^T A

答案:A。特征凝聚是把嵌入矩阵 Z 按照分配矩阵 S 加权聚合到超级节点,因此是 $X_{new} = S^\top Z$。B、D 都没用嵌入 Z,C 矩阵形状不对。

Q3. DiffPool 中 GNN_embed 和 GNN_pool 的关系?

单选题 · easy

  • A.参数完全相同且共享
  • B.输入相同但参数不同← 正确答案
  • C.输出相同但输入不同
  • D.池化 GNN 不需要训练

答案:B。两个 GNN 都读取当前层的邻接矩阵和节点特征,但一个负责生成嵌入 Z,一个负责生成分配分数 S,参数不共享。A 会破坏分工,C 输入并非不同,D 不符合端到端训练。

Q4. 下列关于 DiffPool 池化比的描述正确的是?

单选题 · mid

  • A.节点数由模型自动学习,无需设定
  • B.后一层节点数需要预设,以控制压缩比← 正确答案
  • C.池化比固定为 0.5 不可调整
  • D.池化比越大表示保留节点越少

答案:B。DiffPool 的下一层超级节点数是超参数,等价于人为控制压缩比。A 不符合原始设计,C 过于绝对,D 说反了:池化比越大,保留的节点比例越高。

Q5. DiffPool 的链接预测损失主要作用?

单选题 · mid

  • A.让分配矩阵保留原图邻接信息← 正确答案
  • B.让节点特征维度变得更小
  • C.让分类器输出更平滑
  • D.让池化层参数全部变为 0

答案:A。链接预测损失比较 $SS^\top$ 与原始邻接矩阵,促使有边相连的节点得到相似的分配向量,从而保留连接结构。B、C、D 都不是链接预测损失的目标。

Q6. 熵正则化项在 DiffPool 中鼓励什么?

单选题 · mid

  • A.分配矩阵每行更接近均匀分布
  • B.分配矩阵所有元素全部为零
  • C.每个节点更明确地归属某个超级节点← 正确答案
  • D.邻接矩阵变成完全稀疏矩阵

答案:C。信息熵越小,分配向量越接近 one-hot,也就是每个节点更明确地归入某个超级节点。A 是鼓励均匀分布,与熵正则相反;B 和 D 与熵正则没有直接关系。

Q7. 一个 4 节点图,设定下一层 2 个超级节点,S 为 4×2 行 softmax 矩阵,A 为 4×4 邻接矩阵,则 A_new 的维度是?

单选题 · hard

  • A.4×2
  • B.2×2← 正确答案
  • C.4×4
  • D.2×4

答案:B。$A_{new} = S^\top A S$,其中 $S^\top$ 是 2×4,$A$ 是 4×4,$S$ 是 4×2,最终结果是 2×2。其他选项的维度都不符合矩阵乘法规则。

Q8. DiffPool 的主要计算瓶颈来自?

单选题 · hard

  • A.逐元素激活函数计算
  • B.邻接矩阵平方级运算← 正确答案
  • C.分类损失反向传播
  • D.训练数据的加载过程

答案:B。DiffPool 的稠密实现中,$AX$ 和 $S^\top A S$ 都涉及 $O(n^2)$ 量级的矩阵乘法,这是主要瓶颈。激活函数、损失反向传播和数据加载虽然也有开销,但不是平方级主导。

Q9. DiffPool 训练时的联合损失通常包含哪些部分?

多选题 · mid

  • A.图分类任务损失← 正确答案
  • B.链接预测辅助损失← 正确答案
  • C.分配矩阵熵正则化← 正确答案
  • D.节点特征方差惩罚

答案:ABC。DiffPool 的损失由任务损失、链接预测损失和熵正则化组成。链接预测保留原图结构,熵正则化让归属更明确。D 的节点特征方差惩罚在标准 DiffPool 中并不存在。

Q10. 与 Top-k 池化相比,DiffPool 的特点有哪些?

多选题 · extreme

  • A.使用软分配,每个节点可归入多个组← 正确答案
  • B.通过 GNN 学习分配矩阵,可端到端训练← 正确答案
  • C.所有节点都参与池化,没有直接丢弃← 正确答案
  • D.计算复杂度通常低于 Top-k 池化

答案:ABC。DiffPool 用软分配矩阵,所有节点都参与合并,并且分配矩阵由 GNN 端到端学习;Top-k 则直接选择子集。D 说反了,DiffPool 的稠密矩阵运算通常比 Top-k 池化更贵,因此不能选。