1. 先厘清动态对接到底在评什么蛋白-小分子动态对接说白了就是让配体在口袋里找一个位置的同时允许口袋自己也在动。这件事在真实药物发现里几乎是默认前提——很多靶点的 apo 结构和 holo 结构口袋形状差得离谱侧链翻个身、loop 让个位配体才有地方坐。静态对接把受体当成一块冻住的石头配体怎么摆都撞墙最后打分函数再准也救不回来。等变几何扩散模型这类思路核心就是用生成模型同时采样配体姿态和口袋构象让两者在去噪过程里互相迁就本质上是在学一个联合分布而不是解一个固定能量面的最优化问题。DynamicBind 就是这条路线里比较有代表性的一类实现值得单独拉出来做一次评测。这篇东西写给两类人一类是想把这类模型接进自己流程、需要知道它到底在什么条件下靠谱、什么条件下会翻车的人另一类是正在做类似方法、想搞清楚评测口径怎么定才不至于自欺欺人的人。我不会去复述方法原文而是从我拿到一个待评测的模型怎么设计一套能藏不住问题的评测、怎么跑、跑完怎么读数字这个角度来写。中间会穿插参数选择、显存与时间预算、以及几个我实际踩过的坑。术语会尽量说人话但不是科普向默认你至少跑过分子对接、知道 RMSD 是什么。评测这类模型最容易犯的错是把生成得好看当成对接得对。扩散模型天生会生成物理上看着挺像样的构象但口袋是不是真的移动到了正确位置、配体是不是真的落在结合模式上是两件完全不同的事。所以整套评测必须拆成三层来看配体姿态准不准、口袋构象合不合理、两者放在一起是否自洽。这三层任何一层塌了Top-1 成功率再高也只是数字游戏。1.1 静态对接的失效点在哪里静态对接的失效不是精度问题是自由度问题。当受体被固定成单一构象搜索空间里根本不存在正确解这时候你调采样密度、换打分函数、加大搜索次数都是在错误的解空间里做更精细的搜索。典型的三种塌陷场景一是侧链位阻关键残基的侧链在 apo 里正好堵住口袋入口配体进不去二是口袋闭合apo 状态下口袋是张开甚至半开放的holo 结合后 loop 收拢静态对接会把配体放到一个实际上不存在的空腔里三是水介导的氢键网络重排这个更难因为连显式水都没建模。我一般会用一个小判据快速判断一个靶点值不值得上动态方法把 apo 和 holo 的骨架叠合后计算口袋残基比如配体 8 Å 范围内的残基的 Cα RMSD 和侧链重原子 RMSD。如果 Cα RMSD 超过 1.5 Å或者有 2 个以上关键侧链重原子位移超过 2.5 Å静态对接基本不用指望了。这个判据不需要任何模型几分钟就能算完能帮你省掉大量无效实验。1.2 等变几何扩散在这里承担的角色等变equivariance不是玄学它是一个很强的归纳偏置分子在空间里整体旋转平移物理结果不该变那模型内部的特征变换也应该跟着一起转。实现上就是把节点特征限制在标量不变和向量等变两类消息传递时向量部分跟着坐标变换走。好处是模型不需要从数据里学会旋转不变性样本效率高、外推稳。对于对接这种对几何精度极敏感的任务这个性质几乎是必需品——你要是用一个普通 GNN 去回归坐标光是坐标系对齐就够喝一壶。扩散部分负责的是多模态采样。对接的正确解往往不止一个而且口袋构象本身就是一个分布。用扩散模型去建模这个联合分布采样时从噪声出发一步步去噪每一步都在配体往哪挪和口袋怎么收之间做联合决策。这一步的直觉类比是不是把球扔进一个固定形状的盒子里而是球和盒子一起被捏最后捏成互相契合的样子。1.3 评测必须回答的三个问题我在设计任何一次这类评测时都会先把问题钉死否则跑完一堆数字也不知道该说什么。第一个问题给定 apo 口袋模型能不能把配体放回共晶位置阈值取 2 Å。这是最基本的能力线。第二个问题模型采样出来的口袋构象和真实 holo 口袋的偏离有多大同时这些构象本身是不是物理上站得住。第三个问题模型自己给的置信度分数能不能把好样本排到前面以及这个分数和真实结合亲和力有没有相关性。这三个问题对应三套指标不能混着看。2. 方法骨架拆解它凭什么能同时动配体和口袋要评一个模型得先知道它的能力边界从哪来。这套方法的结构可以拆成四块复合物图表示、SE(3) 上的前向加噪、联合去噪网络、置信度头。每一块的设计选择都直接决定了评测时该盯哪些指标。2.1 表示层把复合物塞进一张等变图配体侧一般按原子建图节点是重原子氢通常隐式处理或者只在后处理补节点特征包括元素类型、杂化、芳香性、电荷、是否在环上边按共价键加上距离截断构造键类型作为边特征。蛋白侧不会按全原子建那样节点数爆炸常见做法是残基级图每个残基一个节点位置取 Cα 或者骨架原子集合特征包括残基类型、二级结构、相对溶剂可及性。两侧之间用一个跨图的消息传递通道连接空间上按距离阈值比如 8~10 Å建立配体原子—残基边。这里有一个容易被忽略的细节口袋中心怎么定义。做法不同采样起点的分布就不同直接影响成功率。常见三种配体质心需要先知道配体大致位置、口袋残基几何中心、以及基于预测的 pocket 检测给出一个概率中心。做 apo 评测时如果你用 holo 配体位置来定义口袋中心那就是信息泄漏成功率会虚高一大截这一点必须在评测协议里写死并且检查。注意口袋中心定义是这类评测里最隐蔽的泄漏源之一。任何用到 holo 配体坐标来确定盒子位置、初始噪声尺度、或者候选筛选范围的操作都要在协议里显式声明或直接禁止。2.2 加噪与去噪SE(3) 上的前向过程怎么设计前向过程对配体坐标加各向同性高斯噪声噪声尺度按一个预设的 schedule 从 0 递增到某个上限对蛋白侧通常是给骨架坐标或者主链 torsion 加一个幅度更小的扰动。配体和口袋的噪声尺度不应该一样因为口袋的柔性远小于配体的平动自由度如果给口袋加同等量级的噪声训练时模型会学到口袋可以随便飘采样出来的构象就散了。我的经验是口袋侧的噪声上限设在配体侧的 1/3 到 1/2 之间比较稳。去噪网络就是那个等变 GNN输入带噪坐标和当前时间步输出预测的噪声或者直接预测干净坐标。时间步的编码一般用正弦位置编码加上一个标量特征拼接。采样时从纯噪声或者从先验分布出发用 DDIM 类加速采样器步数通常在 20 到 40 之间。步数再往上加收益急剧衰减——我实测过 20 步和 50 步的 Top-1 差异大概只有 1 到 2 个百分点但耗时翻了一倍多。# 采样配置示例参数为实践中较稳的一组 sampling: num_steps: 30 # 20~40 之间30 是精度/耗时的平衡点 num_samples: 40 # 每个口袋生成的构象数 ligand_noise_scale: 1.0 pocket_noise_scale: 0.4 pocket_center: residue_centroid # 禁止使用 holo 配体坐标 box_size: 22.5 # 单位 Å边长的立方体 seed: 202401012.3 口袋先验与采样apo 输入怎么长出 holo 口袋这是整套方法里最容易被质疑的一环。apo 结构里没有配体口袋可能没有闭合模型要做的其实是从 apo 出发采样出一个配体可结合的构象集合。如果训练时见过大量 apo-holo 配对模型学到的其实是一个条件分布如果只在 holo 上训练那它对 apo 输入的外推能力就要打问号评测时必须单独拉一个 apo 子集出来看。我建议在评测里明确区分三种输入条件holo 口袋上界参考、apo 口袋真实使用场景、以及加了人工扰动的口袋比如对 holo 结构的主链做 1 Å 的随机扰动用来测鲁棒性。第三种条件是最能暴露问题的很多模型在干净 holo 上成功率很高一旦主链扰一点点成功率就断崖式下跌这类结果在论文表格里往往看不到。2.4 置信度头样本排序与亲和力信号生成式方法必须解决从 40 个样本里选哪个的问题。置信度头通常是一个在生成样本上训练的判别式网络输入复合物结构输出一个标量训练标签是样本和真实结构的 RMSD劣化为二分类或者回归。评价这个头好不好看的是排序能力而不是绝对数值Top-1 相对随机选能提升多少Top-5 到 Top-1 的落差有多大。亲和力预测是另一回事。同一个网络或者另一个头输出的分数如果想拿去做亲和力相关性那评测就得用带实验亲和力标注的子集算 Pearson 和 Spearman。我的态度比较保守这类模型的亲和力信号更多是有用的辅助排序特征直接当打分函数用来做虚拟筛选排序需要非常谨慎地验证尤其是跨靶点家族的泛化。3. 评测方案设计指标、数据与基线方案设计这一块决定了整篇文章的可信度。我的原则是数据集切分按相似性做指标分层给基线至少三类消融至少做三个。3.1 数据切分与难度分层拿一个公开的蛋白-配体共晶复合物集合先做几步清洗去掉含金属离子、共价配体、大于某个重原子数上限比如 60 个重原子的条目去掉分辨率差于 2.5 Å 的结构去掉配体有严重空间冲突的。剩下的大概几千条量级。切分不能随机切要按蛋白序列相似性聚类切保证测试集里的靶点和训练集相似度低于某个阈值常用的 30% 或者 40% 序列一致性。同时再按时间切一刀比如把较晚释放的结构整体留出测一个时间外推。这两刀切完测试集规模通常在几百条。难度分层我一般按三个维度打标签口袋柔性apo-holo 的 Cα RMSD 分档1 Å、1~2 Å、2 Å、配体柔性可旋转键数分档4、4~8、8、以及口袋的疏水/极性比例。分层报告比一个总体平均值有价值得多因为总体平均会被大量简单样本拉高。3.2 指标体系指标定义要点阈值/口径看什么配体 RMSD 成功率重原子对称校正后的 RMSD2 Å 为主1 Å 为严基本能力线口袋 Cα RMSD口袋残基叠合后的骨架偏差2 Å构象采样质量联合成功率配体与口袋同时达标2 Å / 2 Å真正的动态对接能力置信度排序Top-1/随机、Top-5 命中率—排序头有效性物理合理性键长键角偏离、手性、冲突数冲突 0.4 个/千 ų生成质量底线构象多样性样本两两 RMSD 分布—是否塌缩亲和力相关性Pearson / Spearman—辅助信号强弱这张表里我最看重联合成功率因为它最接近真实使用场景也最难刷。单独报配体 RMSD 而回避口袋 RMSD基本可以判定为在藏东西。3.3 基线与消融设置基线至少三类。第一类是传统对接加打分重排固定受体这是下限。第二类是共折叠类方法输入端同时给序列和配体输出复合物结构它本质上是预测而不是采样但在很多靶点上表现相当强。第三类是固定口袋的扩散模型也就是把口袋冻住只扩散配体用来隔离出口袋柔性这一项带来的增益。消融要做的三个去掉口袋侧加噪相当于退化成固定口袋、把等变结构换成普通 GNN 加数据增强、以及把置信度头换成随机选。第三个消融经常被忽略但它能直接告诉你排序头到底值不值这些算力。4. 实操流程从环境到一次完整评测下面这一段是可以直接照着跑的流程。我把目录结构、预处理、推理、后处理拆开写每一步都说明为什么这么做。4.1 环境与依赖环境上没什么特别的坑主流深度学习框架加一个化学信息学工具包处理配体读入、质子化、对称匹配就够。建议把几何计算和模型推理分成两个独立环境因为化学信息学包的依赖经常和框架的 CUDA 版本打架。我吃过一次亏升级框架之后化学包底层的编译依赖挂了导致所有配体读进来键级全是错的RMSD 算出来一片 8 Å 以上排查了两个小时才发现是解析层的问题。# 目录结构建议 dyn_eval/ ├── data/ # 原始结构、清洗后结构、切分文件 ├── prep/ # 预处理脚本与中间产物 ├── configs/ # 采样与评测配置 ├── runs/ # 每次评测的输出 └── reports/ # 汇总表格与图4.2 输入准备与预处理清单这一步的细节决定了后面所有数字的可比性。我的清单是这样的蛋白只保留目标链和必要辅因子去掉水除非方法显式建模水补全缺失侧链但缺失 loop 不要强行补宁可在指标计算时排除这些区域否则补出来的 loop 会把口袋 RMSD 算歪。质子化按 pH 7 处理组氨酸的质子化态按局部氢键环境判断这一步很关键搞错一个 His 的朝向口袋形状和氢键网络都会变。配体从共晶里抽出来保留重原子记录原始 SMILES 用于后续对称匹配和手性检查。注意配体在晶体里的构象可能被结晶 packing 影响评测时以它为真值是有争议的但作为统一下限是可以接受的。口袋定义以 apo 结构上的口袋残基集合为准配体 8 Å 内的残基作为口袋。注意 apo 结构上做这个选择时不能使用 holo 配体位置如果 apo 口袋不明显用几何检测或者保守的残基集合。提示配体抽出来后一定要做一次回到原位的自检——把抽出的配体放回原结构算一次 RMSD应该是 0。如果这一步不为 0说明解析或坐标变换出了问题后面全是废数据。4.3 推理参数与一次完整运行采样数和步数是两个最直接的成本旋钮。我的建议是先在小规模子集比如 50 条上做一次参数扫描把num_samples在 10、20、40、80 上扫一遍看 Top-1 的边际收益在哪里掉下来。经验上 40 附近是一个拐点从 10 到 40Top-1 通常能提升 8 到 15 个百分点从 40 到 80往往只有 2 到 4 个百分点耗时却翻倍。# 单条样本推理示意 python run_dock.py \ --config configs/sample_30step.yaml \ --protein prep/xxx_pocket.pdb \ --ligand prep/xxx_ligand.sdf \ --pocket_residues prep/xxx_pocket_res.txt \ --out runs/case_xxx/ \ --num_samples 40 \ --num_steps 30 \ --seed 20240101跑完之后每个 case 目录下会有 40 个复合物结构和一个打分表。打分表至少包含样本序号、置信度分、配体重原子数、最小蛋白-配体距离、内部冲突计数。4.4 时间与显存账以一个 30 残基的口袋、30 重原子配体为例单次去噪前向在常见数据中心级 GPU 上大约几十毫秒量级30 步加 40 个样本单条 case 大概在 40 秒到 90 秒之间取决于实现细节和批处理程度。显存占用主要被样本数和图规模吃40 个样本一起批量采样时显存会比单样本高一个量级如果显存吃紧把样本数分两批跑总耗时只增加一点点。按 300 条测试集算全量跑一遍大概需要 4 到 8 个 GPU 小时。这个成本是可以接受的所以我很反对在评测里只跑 20 个样本就下结论——多跑一倍的样本只要多花几个小时却能显著降低结论的不确定性。5. 结果解读数字背后的门道数字出来之后怎么读比怎么算更重要。下面是我在几轮评测里总结出的几条判读经验。5.1 Top-1 与 Top-N 的落差说明什么如果 Top-40 里有正确答案、但 Top-1 选错了问题出在置信度头不在生成器。这种情况下继续优化生成模型是南辕北辙应该去看排序头的训练标签和特征。反过来如果 Top-40 里压根没有 2 Å 以内的样本那是生成器的采样覆盖问题可能是噪声尺度设小了采样走不出局部、也可能是口袋先验给错了。一个实用的诊断把每个 case 的最优样本 RMSD和Top-1 样本 RMSD画散点。散点贴着对角线说明排序头很好散点在对角线上方形成一条水平带说明生成器有能力但排序头失效散点整体右移说明生成器本身不行。5.2 配体 RMSD 与口袋 RMSD 的耦合这两者不是独立的。我观察到的一个规律是当口袋 RMSD 超过 2.5 Å 时配体 RMSD 分布会明显右移但如果口袋 RMSD 在 1 到 2 Å 之间配体精度和口袋偏差几乎不相关。这说明存在一个容忍窗口口袋只要大致对配体还能靠局部调整落位一旦超出窗口配体就被带着一起跑偏。这个规律对实践有直接意义如果你只关心配体姿态没必要追求口袋的极致精度把口袋 RMSD 控在 2 Å 以内就够了。但如果你要做的是基于口袋构象的下游任务比如共价抑制剂设计、变构口袋发现那口袋精度就是主要矛盾。5.3 物理合理性生成式方法的老毛病扩散模型生成的构象RMSD 可以很好但物理上不一定站得住。我见过最典型的三类问题一是芳香环被生成为非平面环内二面角偏十几度二是手性中心翻转尤其是季碳三是配体与蛋白出现轻微穿插最小距离小于 2 Å 但又不算严重冲突打分表上不报警可视化时才发现。所以物理合理性检查必须是评测的固定项不能当可选项。检查项至少包括键长键角相对标准值的偏离、环平面性、手性一致性、蛋白-配体重原子最小距离分布、以及配体内部的原子重叠。这几项做下来能筛掉一批看起来很美的样本。5.4 多样性不是越高越好生成式方法的卖点之一是能给出构象集合但多样性本身不是目标。如果 40 个样本两两 RMSD 都在 5 Å 以上说明模型根本没收敛到一个结合模式是在乱撒。合理的多样性应该是大部分样本聚在少数几个模式附近模式之间有明确区分。我一般会算一个简单指标把样本按 2 Å 阈值做聚类看最大簇占比。最大簇占比在 50% 到 80% 之间比较健康低于 30% 说明散得太厉害。6. 常见问题与排查实录这一节是我实际踩过的坑按现象—原因—处理整理。建议收藏真出问题的时候比翻文档快。6.1 成功率异常低的排查顺序先查数据再查模型最后查指标。数据层配体是否读错键级、质子化、口袋残基列表是否为空或错位、蛋白链 ID 是否对得上。模型层口袋中心是否落在配体实际位置附近可以画个图看、采样步数是否被配置文件覆盖、随机种子是否导致某批样本全崩。指标层对称匹配是否生效、是否误把氢算进 RMSD、是否用了不同的原子命名映射。我遇到过最隐蔽的一次是原子命名映射错了配体从 SDF 转格式时原子顺序变了但真值文件没跟着更新结果所有 RMSD 都在 6 Å 以上看着像模型完全失效实际上是指标算错。所以任何一次评测我都会先跑 5 条必过样本就是训练集里的、模型肯定见过的如果这 5 条都不过先怀疑流程而不是模型。6.2 口袋飞了的几种典型表现第一种口袋整体平移所有残基一起挪了几埃配体跟着挪。这通常是口袋中心的定义或者坐标系对齐出了问题。第二种口袋局部塌陷loop 区域塌进配体本该占据的空间配体被挤到口袋边缘。这多半是训练时口袋噪声尺度太小、模型没见过大口径构象变化。第三种口袋没动但配体穿模这是固定口袋扩散的典型症状说明口袋柔性模块没起作用。6.3 手性与对称匹配踩坑RMSD 计算里的对称匹配是必须做的苯环、羧基、磷酸基这些对称基团不做匹配RMSD 会平白多出 1 到 2 Å。但对称匹配做过头也会出问题某些情况下匹配算法会把构象翻转的样本救回来掩盖了手性错误。我的做法是分开算两个数一个做对称匹配的 RMSD衡量姿态一个不做匹配但检查手性的布尔值衡量化学正确性两个都看。6.4 显存与耗时优化如果显存不够优先降样本数而不是降步数。步数降到 15 以下采样质量下降很明显样本数降到 20只是统计上噪声大一点。另外一个技巧是把口袋图的构建结果缓存下来因为同一个口袋在 40 个样本里是共享的重复构图会浪费大量时间。我做过一次 profiling发现在某些实现里图构建占了总耗时的三成以上。7. 我在几轮评测里攒下的几点体会第一评测协议要写在跑之前而且要写死。我见过太多情况是跑完之后发现某个指标不好看就换个阈值或者换个口径最后数字漂亮了但结论没法用。把口径固定下来把不好的结果也报出来这才是一次有价值的评测。第二apo 场景才是这类方法的真正考场。holo 口袋上刷高分意义有限因为静态对接在 holo 上本来就不差。真正能体现动态对接价值的是那些 apo-holo 口袋差异大、静态方法明确失效的靶点。建议单独拉一个高柔性口袋子集专门汇报。第三物理合理性检查不要省。生成式方法的短板往往不在精度而在化学正确性一个手性翻转的分子在 RMSD 上可能只差 0.8 Å但这种结构拿去做后续设计是灾难性的。第四置信度分不要当亲和力用。这两个东西在训练目标上就不一样把一个排序用的分数直接拿去排序化合物库很容易得到一堆高亲和的假阳性。如果确实要用至少先在带实验标注的独立集合上验证一遍相关性。第五多做几个种子的重复实验。扩散采样的随机性不小单次跑出来的成功率抖动 2 到 3 个百分点很常见。三个种子取均值再报成本不高可信度高很多。最后分享一个我觉得挺实用的小习惯每跑完一个 case把 Top-1 样本和一个随机样本叠合到真值结构上出两张图放进同一个目录。眼睛看一遍比看十个指标都快——很多时候问题一眼就能看出来比如配体整个翻了个面、或者口袋的某个 helix 明显歪了。指标是给你量化用的不是给你判断用的。