试想一个孩子面对一大桶乐高积木:有红色、蓝色、透明的小方块,每块积木的顶部有凸起的“插销”,底部有对应的“插槽”。孩子想搭一座城堡,决定城堡样子的,不只是用了多少块积木,更是哪块积木和哪块积木咬合、咬合了几格。化学家想设计一种新分子,处境和这个孩子很像:原子是积木,化学键是插销,而“分子图”就是把这座分子城堡的结构用点和线画出来。过去,化学家只能在实验室里反复试错;现在,AI 可以一边学习“怎样搭积木才好看又结实”,一边源源不断提出新的分子图。分子图生成的核心问题是:让模型直接在图结构上“动手”,一步一步或一次性摆放原子和化学键,同时保证搭出来的不是一碰就散的“危房”。

岗位关联

掌握分子图生成,等于握住了 AI 驱动新材料与药物设计的“生成引擎”,让算法从“只会预测”升级到“能够创造”。

目录
  1. 可视化演示
  2. 分子图表示:先给乐高城堡画连接图
  3. 图神经网络:搭积木的“手感”
  4. 自回归生成:下一块积木怎么放
  5. 一次生成:用蓝图瞬间摆满整张桌子
  6. 化学有效性保证:不让积木长出第六个插槽
  7. 评估方法:验收城堡的合格率
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示自回归逐步生成、范式对比与化学有效性评估,支持有效性约束调节。

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

自回归分子图生成 紫色原子节点逐步添加到分子图中 青色化学键连接新生原子与已有原子 G(t+1) = f(G(t)) → add atom + bond 逐步构建类似语言模型的逐词生成

分子图表示:先给乐高城堡画连接图

孩子在搭乐高之前,常常会看说明书上的结构分解图:哪块积木放在哪个位置,哪两个凸起插进哪两个凹槽。分子图生成的第一步,就是先把真实分子变成一张计算机能读懂的“结构分解图”。在这张图里,每个原子是一块积木,每条化学键是一处咬合关系。把氢原子先隐藏起来,只保留重原子,就得到一张简洁的分子骨架图。

有了“节点”和“边”的概念后,还需要把图变成数字。最常见的方式是邻接矩阵:一个 N 个原子的分子对应一个 N×N 的矩阵,第 i 行第 j 列的值表示原子 i 和原子 j 之间有没有键、是单键还是双键。这个值相当于乐高说明书里“插销咬合了几格”。与此同时,每个原子还需要一张身份证,记录原子种类、形式电荷、手性等信息,这就是特征矩阵。

有了这两张表,模型不需要看三维坐标,也能知道分子的骨架形状。就像孩子在搭积木前先看说明书,心里已经知道城堡的“骨骼”长什么样了。

G=(V,E),Aij={w,(i,j)∈E0,otherwise,X∈RN×d\displaystyle G=(\mathcal{V},\mathcal{E}),\quad A_{ij}=\begin{cases} w,& (i,j)\in\mathcal{E}\\ 0,& \text{otherwise} \end{cases},\quad X\in\mathbb{R}^{N\times d}
一句话:邻接矩阵回答“谁和谁相连、连了几格”,特征矩阵回答“每块积木是谁、长什么样”。
  1. 节点集合分子里每个非氢原子都是一块乐高积木,集合记为 $\mathcal{V}$,大小为 $N$。
    V={v1,v2,…,vN}\mathcal{V}=\{v_1,v_2,\dots,v_N\}
  2. 邻接矩阵如果原子 $i$ 和原子 $j$ 之间有键,$A_{ij}$ 就写成键级 $w$;没有键就是 0。
    Aij={w,(i,j)∈E0,otherwiseA_{ij}=\begin{cases} w,& (i,j)\in\mathcal{E}\\ 0,& \text{otherwise} \end{cases}
  3. 特征矩阵每一行是一个原子的 $d$ 维特征向量,比如元素种类、电荷、手性。
    X∈RN×dX\in\mathbb{R}^{N\times d}

图神经网络:搭积木的“手感”

有经验的乐高师傅不会只盯着一块积木看,他会同时留意这块积木周围已经砌好的砖块:左边卡得紧不紧,下面支撑稳不稳。图神经网络(GNN)模仿的正是这种“手感”。它不把原子当成孤立个体,而是让每个原子不断向邻居“打听”信息。

消息传递的过程很像师傅在工地上喊话:每个原子先把自己的向量发给邻居,邻居收到后把一圈消息“合并”成一条汇总信息,再传回给中心原子;中心原子把这条汇总信息和自己的旧向量组合,得到新的向量。这个过程重复 K 次后,每个原子的向量就携带了 K 层邻居的信息。消息传得越远,原子对周围环境的感知就越完整。

经过 GNN 编码,整个分子图还可以被“读出”成一个表示向量。这个向量像一份浓缩的搭建报告,既包含局部细节,也包含全局骨架信息,可以送给后续的生成器或属性预测器使用。

hv(k+1)=UPDATE(hv(k), AGG({hu(k):u∈N(v)}))\displaystyle h_{v}^{(k+1)}=\text{UPDATE}\left(h_{v}^{(k)},\,\text{AGG}\left(\{h_{u}^{(k)}:u\in\mathcal{N}(v)\}\right)\right)
一句话:每个原子不断“听邻居汇报”,再把自己的状态更新一遍,信息在图上像接力棒一样传递开。
  1. 邻居集合$\mathcal{N}(v)$ 是与原子 $v$ 直接相连的一圈原子,相当于积木旁边已经砌好的相邻砖块。
    u∈N(v)u\in\mathcal{N}(v)
  2. 聚合消息用求和、平均或取最大值等操作,把邻居向量合并成一条“邻域消息”。
    AGG({hu(k):u∈N(v)})\text{AGG}\left(\{h_{u}^{(k)}:u\in\mathcal{N}(v)\}\right)
  3. 更新状态把旧的 $h_v^{(k)}$ 与聚合消息组合,得到新状态 $h_v^{(k+1)}$,相当于师傅看了邻居的支撑情况后,重新判断手里的积木该怎么放。
    hv(k+1)=UPDATE(hv(k),AGG(⋅))h_{v}^{(k+1)}=\text{UPDATE}\left(h_{v}^{(k)},\text{AGG}(\cdot)\right)

自回归生成:下一块积木怎么放

有些孩子搭城堡时习惯一块一块按顺序搭:先铺底座,再立塔楼,最后装屋顶。自回归图生成就是这个思路:模型先看到当前已经搭好的局部分子图,然后决定下一块“积木”(新原子)放在哪里、和哪些已有积木连起来。每一步只做一个小决定,但所有决定串起来就是完整分子。

模型眼中的概率世界是这样的:整张图的概率,等于每一步选择概率的乘积。第 t 步的条件是“目前已有的部分结构 $G_{<t}$”,在这个条件下,模型同时预测新原子 $v_t$ 和它与旧原子之间的边 $\mathbf{e}_t$。这一步很像孩子每次抬头看半成品,再低头挑下一块积木:前面的选择决定了后面的选择空间。

逐块搭建的好处是每一步都能请“化学规则”来把关:超价的选择不允许出现。坏处是每生成一个新原子都要调用一次 GNN,速度比“一次倒出所有积木”慢得多。

P(G)=∏t=1TP(vt,et∣G<t)\displaystyle P(G)=\prod_{t=1}^{T}P\left(v_t, \mathbf{e}_t \mid G_{<t}\right)
一句话:自回归生成像连续做决定,每步都“看着已经搭好的部分”决定下一块积木放哪。
  1. 局部图条件$G_{<t}$ 表示前 $t$ 步之前已经生成的部分分子图。
    G<t={v1,…,vt−1,e1,…,et−1}G_{<t}=\{v_1,\dots,v_{t-1},\mathbf{e}_1,\dots,\mathbf{e}_{t-1}\}
  2. 单步事件$v_t$ 是第 $t$ 步新增的原子,$\mathbf{e}_t$ 是它与旧原子的连接边。
    (vt,et)(v_t, \mathbf{e}_t)
  3. 概率连乘把每一步的条件概率相乘,得到整张图出现的总概率。
    ∏t=1TP(vt,et∣G<t)\prod_{t=1}^{T}P\left(v_t,\mathbf{e}_t\mid G_{<t}\right)

一次生成:用蓝图瞬间摆满整张桌子

另一类师傅不一块一块搭,而是先在脑中画好整张蓝图,然后把积木一次性倒到桌面上,按蓝图同时拼完。一次生成范式就是这样:模型不再逐步做出选择,而是从某个潜变量 $z$ 出发,一次性输出所有原子和所有原子对之间的连接关系。想象一个画家不看局部,直接挥毫泼墨画出整幅画。

一次生成常见于变分自编码器(VAE)或生成对抗网络(GAN)等模型。模型把目标分子压缩成一个潜变量 $z$,$z$ 像一张缩略蓝图;解码器再根据这张蓝图,把所有节点的特征和所有边同时“打印”出来。对每个边,模型输出一个概率,表示这条边是否存在、是单键还是双键。

一次生成的优势是速度快,适合大规模扫库;缺点是所有位置同时决定,局部信息容易互相矛盾。就像把所有积木同时摆上去,可能两块积木抢同一个插槽。

P(A,X∣z)=∏i=1N∏j=1NP(aij∣z)\displaystyle P(A,X\mid z)=\prod_{i=1}^{N}\prod_{j=1}^{N}P(a_{ij}\mid z)
一句话:一次生成把整座“积木城堡”的每个接口同时决定,像 3D 打印一样快,但也容易局部打架。
  1. 潜变量蓝图$z$ 是分子图的压缩表示,保存了“这是一座塔楼还是城堡”的整体信息。
    z∈Rdzz\in\mathbb{R}^{d_z}
  2. 单条边概率$a_{ij}$ 表示原子 $i$ 和原子 $j$ 之间的连接状态,模型对每对原子都预测一个概率。
    P(aij∣z)P(a_{ij}\mid z)
  3. 并行连乘对所有 $N^2$ 个原子对同时做预测,再把所有概率相乘得到整体分布。
    ∏i=1N∏j=1NP(aij∣z)\prod_{i=1}^{N}\prod_{j=1}^{N}P(a_{ij}\mid z)

化学有效性保证:不让积木长出第六个插槽

乐高积木的插槽数量是出厂固定的:四格积木只能接四根插销,硬塞五根,积木就会开裂。化学中的原子也有类似的“插槽容量”——碳通常最多连四根键,氮一般连三根,氧一般连两根。分子图生成最重要的安全红线,就是不能让某个原子“长出第六个插槽”。

化学有效性保证有两种常用做法。第一种是“生成中约束”,模型每预测一步,就把会让原子超价的候选动作直接掩码掉,相当于师傅搭到一半就发现自己手里这块积木不能硬塞。第二种是“生成后校验”,先把分子图生成出来,再用 RDKit 等化学工具检查价态、电荷、芳香性,不合法的结构就丢弃或修复。

有了这些约束,生成的分子才不是天马行空的“散装积木”,而是能够真正放进化学世界、被合成和测试的候选结构。

∑jaij≤batom(i),∀i∈{1,…,N}\displaystyle \sum_{j} a_{ij} \le b_{\text{atom}(i)},\quad \forall i\in\{1,\dots,N\}
一句话:化学有效性保证就是时刻检查“每个原子已经用掉的插槽数”有没有超过它的出厂插槽数。
  1. 统计成键数把原子 $i$ 与所有邻居之间的键级加起来,得到它已经占用的插槽总数。
    ∑jaij\sum_{j} a_{ij}
  2. 价态容量$b_{\text{atom}(i)}$ 是原子 $i$ 能接受的最大成键数,例如碳是 4。
    bC=4,bN=3,bO=2b_{\text{C}}=4,\quad b_{\text{N}}=3,\quad b_{\text{O}}=2
  3. 全图约束对每一个原子都检查这个不等式,任何一个原子超价,整个分子就判为不合法。
    ∑jaij≤batom(i),∀i\sum_{j} a_{ij} \le b_{\text{atom}(i)},\quad \forall i

评估方法:验收城堡的合格率

城堡搭好后,师傅要验收:每个接口是否都扣紧了?每座城堡是不是长得一模一样?有没有设计出新样式?分子图生成也有自己的“验收指标”。最基本的是有效性,也就是生成结果里有多少是化学上合法的分子;这个指标像“每 100 座积木城堡有几座没有散架”。

但只谈有效性远远不够。模型可能学会偷懒,永远输出同一个合法分子,因此需要唯一性来排除重复;如果模型只是背下训练集里的分子,还需要新颖性来衡量有多少生成结果是训练集里没见过的。对于真正有用的 AI 设计,还要看性质命中率:生成一万个分子,有多少个落在目标熔点、溶解度或活性阈值之内?这决定了模型是花架子还是真能帮科学家缩小搜索范围。

评估方法就像城堡质检员的验收单:没有验收,生成模型就成了盲人摸象;有了这几项指标,研究者才能公平地比较不同分子图生成方法的优劣,从而真正把 AI 用在新材料发现的流水线上。

Validity=VvalidVtotal,Uniqueness=UuniqueVvalid,Novelty=NnovelUunique\displaystyle \text{Validity}=\frac{V_{\text{valid}}}{V_{\text{total}}},\quad \text{Uniqueness}=\frac{U_{\text{unique}}}{V_{\text{valid}}},\quad \text{Novelty}=\frac{N_{\text{novel}}}{U_{\text{unique}}}
一句话:先看房子倒不倒(有效性),再看是不是千篇一律(唯一性),最后看有没有新意(新颖性)。
  1. 有效性$V_{\text{valid}}$ 是合法分子数,$V_{\text{total}}$ 是生成分子总数,商越高越好。
    Validity=VvalidVtotal\text{Validity}=\frac{V_{\text{valid}}}{V_{\text{total}}}
  2. 唯一性$U_{\text{unique}}$ 是去重后的合法分子数,衡量生成结果有没有“偷懒复读”。
    Uniqueness=UuniqueVvalid\text{Uniqueness}=\frac{U_{\text{unique}}}{V_{\text{valid}}}
  3. 新颖性$N_{\text{novel}}$ 是训练集中没见过的合法且唯一分子数,衡量创造能力。
    Novelty=NnovelUunique\text{Novelty}=\frac{N_{\text{novel}}}{U_{\text{unique}}}

AI 应用场景

场景一:药物先导化合物从头设计

阶段:模型训练 → 生成采样

解决的问题:传统药物化学家只能基于已知化合物做局部修改,搜索效率低。AI 分子图生成可以在图结构空间直接提出全新骨架,再结合活性预测筛选。

具体案例:某团队想设计一款激酶抑制剂,先用已有抑制剂分子图微调自回归生成模型,再生成 10 万个候选分子,通过 GNN 预测活性和毒性,最后只保留 200 个进入湿实验验证,大幅压缩了早期发现周期。

场景二:电池电解质材料快速筛库

阶段:数据准备 → 一次生成 → 规则过滤器

解决的问题:电池电解液的候选溶剂分子空间巨大,逐一实验合成不现实。一次生成模型能以极高速度输出大量分子图,再用化学有效性过滤器剔除超价、不稳定结构。

具体案例:研究人员用一次生成范式生成 5 万个溶剂分子图,先做价键和稳定性规则过滤,再用性质预测模型估算氧化电位和沸点,最终锁定 30 个高潜力候选物送实验测试。

Python 演示

python61 行
# 简化版自回归分子图生成器:原子像乐高,每次加一块并检查插槽from collections import defaultdict VALENCE = {'C': 4, 'N': 3, 'O': 2}  class MolBuilder:    """用价态规则维护一个正在生长的分子图"""     def __init__(self):        self.atoms = []        self.bonds = {}        self.used = []     def add_atom(self, symbol, connect_to):        """symbol 是新原子类型, connect_to 是 [(已有原子下标, 键级)]"""        if symbol not in VALENCE:            raise ValueError("unknown atom: " + symbol)        order_map = defaultdict(int)        for other, order in connect_to:            order_map[other] += order        if sum(order_map.values()) > VALENCE[symbol]:            raise ValueError("too many bonds for new atom")        idx = len(self.atoms)        self.atoms.append(symbol)        self.used.append(0)        for other, order in order_map.items():            if self.used[other] + order > VALENCE[self.atoms[other]]:                self.atoms.pop()                self.used.pop()                raise ValueError("no free valence on neighbor")        for other, order in order_map.items():            self.bonds[(min(idx, other), max(idx, other))] = order            self.used[idx] += order            self.used[other] += order        return idx     def is_valid(self):        for i in range(len(self.atoms)):            if self.used[i] > VALENCE[self.atoms[i]]:                return False        return True     def adjacency(self):        n = len(self.atoms)        A = [[0] * n for _ in range(n)]        for (i, j), order in self.bonds.items():            A[i][j] = order            A[j][i] = order        return A  if __name__ == "__main__":    m = MolBuilder()    c0 = m.add_atom('C', [])    c1 = m.add_atom('C', [(c0, 1)])    n2 = m.add_atom('N', [(c1, 1)])    o3 = m.add_atom('O', [(c0, 1)])    print("atoms:", m.atoms)    print("adjacency:", m.adjacency())    print("valid:", m.is_valid())
目的:用一个极简的价态检查器演示“自回归式分子图生长”——每加一个新原子,都像给乐高城堡新增一块积木,并且随时检查新旧插槽是否超载。
  1. VALENCE = {'C': 4, 'N': 3, 'O': 2}定义每类原子的“插槽容量”,这是化学有效性检查的依据。
  2. order_map = defaultdict(int)先把同一邻居的多根键合并,防止重复占槽被绕过。
  3. if sum(order_map.values()) > VALENCE[symbol]:检查新原子这一侧是否超载。
  4. idx = len(self.atoms)新原子编号等于当前原子列表长度,天然形成顺序生成。
  5. self.bonds[(min(idx, other), max(idx, other))] = order用无序对存边,保证邻接矩阵对称。
  6. return self.used[i] <= VALENCE[self.atoms[i]]最终全图校验,相当于给整座堡垒做验收。

常见误区

误区用语言模型生成 SMILES 字符串,就是在做分子图生成,根本不需要考虑图结构。

正解SMILES 只是分子图的线性编码,容易在括号、环编号等处出错;分子图生成直接在图上决策原子和化学键,天然可以使用节点、边和价态约束。就像用一段文字描述乐高城堡,和直接看连接图搭积木,前者更容易产生歧义。

为何常见:很多入门课程和数据集中都使用 SMILES,导致新手误以为字符串就是分子的本质。

误区训练时损失函数收敛得很好,模型生成的分子应该都是合法结构。

正解生成模型的 loss 衡量的是数据分布拟合程度,并不包含化学硬规则。模型可能会生成“五键碳”这种在化学上不存在的结构;必须显式加入价态掩码或后处理校验,就像搭积木时不能只看造型,还要检查插槽数量。

为何常见:深度学习模型常在“平均表现”上很好,但分子合法性是逐原子硬约束,不能被平均掉。

误区一次生成速度快、并行度高,所以应该全面取代自回归生成。

正解一次生成所有节点和边,局部容易出现价键矛盾,比如两个原子同时抢同一个键位;自回归生成虽然慢,但每步都看着局部图做决策,更容易保证化学合理性。两者更像是“粗筛”和“精修”的关系。

为何常见:人们容易被“快”吸引,却忽略了分子图生成里局部一致性比单纯速度更重要。

误区只要图神经网络足够强,化学价态、官能团规则都可以自动学会,不需要显式校验。

正解GNN 擅长提取结构模式,但生成过程中仍可能产生违反价态规则的结构。优秀的分子图生成系统通常把 GNN 的表示能力和化学规则校验结合起来:GNN 负责“想”,规则器负责“查”。

为何常见:深度学习“端到端”的成功案例很多,让人误以为硬规则可以被完全遗忘。

面试题

Q1. 在分子图生成中,把分子表示成图时,“节点”和“边”分别指什么?

单选题 · easy

  • A.原子和化学键← 正确答案
  • B.分子和官能团
  • C.分子量和极性
  • D.电子和电子云

答案:A。分子图以原子为节点、以化学键为边,就像乐高城堡以积木为节点、以插销咬合为边。官能团、分子量都可以由图推导出来,但不是图的基本元素。

Q2. 图神经网络中“消息传递”的核心思想是什么?

单选题 · easy

  • A.让原子吸收邻居原子信息← 正确答案
  • B.把分子顺序完全颠倒
  • C.让原子随机游走
  • D.把键长全部设为固定值

答案:A。GNN 的核心是每个节点从邻居那里收集信息,再更新自己。这像乐高师傅看周围已砌好的砖来调整手里积木的位置,而不是把积木顺序倒过来或让积木乱跑。

Q3. 自回归图生成每一轮主要做什么?

单选题 · easy

  • A.添加一个新原子及其连接← 正确答案
  • B.一次性生成完整的分子图
  • C.对已有原子按质量排序
  • D.把分子图直接送入模型

答案:A。自回归生成是一块块搭积木的过程:观察当前局部图,预测新原子和它与旧原子的连接,再更新图。一次性生成属于一次生成范式,不是自回归。

Q4. 相比一次生成,自回归图生成的最大优点是什么?

单选题 · mid

  • A.局部连接结构更加合理← 正确答案
  • B.生成速度必然会更快速
  • C.不需要任何原子特征
  • D.无需训练数据即能工作

答案:A。自回归生成每一步都参考已生成的局部图,所以能更好地避免局部键连矛盾。它通常更慢,也需要原子特征和训练数据,速度优势恰恰属于一次生成。

Q5. 化学有效性保证中,“价键上限”指的是什么?

单选题 · mid

  • A.每个原子成键总数不超价态容量← 正确答案
  • B.每个分子只能有一条主链
  • C.模型参数量不能超过一万
  • D.数据集每个类别数量相等

答案:A。价键上限就是原子的“插槽数”,碳最多 4、氮最多 3、氧最多 2。超出就意味着生成了超价分子,是不合法的化学结构。

Q6. 评估生成分子质量时,“新颖性”通常指什么?

单选题 · mid

  • A.训练集未见过有效分子占比← 正确答案
  • B.生成结果中重复分子占比
  • C.生成分子的平均原子数目
  • D.训练数据集的总体规模

答案:A。新颖性衡量模型是否只会“背答案”。如果生成的全部分子都在训练集中出现,即使有效且唯一,也只是记忆而不是创造。

Q7. 在自回归分子图生成中,新原子接在已有分子图的哪个位置通常如何决定?

单选题 · hard

  • A.GNN预测新原子与每个旧原子的连接← 正确答案
  • B.随机选择最重的原子作为接入点
  • C.按SMILES字符顺序从后往前插入
  • D.复制所有原子后取平均位置

答案:A。自回归图生成每一步用 GNN 编码当前局部图,然后预测新原子与图中每个旧原子是否连边、键级是多少。其他选项既不符合图结构,也不符合化学常识。

Q8. 关于一次生成和自回归生成,下列说法正确的有哪些?

多选题 · mid

  • A.一次生成可并行输出所有边← 正确答案
  • B.一次生成更易出现价键失衡← 正确答案
  • C.一次生成不需要任何训练数据
  • D.自回归逐块扩展分子图← 正确答案

答案:ABD。一次生成通过潜变量同时解码所有节点和边,并行度高,但局部容易抢槽,所以更容易出现价键失衡;自回归则逐块扩展,像一块块搭城堡。两者都需要训练数据,C 错误。

Q9. 下列哪些方法能提高生成分子的化学有效性?

多选题 · hard

  • A.生成时掩码超出价态的原子← 正确答案
  • B.生成后运行化学规则校验器← 正确答案
  • C.用字符串长度给分子性质打分
  • D.用化学工具做合法化后处理← 正确答案

答案:ABD。在生成时掩码超价选择、生成后规则校验和化学工具后处理,都能防止“五键碳”出现。字符串长度与化学有效性无关,属于错误做法。

Q10. 关于分子图生成评估指标,下列说法正确的有哪些?

多选题 · mid

  • A.有效性统计合法分子占比← 正确答案
  • B.唯一性衡量生成结果多样性← 正确答案
  • C.新颖性无需与训练集比较
  • D.性质命中率衡量目标属性优化← 正确答案

答案:ABD。有效性是合格率,唯一性看去重后还剩多少,性质命中率看目标属性是否达标。新颖性恰恰需要把生成结果与训练集比较,所以 C 错误,其余正确。