第2章 分子表示方法:SMILES、图表示、3D坐标
做分子生成,选对表示方式,就等于选对了“赛道”。不同的表示方式,直接决定了你的模型结构和损失函数该怎么设计。我是从SMILES入门的,后来被图表示虐过,最近又在折腾3D坐标。每种方式都有它的脾气。今天咱们就掰开揉碎聊聊。
2.1 SMILES表示与损失函数
SMILES说白了就是用一串字符来描述分子结构。比如苯就是 c1ccccc1,乙醇就是 CCO。你想想看,这本质上就是个序列生成问题。很多早期的分子生成模型,直接把分子当成"化学式的句子"来处理。损失函数嘛,自然就用了NLP里那套。
核心损失函数:交叉熵损失(Cross-Entropy Loss)
给定真实SMILES序列 y = [y₁, y₂, ..., y_T] 和模型预测的概率分布 p(y_t|y<t),单步损失为:
L = - Σ_{t=1}^{T} log p(y_t | y_<t)
整句话的损失就是所有token损失之和。
我在项目里踩过一个坑:SMILES序列长度差异巨大。像阿斯匹林才20几个字符,一些大环化合物能到上百。如果你用固定长度padding,空白处也是损失计算的一部分。嗯,这里要注意——空白填充会引入噪声,我建议用mask机制把padding位置排除掉。代码实现时加个注意力掩码就行。
# 伪代码:带mask的交叉熵损失
loss = F.cross_entropy(predictions, targets, reduction='none')
loss = loss * mask # mask: 有效位置为1,padding为0
loss = loss.sum() / mask.sum()
技巧:SMILES损失还可以结合策略梯度(Policy Gradient),尤其是在强化学习场景下。比如你想让生成的分子满足某些性质(LogP、QED),可以用性质得分作为奖励,损失函数改为:
L_reinforce = - R * log p(y|θ)
R是奖励值,p是生成概率。我在做先导化合物优化时,直接拿这项替换纯交叉熵,效果立竿见影。
2.2 图表示与损失函数
SMILES的序列视角有一个致命问题:化学结构本质是图,不是线性序列。两个在SMILES上距离很远的原子,在图里可能紧挨着(比如环上的邻位关系)。所以后来大家开始用分子图——节点是原子,边是化学键。这就意味着损失函数要处理拓扑结构。
图表示下有两种主流损失设计方向:
- 逐节点/逐边预测损失:把生成看成一步步添加原子和键。损失函数用交叉熵或者负对数似然,但计算时需要按图拓扑对齐。
- 图编辑距离损失:生成整张图后,计算生成图与目标图的编辑距离(节点插入/删除/替换、边操作)。这个损失很难做梯度下降,通常配合对比学习或者VAE框架使用。
避坑指南:我刚开始做图生成时,直接套用了图神经网络(GNN)分类任务的损失——节点分类交叉熵。结果模型生成出来的分子化学上根本不合理,比如出现一个碳连四个单键再连一个氧。后来才意识到:图生成不仅要预测节点类型,还要预测边类型,而且每个节点的度必须满足化学规则。损失函数必须包含化学有效性约束。
我习惯把图生成损失拆成三块:
L_graph = L_node + L_edge + L_validity
其中:
L_node = - Σ_i Σ_k y_ik log p_ik # 节点类型预测
L_edge = - Σ_{i,j} Σ_m e_ijm log p_ijm # 边类型预测
L_validity = penalty(违反化学规则的程度) # 软约束
有人说加惩罚项会降低模型探索性。说实话,我觉得初始阶段加一点惩罚项能帮你快速收敛到合理空间,后期再逐渐减小惩罚系数。
2.3 3D坐标表示与损失函数
如果SMILES是“怎么拼”,图是“怎么连”,那3D坐标就是“怎么摆”。对于需要对接、构象分析的场景,你得直接生成原子的三维空间位置。这就涉及到连续坐标的回归问题。
3D生成损失通常包含两部分:
- 坐标回归损失:MSE或Huber损失,对比生成坐标与真实坐标。
- 距离矩阵损失:保证生成的分子内部几何关系合理(键长、键角、二面角)。
我参与过一个蛋白质-配体对接生成的项目,当时用纯MSE损失训模型,生成出来的分子坐标基本都对上了,但键长严重偏离——有些C-C单键居然只有0.8 Å。后来加了拉普拉斯损失(Laplacian loss)做平滑约束才好转。
常见3D损失组合示例:
L_coord = MSE(x_pred, x_target) # 坐标直接回归
L_dist = MSE(D_pred, D_target) # 距离矩阵损失
L_angle = MSE(angle_pred, angle_target) # 角度损失(可选)
L_3D = L_coord + λ₁ * L_dist + λ₂ * L_angle
λ₁和λ₂是超参数,我一般用0.1和0.05起步。
小技巧:当坐标空间很大时(比如数百个原子),MSE容易受整体平移影响。建议先做对齐(alignment):对生成坐标和真实坐标做质心对齐后再计算损失。我通常用Kabsch算法。
2.4 不同表示的对比与选择
为了帮你快速做决策,我列个对比表:
| 表示方式 | 数据结构 | 代表性损失函数 | 适用场景 | 我的建议 |
|---|---|---|---|---|
| SMILES | 序列 | 交叉熵、策略梯度 | 快速探索、大规模虚拟筛选 | 简单粗暴但丢失拓扑信息 |
| 分子图 | 图(节点+边) | 节点/边分类损失、图编辑距离 | 需要保持结构合理性、逆向设计 | 适合大部分生成任务 |
| 3D坐标 | 连续空间点集 | MSE、Huber、距离矩阵损失 | 对接、构象采样、药物设计 | 计算成本高,但精度上限高 |
| 混合表示 | 图文结合等 | 加权组合损失 | 多目标优化、跨模态生成 | 调参复杂,非必要不用 |
我个人习惯是:先看任务,再选表示,最后设计损失。不需要上来就搞最复杂的3D,很多分子生成问题用图表示就足够了。我记得有一次给客户做先导优化,他们非要上3D,结果数据量不够,坐标回归总是过拟合。换回图表示+对比学习,效果反而更好。
最后提醒一句:别把损失函数当成万能药。如果你的表示方式本身就丢失了关键化学信息(比如SMILES不考虑环的柔性),再怎么调损失函数也救不回来。选表示时,就想清楚——你的损失函数到底在惩罚什么?