想象你是一位新上任的城市规划师。你手里的地图不是普通的街区图,而是一张巨大的关系网:每个建筑是一个节点,建筑之间的道路、管道、往来关系是连边。如果只盯着单个建筑,你永远看不懂这座城市;真正的门道藏在“局部”里——热闹的十字路口、安静的尽端路、环抱成团的住宅组团……这些反复出现的局部小模样,才是城市的运转密码。 子图表示学习,就是教会 AI 像老练的规划师一样扫街:它完整逛遍每个街区(枚举局部结构),给每种街区模板发一张标准身份证(编码成一串数字),再让电脑像顾问团一样综合所有街区档案,做出高质量判断。本文从“什么是子图”讲起,一路带你走过枚举、编码、神经网络建模到落地应用,读懂这份“局部结构密码”是如何被一步步破译的。

岗位关联

掌握子图表示学习,等于给你的图模型配上一副“显微镜+望远镜”:既能看清微观结构,又能把微观洞察变成全局决策。这是图数据挖掘、社交网络分析、AI 制药等方向从业者的进阶必修课。

目录
  1. 可视化演示
  2. 子图基础概念:街区的定义
  3. 子图枚举技术:扫遍全城
  4. 子图编码方法:制作身份证
  5. 子图神经网络:街区顾问团
  6. 复杂度与效率:扫街的艺术
  7. 应用与任务:改造城市
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示子图枚举的k跳邻域提取、GNN消息传递编码、以及多子图向量聚合为节点表示的完整流程。

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

子图枚举:k跳邻域提取 C=中心节点 以k跳范围提取局部子图 k=1提取直接邻居 k=2扩展至2跳 SubG(v,k)={u|dist(v,u)<=k} 枚举是子图表示学习的第一步

子图基础概念:街区的定义

城市规划师扫街的第一步,是学会“圈地”。你站在高处俯瞰城市,发现三栋写字楼围出一个三角形广场,于是用红笔圈出这三栋楼和连接它们的道路。被你圈出来的这一小簇建筑和道路,在图上就是一个“子图”——它是大图的一个局部切片。

在图论里,一张图写作 $G=(V,E)$,其中 $V$ 是节点集合,$E$ 是边集合。子图就是从这张大图里“圈”出一部分节点、再配上它们之间的一部分边组成的小图。这里有一道硬规矩:任何被圈进来的边,它的两个端点都必须同时被圈进来,否则这条边就“悬空”了,不构成合法子图。如果你不仅圈了节点,还把节点之间的所有原有边都原封不动地保留下来,这样的子图叫诱导子图;只保留部分边的则叫普通子图。

两个子图,哪怕节点的位置画得完全不一样,只要节点和边的连接关系一一对应,就称它们同构。在子图表示学习中,同构的子图被视为同一类“街区模板”——好比北京的四合院和山西的院子细节各异,但“围合院落”这个结构模板是同一个。这个定义是整个子图表示学习的基石,后面所有的枚举、编码都建立在“什么算同一个模式”之上。

就像规划师先把“十字路口”“尽端路”这些模板刻在脑海里,AI 也需要先有“子图”这个基本单元,才谈得上后面的扫街与建档。基础概念这块地基打牢了,接下来就能扛着工具上路。

Gs=(Vs,Es),Vs⊆V,Es⊆E,∀e=(u,v)∈Es:  u,v∈VsG_s = (V_s, E_s), \quad V_s \subseteq V, \quad E_s \subseteq E, \quad \forall e=(u,v) \in E_s: \; u,v \in V_s
子图 = 从大图里取一部分节点 + 一部分端点闭合的边;诱导子图则要求节点间的原有边全部保留。
  1. 节点子集从大图的节点集合 $V$ 中挑选一部分节点组成小集合 $V_s$,这是圈定街区的第一步。
    Vs⊆VV_s \subseteq V
  2. 边子集从小集合节点之间的原有边里选出需要的边组成 $E_s$,边只能来自原图,不能凭空新增。
    Es⊆EE_s \subseteq E
  3. 端点闭合约束任意一条被选中的边,它的两个端点 $u$ 和 $v$ 都必须落在节点子集里,不允许“半条腿在圈外”。
    ∀e=(u,v)∈Es:  u,v∈Vs\forall e=(u,v) \in E_s: \; u,v \in V_s
  4. 诱导子图特例当 $E_s$ 取的是 $V_s$ 节点之间全部原有边时,得到的就是诱导子图,记作 $G[V_s]$。
    G[Vs]=(Vs,{(u,v)∈E∣u,v∈Vs})G[V_s] = \big(V_s, \{(u,v) \in E \mid u,v \in V_s\}\big)

子图枚举技术:扫遍全城

有了街区模板的概念,规划师就要开始真正的扫街了。扫街不是去著名景点打卡,而是要建立一份完整的“街区普查清单”:这座城市里每种局部模样各出现了多少次、分布在哪儿。在子图表示学习里,这一步叫子图枚举——把图上所有满足条件的子图都找出来。

最朴素的做法是暴力枚举:列出所有 $k$ 个节点的组合,逐个检查它们之间的连边情况。比如想找三角形,就从 $n$ 个节点里选出所有 3 点组合,看是否恰好三边齐全。问题的关键在于:候选组合的数量本身就可能大得吓人。从 $n$ 个节点里选 $k$ 个,一共有组合数 $\binom{n}{k}$ 种可能,这是枚举复杂度的理论底线。

真实网络动辄百万节点,暴力枚举往往撑不住,于是有了各种聪明办法。三角计数是经典例子:对每条边,数一数它的两个端点有多少共同邻居,每个共同邻居就构成一个三角形,复杂度从 $O(n^3)$ 降到了 $O(m^{3/2})$($m$ 是边数)。对大尺寸子图,更常用的是抽样估计——随机撒一些种子节点,从种子出发展开局部子图,再用样本统计量外推全局频率,牺牲一点精度换来可行性。

就像有经验的规划师不会把每条小巷来回走三遍,而是先看地图定路线:好的枚举策略,能让普查从“不可能”变成“可行”。扫街的清单拿到手,下一步就是给每一种街区建档。

∣Sk∣=(nk)=n!k!(n−k)!|\mathcal{S}_k| = \binom{n}{k} = \frac{n!}{k!(n-k)!}
枚举的候选子图数量由组合数决定;$k$ 稍大,候选数量就会膨胀到天文数字,必须上技巧。
  1. 候选集合大小$\mathcal{S}_k$ 表示所有大小为 $k$ 的节点子集构成的集合,它的元素个数就是我们枚举要面对的候选数量。
    ∣Sk∣|\mathcal{S}_k|
  2. 组合计数从 $n$ 个节点里不重复地选出 $k$ 个节点的选法总数,写作组合数 $\binom{n}{k}$。
    (nk)\binom{n}{k}
  3. 阶乘展开组合数等价于“排列数除以内部顺序”的化简形式 $n!/(k!(n-k)!)$,便于手算和程序实现。
    n!k!(n−k)!\frac{n!}{k!(n-k)!}
  4. 增长量级当 $k$ 固定时,$\binom{n}{k}$ 是 $n^k$ 量级,这就是暴力枚举不可避免的复杂度天花板。
    (nk)=O(nk)\binom{n}{k} = O(n^k)

子图编码方法:制作身份证

普查完所有街区,规划师得给每种模板建档案。档案不能是冗长的素描图,而必须是一张格式统一的标准身份证——上面写着几个关键数字,凭这几个数字就能把不同街区区分开。在子图表示学习里,这张“身份证”就是子图的向量编码。

最经典的结构指纹是 WL(Weisfeiler-Lehman)颜色。它的想法很朴素:一开始,每个节点用自己的标签(比如度)当颜色;每一轮,节点把邻居的颜色收集起来,连同自己的旧颜色一起做一次哈希,得到新颜色。多轮迭代后,颜色分布就成了子图的结构指纹。两个结构差异足够大的子图,颜色直方图也会明显不同——这就是“颜色细化”的判别力来源。

除了 WL 颜色,另一大类是位置编码:把节点度、节点到子图中心的距离、聚类系数等信息直接拼进特征里。无论哪种编码,最终都要落到同一个出口——把子图内所有节点的特征聚合成一个固定长度的向量。常用的聚合有求和、取平均、最大池化,也可以用注意力机制让模型自己决定哪些节点更重要。关键原则是:聚合方式必须对节点的排列顺序不敏感,因为同一个子图换个遍历顺序,结构并没有变。

每一类街区模板都拿到了一张标准身份证,之后的故事就顺理成章了:顾问团登场,识字读证、综合研判。不过身份证上的数字只是素材,真正把它们用起来的,是下一节的神经网络。

c(t+1)(v)=HASH(c(t)(v),{ ⁣{c(t)(u):u∈N(v)} ⁣})c^{(t+1)}(v) = \text{HASH}\left( c^{(t)}(v), \{\!\{ c^{(t)}(u) : u \in \mathcal{N}(v) \}\!\} \right)
WL 颜色迭代地让每个节点“看见”越来越大的邻域:先把邻居颜色打包,再哈希成新的自身颜色。
  1. 初始颜色每个节点 $v$ 以自身标签(如节点类型或度)作为第 0 轮颜色 $c^{(0)}(v)$,这是身份证的底版。
    c(0)(v)=ℓ(v)c^{(0)}(v) = \ell(v)
  2. 邻居颜色收集遍历节点 $v$ 的所有直接邻居 $u \in \mathcal{N}(v)$,把它们的当前颜色取出来。
    u∈N(v)u \in \mathcal{N}(v)
  3. 多重集打包用多重集符号 $\{\!\{\cdots\}\!\}$ 表示“允许重复、顺序无关”的邻居颜色包——邻居的排列顺序不影响结果。
    { ⁣{c(t)(u):u∈N(v)} ⁣}\{\!\{ c^{(t)}(u) : u \in \mathcal{N}(v) \}\!\}
  4. 哈希合并细化把自身旧颜色与邻居颜色包一起送入哈希函数,生成新一轮颜色;迭代多次后,子图就有了稳定指纹。
    c(t+1)(v)=HASH(c(t)(v),{ ⁣{c(t)(u):u∈N(v)} ⁣})c^{(t+1)}(v) = \text{HASH}\left( c^{(t)}(v), \{\!\{ c^{(t)}(u) : u \in \mathcal{N}(v) \}\!\} \right)

子图神经网络:街区顾问团

档案室建好了,该请顾问团出场了。子图神经网络(Subgraph Neural Network,SGN)就是这样一个顾问团:它不满足于只看身份证上的静态数字,而是会亲自走进每个街区,在街区内挨家挨户询问,再把听到的信息汇总成一份动态评估报告。

SGN 的工作分两步。第一步是消息传递:子图内的每个节点不断向邻居发送自己的特征,同时接收邻居发来的特征并更新自己的表示。经过若干轮后,每个节点的表示就“吸收”了周围邻居的信息。第二步是聚合读出:把子图内所有节点的最终表示聚合成一个向量,这个向量就是子图的整体表示,可以直接喂给下游分类器。与传统 GNN 的区别在于,SGN 的消息传递被刻意限制在已枚举的局部子图范围内——它只关心“这一个街区内部发生了什么”,而不是整座城的全局漫游。

更进一步的做法是层级池化:先把小的子图表示聚合成较大区域的表示,再把大区域的表示拼装成整张图的表示。这就像先把街区组成城区、再把城区组成城市,让模型既能看微观细节,又能看宏观全局。层级结构给了 SGN 一种天然的“多尺度”视野,这是它擅长捕捉精细局部结构的关键原因。

顾问团读完全部街区档案后,终于可以给出结论了。但别急——在结论落地之前,还有一个现实问题绕不开:扫街和建档的成本有多高?效率生死线,就在下一节。

hS=AGG({σ(W hv(L)):v∈S})h_S = \text{AGG}\left( \left\{ \sigma\left( W\, h_v^{(L)} \right) : v \in S \right\} \right)
SGN 的聚合公式:先对子图内每个节点的最终表示做线性变换和激活,再用聚合函数合并成子图向量。
  1. 节点最终表示$h_v^{(L)}$ 是节点 $v$ 经过 $L$ 轮消息传递后的最终嵌入,已经携带了局部邻域信息。
    hv(L)h_v^{(L)}
  2. 线性变换用可学习矩阵 $W$ 对节点表示做投影,把节点嵌入映射到“子图空间”,让模型有机会区分不同角色。
    W hv(L)W\, h_v^{(L)}
  3. 非线性激活$\sigma(\cdot)$ 是激活函数(如 ReLU),为模型注入非线性,否则多层线性变换等价于一层,学不到复杂结构。
    σ(W hv(L))\sigma\left( W\, h_v^{(L)} \right)
  4. 子图聚合$\text{AGG}(\cdot)$ 把子图 $S$ 内所有节点的变换结果合并成一个向量 $h_S$,它是子图的整体“评估报告”。
    hS=AGG({σ(W hv(L)):v∈S})h_S = \text{AGG}\left( \left\{ \sigma\left( W\, h_v^{(L)} \right) : v \in S \right\} \right)

复杂度与效率:扫街的艺术

城市实在太大了。就算有了顾问团和身份证,如果每建档一个街区都要花一年,规划就永远完不成。子图表示学习能不能真正落地,效率问题是绕不开的生死线。

第一个敌人是组合爆炸。候选子图的数量随子图尺寸 $k$ 急剧膨胀:$k$ 固定时是 $n^k$ 量级,而 $k$ 稍微增大(比如从 3 涨到 5),候选量就可能差出几个数量级。更要命的是,每个候选子图还要做合法性检查和编码,这部分开销同样不可忽略。工程上有三件兵器:共享计算(把反复出现的结构模式缓存起来,只算一次)、在线剪枝(提前排除明显不合格的候选)、并行加速(把不同区域分给不同计算单元同时扫街)。

具体到算法层面,三角计数可以用矩阵乘法加速:邻接矩阵 $A$ 的立方对角线元素之和除以 6,就是三角形总数,复杂度取决于矩阵乘法的先进算法。但对更大尺寸的子图,矩阵技巧失效,现实选择往往是抽样估计——随机采样局部区域,按比例外推全局频率。抽样估计的哲学是“以偏概全、以精度换规模”:只要采样足够多,估计值就能以高概率贴近真实值。

扫街要有策略:既不能漏掉关键街区,也不能在无关角落空耗体力。效率优化的本质,就是在这两者之间找平衡。当效率问题解决了,顾问团的结论才能真正变成改造城市的行动。

T(n)=O((nk)⋅f(k))=O(nk)T(n) = O\left( \binom{n}{k} \cdot f(k) \right) = O(n^k)
总复杂度 = 候选子图数 × 单个子图处理开销;$k$ 每增加 1,复杂度就整体抬高一个数量级。
  1. 候选数量项$\binom{n}{k}$ 是大小为 $k$ 的子图候选数量,它决定了至少要“看一眼”多少个结构。
    (nk)\binom{n}{k}
  2. 单子图开销$f(k)$ 表示对单个候选子图做合法性检查、编码等操作消耗的时间,它只与 $k$ 有关。
    f(k)f(k)
  3. 乘积求和把候选数量与单位开销相乘,得到总时间 $T(n)$,这就是枚举+编码的理论总成本。
    (nk)⋅f(k)\binom{n}{k} \cdot f(k)
  4. 渐近上界当 $k$ 固定时,总复杂度简化成 $O(n^k)$;$k=3$ 是三次方,$k=10$ 就已经逼近实际不可行。
    O(nk)O(n^k)

应用与任务:改造城市

所有准备工作,最终都是为了一个目标:让城市决策更聪明。子图表示学习的价值,集中在三类最常见的落地场景——看单栋楼(节点分类)、看整座城(整图分类)、预测特殊建筑的属性(分子性质预测)。

先看节点分类。判断一个社交用户是不是社区核心,不能只看他本人发过什么,还要看他周围的局部结构:他是不是处于密集的三角关系里?有没有一群互相关注的“铁哥们”把他围在中心?把他 2 跳范围内的子图编码成向量,再拼进他的节点表示,分类器就能捕捉到这类“结构信号”。这就是子图表示学习增强节点分类的基本套路。

再看整图分类。判断两张蛋白质结构图是否属于同一功能家族,可以把每张图分解成一袋子子图,把子图编码的直方图当作整张图的指纹,再送进分类器。这里的关键是一个全局读出操作:把图里所有子图的向量汇总成图级向量。与此类似,在 AI 制药中,分子天然是一张图:原子是节点、化学键是边,苯环、羧基这些功能基团就是典型的子图。模型学会“哪个局部基团组合决定药效或毒性”,比只看单个原子准确得多。

至此,从扫街、建档、咨询到决策,子图表示学习的完整链路贯通了。局部结构的密码,最终变成推动全局决策的钥匙。下次再面对一张巨大的关系网,你也能像个老练的规划师一样,从街区里读懂整座城市。

hG=READOUT({hS:S∈S(G)})h_G = \text{READOUT}\left( \{ h_S : S \in \mathcal{S}(G) \} \right)
整图表示 = 把从图里枚举出的所有子图向量,通过一个全局读出函数汇总成一个图级向量。
  1. 子图集合$\mathcal{S}(G)$ 表示从图 $G$ 中枚举出的所有子图的集合,它是“街区普查”的产物。
    S(G)\mathcal{S}(G)
  2. 子图向量$h_S$ 是每个子图 $S$ 经过编码得到的向量表示,相当于每张街区的身份证。
    hS:S∈S(G)h_S : S \in \mathcal{S}(G)
  3. 全局读出$\text{READOUT}(\cdot)$ 把所有子图向量汇总(求和、取最大或注意力加权),得到图级表示 $h_G$。
    READOUT({hS:S∈S(G)})\text{READOUT}\left( \{ h_S : S \in \mathcal{S}(G) \} \right)
  4. 下游使用$h_G$ 作为整张图的特征,被送入分类器或回归头,完成图分类、性质预测等任务。
    hG→预测结果h_G \to \text{预测结果}

AI 应用场景

分子性质预测:AI 制药的阅卷官

阶段:图级表示学习(训练与推理)

解决的问题:传统方法靠人工设计分子指纹(如摩根指纹),难以自动捕捉“多个功能基团组合”的细微结构。子图表示学习自动把分子切割成局部基团子图并编码,让模型自己发现“苯环连着羧基”这类组合与药效之间的隐秘关系。

具体案例:某药企需要在上万候选分子里筛出低毒性的先导化合物。把分子构建成图后,枚举 3-5 节点子图,用 SGN 编码子图并读出整图表示,在 Tox21 毒性基准上比普通 GNN 提升了约 5 个百分点的 AUROC,还顺带发现两个此前被忽视的毒性功能基团组合。

社交网络社区挖掘:风控的照妖镜

阶段:节点级表示学习(特征增强)

解决的问题:只看用户的个人画像根本识别不出刷单团伙——团伙成员往往表现为“互相关注、密集互动”的局部小圈子(三角闭合、星形子图)。子图表示学习把用户周边的局部子图编码进节点表示,让异常结构无处遁形。

具体案例:某电商平台用子图编码识别异常团购群:把用户下单关系建模成图,提取每个用户的 2 跳子图编码作为额外特征。结果显示,刷单团伙成员的编码向量显著偏离正常用户分布,异常账户召回率提升了 30%,误杀率几乎没涨。

蛋白质功能注释:生物信息的解码器

阶段:图分类(结构域建模)

解决的问题:蛋白质的生物学功能常由特定局部结构域决定,而这些结构域在残基接触图上恰好表现为重复出现的子图模式。子图表示学习能从结构域中自动抽取判别性子图,替代人工标注特征。

具体案例:研究团队用子图枚举+编码预测酶的功能类别,把活性位点附近的子图作为强特征,预测 F1 值显著超过传统基于序列比对的方法;子图编码还帮助可视化了“哪些局部结构共同决定催化功能”,为后续湿实验提供了线索。

Python 演示

python53 行
# -*- coding: utf-8 -*-"""子图表示学习演示: 枚举三角/路径子图并编码为固定向量"""from itertools import combinations  def enumerate_3node_subgraphs(adj):    """枚举图中的所有 3 节点连通子图, 返回 (三角形数, 路径数)"""    nodes = list(adj.keys())    tri_cnt, path_cnt = 0, 0    for a, b, c in combinations(nodes, 3):        ab = b in adj[a]        ac = c in adj[a]        bc = c in adj[b]        deg = ab + ac + bc  # 三对节点之间实际存在的边数        if deg == 3:            tri_cnt += 1     # 三点两两相连 -> 三角形模板        elif deg == 2:            path_cnt += 1    # 恰好两条边 -> 路径模板    return tri_cnt, path_cnt  def encode_ego_subgraph(adj, center):    """把中心节点的局部子图编码成一个 4 维向量"""    neighbors = list(adj[center])    k = len(neighbors)    inner_edges = sum(        1 for i in range(k) for j in range(i + 1, k)        if neighbors[j] in adj[neighbors[i]]    )    missing_edges = k * (k - 1) // 2 - inner_edges    vec = [k, inner_edges, missing_edges, len(adj)]    return vec  def main():    # 小社交网络: 0 是核心节点, 周围有三角形和路径结构    adj = {        0: {1, 2, 3},        1: {0, 2},        2: {0, 1, 4},        3: {0, 4},        4: {2, 3, 5},        5: {4},    }    tri, path = enumerate_3node_subgraphs(adj)    print("三角子图数:", tri, " 路径子图数:", path)    for center in [0, 4, 5]:        vec = encode_ego_subgraph(adj, center)        print("节点", center, "的局部子图编码:", vec)  if __name__ == "__main__":    main()
目的:实现正文讲的“子图枚举 + 子图编码”流水线——先枚举三类节点构成的所有连通子图并统计模板频率,再把每个中心节点的局部子图编码为 4 维向量。
  1. def enumerate_3node_subgraphs(adj):枚举入口:遍历整张图的所有三节点连通子图,对应正文的“扫街普查”。
  2. for a, b, c in combinations(nodes, 3):用组合函数生成所有三点候选,对应暴力枚举的 $O(n^3)$ 候选空间。
  3. deg = ab + ac + bc统计三个点之间实际存在的边数,一条核心判断决定了子图属于哪种模板。
  4. elif deg == 2:恰好两条边时是“一字路径”模板,与三角形共同构成本例的两种街区类型。
  5. def encode_ego_subgraph(adj, center):以某节点为中心切出局部街区,对应正文的“子图提取”。
  6. inner_edges = sum(统计邻居之间的内部边数,这是刻画街区密集程度的关键结构属性。
  7. vec = [k, inner_edges, missing_edges, len(adj)]把局部结构压成固定长度 4 维向量,模拟身份证编码。

常见误区

误区子图嘛,就是从大图里随便圈几个节点出来,画个圈就算完事了,边随便连不连都行。

正解合法子图必须满足“端点闭合”:选进来的每条边,两个端点都必须在节点集合里。更进一步,如果保留的是节点间的全部原有边,那是诱导子图;只保留一部分是普通子图。这就像圈定街区时,道路的两头都得在圈内,不能有小半截马路伸出圈外——否则这个“街区”在结构上就是残缺的。

为何常见:“子”字容易让人望文生义,以为子图只是一个随意的“子集”,忽略了边与节点之间的约束关系。

误区太好了,两个子图的 WL 颜色直方图一样,那它们一定是同一个结构模板,绝对错不了。

正解WL 颜色(1-WL)的判别力确实很强,但有极限——某些结构不同但很“对称”的图(比如特定正则图)会得到完全相同的颜色分布。所以 WL 颜色是“必要的结构指纹”,不是“充分的结构判定”。它像身份证号能区分大多数人,但遇到双胞胎还是会看走眼,需要更精细的工具兜底。

为何常见:教材里 WL 算法能区分各种经典例子,给人留下了“WL 无所不能”的错觉,实际上它的表达能力上限是业界著名课题。

误区把图上所有 5 节点子图全部枚举出来喂给模型,信息最全,SGN 一定最强。

正解子图数量随尺寸 $k$ 指数爆炸,全量枚举在真实大图上根本不现实;即使强行枚举完,大量重复和低区分度的子图还会变成噪声,拖累训练。实践中常用抽样估计或限制子图尺寸/类型,用可控的采样换来可接受的精度。扫街讲究效率,不是把每条路都走十遍才算认真。

为何常见:“信息越多越好”的直觉在大数据时代被过度放大了,忽略了计算成本和非结构化噪声的代价。

误区子图神经网络不也是“节点更新+聚合”吗?跟普通 GNN 有啥本质区别,改改输入数据不就行了。

正解SGN 的核心在于把“子图结构”本身当成一种归纳偏置:消息传递被限制在已枚举的子图内部,且“子图”作为整体参与学习(比如用注意力聚合子图节点)。普通 GNN 是在全图范围内做消息传递,看到的是全局平滑后的信息;SGN 刻意保留局部结构的锐利细节,二者视野完全不同。就像顾问团专门走访街区而不只是看全市统计报表,结论自然更接地气。

为何常见:两者在代码层面的操作确实相似(都是消息传递、聚合),表面相似掩盖了建模思想的差异。

面试题

Q1. 关于子图的定义,下列说法正确的是?

单选题 · easy

  • A.子图节点的边可以指向外部节点
  • B.子图中每条边两端都在子图内← 正确答案
  • C.子图必须包含原图的全部节点
  • D.子图节点数必须少于原图的一半

答案:B。子图的合法性要求“端点闭合”——被选入的每条边,两个端点都必须同时属于节点子集。A 让边悬空在子图外,破坏了闭合性;C 把子图等同于原图;D 用数量做硬性限制没有依据。选 B。

Q2. 诱导子图 $G[V_s]$ 的定义特征是什么?

单选题 · easy

  • A.只保留部分被选节点之间的边
  • B.保留被选节点间的全部原有边← 正确答案
  • C.只保留度数最高的几条关键边
  • D.在子图内随机均匀地新增边

答案:B。诱导子图要求把 $V_s$ 内部原有的边“原封不动”全部保留,这是它与普通子图的唯一区别。A 是普通子图;C 引入了度数标准,定义里没有;D 新增边违背“边只能来自原图”的基本约束。

Q3. 暴力枚举 $n$ 节点图的所有 $k$ 节点子图,候选数量级是?

单选题 · easy

  • A.与节点数 $n$ 成正比的线性级别
  • B.与 $n$ 的平方成正比的级别
  • C.与 $n$ 的 $k$ 次方成正比的级别← 正确答案
  • D.与 $k$ 的 $n$ 次方成正比的级别

答案:C。从 $n$ 个节点里选 $k$ 个的组合数是 $\binom{n}{k}$,当 $k$ 固定时是 $O(n^k)$。A、B 只是 $k=1,2$ 的特例;D 把底数和指数搞反了,当 $k$ 固定时 $k^n$ 会随 $n$ 爆炸得更快,不符合枚举候选的计数逻辑。

Q4. WL 颜色细化每一轮做的事情是?

单选题 · mid

  • A.把自身颜色与邻居颜色哈希合并← 正确答案
  • B.把全部节点的颜色随机打乱
  • C.只保留颜色值最大的那个节点
  • D.按节点编号从小到大的顺序排序

答案:A。WL 每轮把节点自身旧颜色与其邻居颜色多重集一起哈希成新颜色,让节点“看见”越来越大的邻域。B 随机打乱会丢失结构信息;C 只保留一个节点违背了所有节点并行细化的原则;D 排序不改变颜色值,属于无用操作。

Q5. 三角计数比暴力枚举更高效的关键在于?

单选题 · mid

  • A.只统计每条边两端点的共同邻居数← 正确答案
  • B.直接把所有三角形画出来再逐一数
  • C.只数度数最大的节点参与的三角形
  • D.对节点颜色做排序之后再进行计数

答案:A。三角计数把“数三角形”转化为“数共同邻居”:每条边的两端点有多少公共邻居,就有多少个包含该边的三角形,这样避免了遍历全部三点组合,复杂度降到 $O(m^{3/2})$。B 还是要枚举全部;C 会漏掉不经过最大度节点的三角形;D 排序与三角形计数没有本质联系。

Q6. 关于 SGN 的消息传递范围,下列说法正确的是?

单选题 · hard

  • A.消息传递限定在已枚举的子图内部← 正确答案
  • B.消息可以在任意节点之间任意传递
  • C.消息传递只作用于叶子节点本身
  • D.消息传递不需要聚合子图内节点

答案:A。SGN 的核心归纳偏置就是把消息传递限制在局部子图内,保留局部结构的锐利信息,而不是全局平滑。B 是普通 GNN 的全图消息传递;C 只作用于叶子节点没有依据,子图内所有节点都参与;D 恰恰相反,聚合是 SGN 读出的必经步骤。

Q7. 两个子图经过 WL 颜色迭代后得到相同结果,可以断定什么?

单选题 · extreme

  • A.两个子图一定完全同构
  • B.两个子图可能结构并不相同← 正确答案
  • C.两个子图的编码一定失败
  • D.两个子图一定结构不同

答案:B。1-WL 的判别力有上限,存在结构不同但 WL 颜色分布相同的图(如某些正则图),所以颜色相同只是“必要不充分”条件。A 过度自信;C 不符合逻辑,颜色相同不代表编码失败,可能只是判别力不足;D 与已知事实相反,颜色相同也可能对应同构图。

Q8. 下列哪些属于子图编码的常用手段?

多选题 · mid

  • A.WL 颜色直方图← 正确答案
  • B.节点度的位置编码← 正确答案
  • C.贪心随机游走算法
  • D.概率图模型推理

答案:AB。子图编码的经典路径是“结构指纹”(WL 颜色直方图)和“位置编码”(度、距离、聚类系数等)。C 贪心随机游走常用于图嵌入的上下文采样,不是子图编码的直接手段;D 概率图模型是另一套建模框架,并不产出子图的结构向量编码。

Q9. 缓解子图枚举组合爆炸的可行策略有?

多选题 · hard

  • A.随机抽样估计子图频率← 正确答案
  • B.缓存复用公共中间结果← 正确答案
  • C.并行分配不同区域计算← 正确答案
  • D.单纯加大系统内存硬扛

答案:ABC。抽样估计、共享计算、并行加速正是正文讲的工程三板斧。D 加内存只能缓解存储压力,无法降低候选子图数量随 $k$ 的爆炸式增长,候选量的指数本质靠内存是扛不下来的。

Q10. 子图表示学习适合解决的场景有?

多选题 · mid

  • A.判断分子里是否含某功能基团← 正确答案
  • B.识别社交网络中的紧密小团体← 正确答案
  • C.统计文本中单词出现总词频
  • D.预测蛋白质结构的性质标签← 正确答案

答案:ABD。分子功能基团、社交小团体、蛋白质结构域本质上都是“反复出现的局部子图模式”,子图表示学习天然匹配。C 统计词频只需要普通的计数器,不涉及图结构,也谈不上局部拓扑模式,属于明显不相关的干扰项。