新学期结束,教务处让每个班主任交一张“班级总评表”。班里几十个学生,每个人有语文、数学、英语三科成绩;教务处不要花名册,只要一行字:这个班整体怎么样?你要做的,就是把单个学生的信息浓缩成一句评语。图神经网络里的读出函数,干的正是这件事。先让节点特征经过消息传递层层更新,最后再用读出函数把所有节点向量合并成一个图级向量,为图分类、分子性质预测等任务提供判断依据。不同的总结方式——总分、平均分、最高分、按名次选尖子——就对应求和、平均、最大、排序等读出策略。

岗位关联

掌握读出函数,等于学会给 GNN 的“班级画像”收尾;图分类、分子属性预测这类图级任务的最后一公里,都靠它把节点特征变成模型能用的图特征。

目录
  1. 可视化演示
  2. 图级任务需求
  3. 读出原理
  4. 求和池化
  5. 平均池化
  6. 最大池化
  7. 排序池化
  8. 注意力读出
  9. 实践选择
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

\u5c55\u793a\u6c42\u548c\u3001\u5e73\u5747\u3001\u6700\u5927\u6c60\u5316\u4e09\u79cd\u8bfb\u51fa\u7b56\u7565\u5bf9\u6bd4\uff0c\u4ee5\u53ca\u6392\u5e8f\u6c60\u5316\u7684\u7ed3\u6784\u4fdd\u6301\u7279\u6027\u4e0eTop-K\u9009\u62e9\u8fc7\u7a0b\u3002

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

\u8bfb\u51fa\u5bf9\u6bd4\u6a21\u5f0f SUM=\u6240\u6709\u8282\u70b9\u503c\u4e4b\u548c(3.20)\uff0c\u4fdd\u7559\u603b\u91cf\u4fe1\u606f AVG=\u5747\u503c(0.53)\uff0c\u5bf9\u56fe\u5927\u5c0f\u4e0d\u654f\u611f SUM=\u03a3h_i, AVG=\u03a3h_i/N, MAX=max(h_i)

图级任务需求

教务处让班主任交一张“班级总评表”,可班里几十个学生,总不能把花名册直接交上去。班主任必须把每个人的信息浓缩成一行评语:“这个班整体学风扎实、特长突出。”在图神经网络里,这一行评语就是图级向量,而负责浓缩的班干部就是读出函数。

在图神经网络中,每个节点经过若干轮消息传递后,会得到一个向量表示 \(h_v\)。如果任务是判断某个节点属于哪一类,直接拿节点向量去分类就行;但如果任务是判断整张图的类别,比如“这张分子图是否有毒性”“这个社交网络是否是垃圾群组”,就必须把图上所有节点的特征合并成整个图的特征。这个合并动作,正是图级读出。

读出函数通常放在所有 GNN 层之后,是图分类任务的最后一步。它的输入是一组节点向量,输出是一个定长的图向量 \(h_G\)。有了 \(h_G\),再接一个分类器,就能完成图级别的分类或回归。

这就像你最后写在表上的那句总评:学生还是那些学生,但评价对象已经从“每个人”变成了“整个班”。

hG=READOUT({hv(L)∣v∈V})h_G = \mathrm{READOUT}\left( \left\{ h_v^{(L)} \mid v \in V \right\} \right)
这个公式的意思是:把图中所有节点在最后一层的特征拿出来,用某种汇总方式合并成图向量。
  1. 取出全部节点把最后一层所有节点特征放进同一个集合,这里的 \(L\) 表示最后一层。
    {hv(L)∣v∈V}\left\{ h_v^{(L)} \mid v \in V \right\}
  2. 施加读出函数用求和、平均、取最大等汇总运算遍历整个节点集合。
    READOUT(⋅)\mathrm{READOUT}(\cdot)
  3. 得到图向量聚合结果就是整张图的表示,记作 \(h_G\)。
    hGh_G

读出原理

无论学生按学号排还是按身高排,班级总评都不该变。图本身没有天然顺序,节点只是一个个元素的集合;如果打个乱节点顺序,图向量就变了,模型就会像“换个座位就看不出是同一个班”的老师一样不可靠。

这正是读出函数必须满足的核心性质:置换不变性。所谓置换不变性,是指把图的节点顺序任意打乱,最终输出的图向量保持不变。求和、平均、最大这类基础池化天然满足这个性质;排序池化本身也是先对节点排序再选取,因此排序结果同样不依赖节点输入的先后顺序。

班级画像不会因为学生换了座位就变成另一个班,这正是读出函数最可贵的品格。

hG=READOUT({hπ(v)∣v∈V})=READOUT({hv∣v∈V})h_G = \mathrm{READOUT}\left(\left\{ h_{\pi(v)} \mid v \in V \right\}\right) = \mathrm{READOUT}\left(\left\{ h_v \mid v \in V \right\}\right)
对任意节点顺序变换 \(\pi\),读出后的图向量都相同,这就是读出函数能稳定工作的底层保证。
  1. 定义节点集合原始图中所有节点构成集合 \(V\),\(\pi\) 表示任意一种排列方式。
    V,π(v)V, \quad \pi(v)
  2. 交换节点顺序把每个节点换到新的位置上,但集合内容没有变。
    {hπ(v)∣v∈V}\left\{ h_{\pi(v)} \mid v \in V \right\}
  3. 读出结果不变读出函数对集合做汇总,因此集合内容不变,结果也就不变。
    READOUT({hπ(v)})=READOUT({hv})\mathrm{READOUT}\left(\left\{ h_{\pi(v)} \right\}\right) = \mathrm{READOUT}\left(\left\{ h_v \right\}\right)

求和池化

班主任最直观的总结方式,是算全班总分。把每个学生的各科成绩都加一遍,得到一个“总分向量”。总分高,说明这个班整体“体量”大;但也正因如此,班里人数越多,总分通常越高。

求和池化就是对所有节点特征逐维相加:

它的优点是实现简单、保留总量的信息;缺点是对图规模敏感。两张结构相似的图,仅因为一张图的节点数更多,求和后的向量就可能整体偏大。好在分子性质预测这类任务里,分子的大小往往本身就有意义,因此求和池化仍是常用的强基线。

总分最高的班,不一定每门课都最强,但它一定拥有更大的“总量”——求和池化捕捉的正是这种规模感。

hG=∑v∈Vhvh_G = \sum_{v \in V} h_v
求和池化把所有节点的每一维特征累加,得到和节点特征维度相同的图向量。
  1. 逐维累加对特征向量的每一维分别累加,符号 \(\sum\) 表示累加。
    ∑v∈V\sum_{v \in V}
  2. 所有节点都参与每个节点特征 \(h_v\) 都被加入最终结果,一个都不能少。
    hvh_v
  3. 得到同维图向量输出向量的维度和单个节点特征维度一致,但含义已从“单个节点”变成“整张图”。
    hG=∑v∈Vhvh_G = \sum_{v \in V} h_v

平均池化

如果教务处要看“这个班整体水平怎么样”,总分就会被人多的班占便宜。聪明的班主任会改报平均分:把总分除以人数,得到一个不受班级人数影响的指标。

平均池化就是把求和结果除以节点数量:

平均池化的优势是减少了图规模带来的偏差。当图的大小差异很大,而我们希望模型更关注“整体水平”而非“总量”时,平均池化更稳定。代价是它丢失了节点总数这一信息:两个平均分相同的班,一个 20 人、一个 40 人,在图向量里看不出区别。

平均分能公平比较人数不同的班级,但也掩盖了“班级大小”这个本来可能有用的信息。

hG=1∣V∣∑v∈Vhvh_G = \frac{1}{|V|} \sum_{v \in V} h_v
平均池化相当于先求总和,再除以图中节点总数,使图向量不再随图规模线性增长。
  1. 先求总和把所有节点特征逐维相加,得到总量。
    ∑v∈Vhv\sum_{v \in V} h_v
  2. 统计节点数量计算图的节点个数 \(|V|\)。
    ∣V∣|V|
  3. 除法归一化用总量除以节点数,得到每个节点特征的平均水平。
    1∣V∣∑v∈Vhv\frac{1}{|V|} \sum_{v \in V} h_v

最大池化

有时教务处只想看“这个班最亮眼的科目是哪科”。比如要评“数学特色班”,只看全班数学最高分就够了。最大池化就是这种“单项冠军”思维。

最大池化对特征向量的每一维,在所有节点中取最大值:

其中 \([h_v]_i\) 表示节点 \(v\) 特征向量的第 \(i\) 维。最大池化擅长捕捉“图中是否存在某种突出信号”,比如分子中是否存在某个关键的化学基团。但它只保留了每个维度上最极端的那个值,大量关于分布、次数、普通节点的信息都被丢弃。

只看最高分,能快速发现“最闪光的科目”,但也可能漏掉全班整体偏科、只有一个人拔尖的真相。

[hG]i=max⁡v∈V[hv]i[h_G]_i = \max_{v \in V} [h_v]_i
最大池化逐维比较所有节点,只保留该维度的最大值,因此输出维度不变,但信息非常浓缩。
  1. 取第 \(i\) 维只看特征向量的某一维,例如“数学成绩”这一列。
    [hv]i[h_v]_i
  2. 遍历所有节点在这一列上比较每个节点的数值。
    max⁡v∈V\max_{v \in V}
  3. 写入图向量把找到的最大值放到图向量的第 \(i\) 个位置。
    [hG]i=max⁡v∈V[hv]i[h_G]_i = \max_{v \in V} [h_v]_i

排序池化

如果班主任要推选“年级前十名”,不能只算总分,还要先按综合表现排序,再重点介绍前面的尖子生。排序池化就是这个思路:先给每个节点打分排序,再取前 \(k\) 个节点作为图的代表。

这里 \(s(v)\) 是节点 \(v\) 的排序分数,可以由模型学习得到。排序后取前 \(k\) 个节点,把它们各自的特征拼接成一个长向量。这个输出向量的维度是 \(k \times d\),\(d\) 是节点特征维度。相比求和、平均、最大,排序池化保留了更多“顺序结构”信息。

尖子榜不是每个学生都上榜,而是按名次挑出最有代表性的前几名,再把他们组合成班级印象。

Hsort=SORT({hv},key=s(v)),hG=Flatten(Hsort[0:k])H_{\text{sort}} = \mathrm{SORT}\left(\{h_v\}, \mathrm{key}=s(v)\right), \quad h_G = \mathrm{Flatten}\left(H_{\text{sort}}[0:k]\right)
排序池化先按节点得分排序,再取前 \(k\) 个节点并拼接特征,因此输出维度由特征维度和 \(k\) 共同决定。
  1. 给节点打分用函数 \(s(v)\) 计算每个节点的排序分数。
    s(v)s(v)
  2. 排序并截取把全部节点按分数从高到低排列,只保留前 \(k\) 个。
    Hsort[0:k]H_{\text{sort}}[0:k]
  3. 拼接成图向量把选出的 \(k\) 个节点特征展平,变成一维长向量。
    Flatten(Hsort[0:k])\mathrm{Flatten}\left(H_{\text{sort}}[0:k]\right)

注意力读出

有经验的班主任总结班级时,不会把每个学生看得一样重:班长说的话多一点,平时沉默的学生少提一点。这种“谁更重要”的判断,就是注意力读出。

注意力读出先给每个节点学一个分数 \(s_v\),再用 softmax 归一化成权重 \(\alpha_v\),最后做加权求和:

其中 \(w\) 是可学习的参数。权重越大,代表该节点对整张图贡献越大。注意力读出比朴素求和、平均更灵活,因为它能根据任务自动决定“哪些节点更值得听”。也可以加入门控机制,用 sigmoid 之类的方式控制信息流,进一步增强表达能力。

班主任心里有杆秤,注意力读出就是让模型自己学会这杆秤。

sv=w⊤hv,αv=exp⁡(sv)∑u∈Vexp⁡(su),hG=∑v∈Vαvhvs_v = w^\top h_v, \quad \alpha_v = \frac{\exp(s_v)}{\sum_{u \in V} \exp(s_u)}, \quad h_G = \sum_{v \in V} \alpha_v h_v
注意力读出让模型给每个节点分配一个学习出来的重要性权重,再按权重把节点特征合并成图向量。
  1. 计算原始分数用可学习向量 \(w\) 点乘节点特征 \(h_v\),得到分数 \(s_v\)。
    sv=w⊤hvs_v = w^\top h_v
  2. softmax 归一化把所有分数指数化后相加,再逐个相除,得到总和为 1 的权重。
    αv=exp⁡(sv)∑u∈Vexp⁡(su)\alpha_v = \frac{\exp(s_v)}{\sum_{u \in V} \exp(s_u)}
  3. 加权求和每个节点特征乘上自己的权重后相加,得到图向量。
    hG=∑v∈Vαvhvh_G = \sum_{v \in V} \alpha_v h_v

实践选择

不同报告需要不同的总结方式:家委会想看总分,教育局想看平均分,表彰会看最高分,推优看名次。图任务也一样,没有一种读出策略能通吃所有场景。

实践中的选择逻辑可以这样看:如果图的大小本身有语义,比如分子越大性质越不同,求和池化常常更有优势;如果图大小差异大而任务与规模无关,平均池化更稳定;如果任务关心“是否存在某个极端信号”,最大池化更合适;如果关心节点之间的顺序结构,排序池化更合适;如果希望模型自动决定节点重要性,注意力读出更灵活。

读出函数得到图向量后,通常还会接一个下游分类头:

策略没有绝对好坏,只有是否匹配任务。多跑几次对比实验,比争论“哪个池化最好”更有价值。

y^=Softmax(WhG+b)\hat{y} = \mathrm{Softmax}(W h_G + b)
这里 \(W\) 和 \(b\) 是分类器参数,softmax 把得分变成类别概率,最终预测图标签。
  1. 线性映射把图向量 \(h_G\) 乘以权重矩阵 \(W\),加上偏置 \(b\)。
    WhG+bW h_G + b
  2. softmax 归一化把每个类别的得分变成概率,且所有类别概率之和为 1。
    Softmax(⋅)\mathrm{Softmax}(\cdot)
  3. 输出预测类别取概率最大的类别作为整张图的预测结果 \(\hat{y}\)。
    y^\hat{y}

AI 应用场景

药物分子性质预测

阶段:图分类 / 分子属性预测

解决的问题:传统方法需要人工设计分子指纹或大量化学特征,工作量大且容易遗漏原子之间的连接结构。GNN 把原子看作节点、化学键看作边,消息传递学到原子表示后,再用读出函数得到整个分子的图向量,端到端预测水溶性、毒性等性质。

具体案例:某制药公司要筛选一万个候选分子,判断是否容易透过血脑屏障。模型先用 GIN 消息传递层更新原子特征,再用求和池化把分子图变成固定长度的图向量,最后接分类器输出“可透过/不可透过”。在公开的 MoleculeNet 数据集上,这种方案能显著减少人工特征工程。

社交网络群体分类

阶段:图级表征学习

解决的问题:判断一个用户群体是不是垃圾广告群,不能只看单个用户,还要看整个子图的结构和互动模式。传统规则容易误伤正常群组,AI 需要把整张子图压缩成一个向量再分类。

具体案例:风控团队把某个群聊的 7 天交互记录构造成一张图,每个用户是节点,消息互动是边。GNN 学习用户嵌入后,用平均池化得到群体向量,避免人数差异对判断的干扰,然后预测该群是否包含恶意导流行为。

程序代码缺陷检测

阶段:图分类 / 静态分析

解决的问题:把一段代码抽象成控制流图或抽象语法树,节点是语句或变量,边是跳转与依赖关系。判断代码片段是否有缺陷,需要对整张代码图做分类,而不是只看某一个节点。

具体案例:安全团队用图神经网络分析开源项目的函数级代码图,使用排序池化保留关键语句的先后顺序,再将图向量输入分类器,识别是否存在内存泄漏风险。排序池化对“先分配后释放”这类顺序依赖特别敏感。

Python 演示

python24 行
import numpy as np def sum_readout(h):    return np.sum(h, axis=0) def mean_readout(h):    return np.mean(h, axis=0) def max_readout(h):    return np.max(h, axis=0) def sort_readout(h, k):    scores = h.sum(axis=1)    idx = np.argsort(scores)[::-1][:k]    return h[idx].reshape(-1) if __name__ == "__main__":    np.random.seed(42)    node_features = np.random.rand(6, 3)    print("node_features:\n", node_features)    print("sum:", sum_readout(node_features))    print("mean:", mean_readout(node_features))    print("max:", max_readout(node_features))    print("sort top2:", sort_readout(node_features, 2))
目的:用 NumPy 快速实现四种常见读出函数,演示同一组节点特征如何被聚合为不同的图向量。
  1. def sum_readout(h):定义求和池化函数。
  2. return np.sum(h, axis=0)axis=0 表示按“所有节点”这一轴求和,即逐维相加。
  3. np.mean(h, axis=0)对所有节点求平均,等效于平均池化。
  4. np.max(h, axis=0)对所有节点逐维取最大值。
  5. scores = h.sum(axis=1)给每个节点算一个综合分,是排序池化的排序依据。
  6. idx = np.argsort(scores)[::-1][:k]按综合分倒序排列,取出前 \(k\) 个节点的下标。
  7. return h[idx].reshape(-1)把选中的 \(k\) 个节点特征展平,得到排序池化输出。

常见误区

误区很多人以为读出函数就是 `Linear` 或全连接层,写模型时直接在节点特征后接一个全连接层当作图输出。

正解全连接层只是对向量做线性变换,并不负责把多个节点合并成一个向量。读出函数的核心是“跨节点聚合”,先把 \(N\) 个节点向量变成 \(1\) 个图向量,之后才轮到全连接层做分类。好比班干部负责把全班的成绩汇总成一张表,教务处才负责给这张表评等级。

为何常见:因为很多分类模型最后一层都是全连接层,初学者容易把“输出层”和“聚合层”混为一谈。

误区看到某些论文说求和池化表达能力更强,就以为任何图任务都应该无脑用求和。

正解求和池化对图规模敏感,图越大向量数值越大。如果任务本身和图的规模无关,比如判断社交子图的用户密度,求和池化可能带来偏差。平均池化、最大池化、注意力读出各有适用场景,必须用验证集对比。

为何常见:论文结论往往基于特定数据集,容易让人忽略任务本身的差异。

误区最大池化听起来“最大最强”,有人认为它能把最重要的信息都留下来。

正解最大池化每个维度只保留一个最大值,把所有非最大值的分布信息全部丢弃。如果任务需要知道“有多少个节点具备某种特征”,最大池化完全无能为力。它更像只表扬最高分,却忽略了班级的整体水平。

为何常见:因为“最大值”天然带有显著性,容易让人误以为显著就等于信息完整。

误区实现排序池化时,以为必须把所有节点都保留,否则会丢失信息。

正解排序池化的核心价值恰恰是只取前 \(k\) 个节点,用固定长度的输出对齐不同尺寸的图。如果把所有节点都保留,图的节点数一变,输出维度就变了,无法直接拼 batch 做分类。

为何常见:初学者对“降维”有本能抗拒,总担心截断会丢信息,但图级任务本来就要求定长输出。

面试题

Q1. 读出函数最核心的任务是什么?

单选题 · easy

  • A.把节点向量聚合成图向量← 正确答案
  • B.把图向量拆成节点向量
  • C.给节点特征增加维度
  • D.把边特征变成点特征

答案:A。读出函数把一整组节点向量汇总成一个图向量,这是图分类任务的最后一步。把图向量拆开、增加维度、边特征转点特征都不是读出的职责。

Q2. 求和池化在图规模变大时可能出现什么问题?

单选题 · easy

  • A.图向量数值整体偏大← 正确答案
  • B.图向量数值整体偏小
  • C.图向量维度自动增加
  • D.图向量维度自动减少

答案:A。求和池化把所有节点特征逐维相加,节点越多,累加结果越大。它改变的是数值大小,不会改变输出维度。

Q3. 平均池化相比求和池化的主要优点是什么?

单选题 · mid

  • A.减少图规模带来的偏差← 正确答案
  • B.保留图的节点总数信息
  • C.让输出维度变成可变
  • D.不需要读取任何节点信息

答案:A。平均池化先求和再除以节点总数,把图规模的影响归一化,因此对节点数不同的图更公平。它不会保留节点总数,也不会改变输出维度。

Q4. 最大池化对每个维度做什么操作?

单选题 · mid

  • A.取该维度所有节点的最大值← 正确答案
  • B.取该维度所有节点的总和值
  • C.取该维度所有节点的平均值
  • D.取该维度所有节点的中位值

答案:A。最大池化是逐维比较所有节点,只保留该维度上的最大值。求和给总和,平均给均值,中位给中间值,都不是最大池化的定义。

Q5. 关于置换不变性,下列说法正确的是?

单选题 · mid

  • A.节点顺序改变时输出保持不变← 正确答案
  • B.节点顺序改变时输出随之变化
  • C.只有求和池化能做到顺序无关
  • D.读出函数不需要关心顺序问题

答案:A。读出函数必须满足置换不变性:无论节点输入顺序如何打乱,图向量都不变。求和、平均、最大都满足,排序池化通过排序也满足,不是只有求和池化能做到。

Q6. 排序池化输出向量的维度由什么决定?

单选题 · hard

  • A.由节点数量加特征维度决定
  • B.由特征维度和选取的k值决定← 正确答案
  • C.由图边数加上节点数决定
  • D.由消息传递的层数多少决定

答案:B。排序池化取前 \(k\) 个节点,每个节点特征维度为 \(d\),展平后输出维度是 \(k \times d\)。节点总数和边数只决定候选集合,不影响最终输出维度。

Q7. 注意力读出中的注意力权重通常如何得到?

单选题 · hard

  • A.对节点打分后做softmax归一化← 正确答案
  • B.对节点特征直接求平均处理
  • C.随机固定而且不参与任何训练
  • D.只根据节点自身的度数来计算

答案:A。注意力读出先给每个节点算一个可学习分数,再用 softmax 把所有分数归一化成权重,权重总和为 1。直接求平均是平均池化,随机固定或只看度数都不需要训练。

Q8. 以下哪些属于常见的读出函数?

多选题 · mid

  • A.求和池化← 正确答案
  • B.平均池化← 正确答案
  • C.最大池化← 正确答案
  • D.最短路径

答案:ABC。求和、平均、最大是最基础的三种读出函数。最短路径是一种图算法,用来计算节点之间的距离,不是把节点特征变成图特征。

Q9. 关于读出函数的描述,哪些是正确的?

多选题 · mid

  • A.通常在GNN层之后使用← 正确答案
  • B.把节点集合变成图向量← 正确答案
  • C.图分类任务依赖图级输出← 正确答案
  • D.输出维度和节点数相同

答案:ABC。读出函数一般放在所有消息传递层之后,把一组节点向量聚合为图向量,供图分类任务使用。输出维度由特征维度决定,和节点数量没有必然关系。

Q10. 选择读出策略时需要考虑哪些因素?

多选题 · hard

  • A.图规模是否变化较大← 正确答案
  • B.任务关注总量还是极值← 正确答案
  • C.是否需要保留顺序信息← 正确答案
  • D.是否使用ReLU激活函数

答案:ABC。图规模大且与任务无关时平均更稳,任务关注总量时求和更合适,关注极值时最大更合适,关注顺序时排序更合适。激活函数是消息传递层里的选择,不属于读出策略选择的决定性因素。