如果你接触过组合药物筛选,大概率见过那种让人头皮发麻的画面:几十种单药按两两组合排进 384 孔板,每个组合还要叠几个剂量梯度,最后铺出几十块板子。等到测完、导出结果,真正有协同效应的组合可能只有个位数。这个问题有没有更聪明的解法?ScreenShot 这个项目,从论文标题看给了一个很明确的方向:用 Foundation Model 的思路,把组合药物筛选当成 Few-Shot 任务来解。说白了就是——不指望一次把所有组合测完,而是先用足够多的历史筛选数据训练一个通用模型;到了新细胞系、新药物组合场景,只需要喂给它极少量的实验结果,它就能把剩下的大量组合排出一个靠谱的优先级。
这个思路背后有一个值得反复琢磨的判断。组合筛选领域的核心矛盾从来不是“模型不够强”,而是“实验数据太少、太贵、太碎”。单药、双药、三药组合,配合不同剂量和细胞环境,组合空间是指数级扩张的,而湿实验能覆盖的样本量却受成本、时间和人力限制。ScreenShot 这类工作真正要解决的,不是“给你全部数据然后预测得更准”,而是“在只有少量样本的新任务上,如何把历史数据攒下来的知识真正用起来”。
1. 为什么组合药物筛选天生就是少样本问题
组合药物筛选远不是“A 药加 B 药”这么简单。两个药放在一起,可能协同、可能拮抗、可能效果只是单药相加,甚至可能因为代谢通路抵消,出现比单药更差的情况。更麻烦的是,同一个组合在不同细胞系、不同剂量配比、不同时间窗口下的结论可能完全不同。这些因素叠加在一起,让组合筛选成为一个典型的高维、稀疏、强交互问题。
1.1 组合爆炸:规模决定了你不可能全量测完
算一笔很粗的账。假设一个实验室有 100 个候选单药,两两组合就是 4950 对;如果每种组合还要测 5 个剂量配比,就是接近 2.5 万个实验条件;如果再考虑三个药的组合,数量会直接跳到百万级别。这个规模,即使有自动化液体工作站和高内涵筛选平台,也很难全量覆盖。
这就是组合爆炸。它带来的直接后果是:在绝大多数真实项目里,你永远无法通过“把所有组合都测一遍”来得到完整答案。任何现实可行的方案,都必须在一部分没有测过的组合空间里做推断。这种推断能力,恰好就是机器学习模型的价值所在。
1.2 已有数据极其不均匀
另一个容易被忽视的现实是:即使把历史数据汇总起来,数据本身也极其不均匀。公开数据库里,有些经典药物组合被反复验证过很多次,有些新药只有零星的单药数据;同一对组合在不同实验室、不同批次里的读数还会有明显波动。这种不均匀,会让“一个大模型把全部数据吞进去,然后做全局拟合”的做法很容易翻车。
如果模型只学会记住高频出现的组合,那它对低频但真正有价值的组合几乎无能为力。而药物筛选里最有价值的发现,往往恰恰出现在那些少有人试过的组合里。
1.3 新任务里,少样本才是常态
更贴近实际的是,真正到了一个新任务——比如拿到一个病人来源的类器官模型,或者一个新药进入管线需要做组合评估——实验室通常只能承担有限的验证实验。这就是 Few-Shot 的真实语境:支持集可能只有十几到几十个组合的实测结果,你却要预测后面几千甚至几万个组合。
如果只记住一句话,那应该是:组合药物筛选的核心矛盾不是“预测精度不够”,而是“数据预算永远不够”。谁能在极少量实验数据下给出更可靠的优先级,谁就能把有限的实验资源用在刀刃上。
2. ScreenShot 的设计逻辑:先验、适配、复用
从标题的关键词组合来看,ScreenShot 把 Foundation Model 和 Few-Shot 放在一起,并不是随意的拼凑,而是体现了三种研究思路的交汇。
2.1 为什么需要基础模型
传统机器学习做组合预测,通常是在一个固定的数据集上训练,然后在这个数据集范围内测试。问题是,换一个细胞系、换一个药物家族,模型往往要重新训练。基础模型的核心价值在预训练阶段:它用大量药物结构、细胞系特征、历史筛选结果,学习出一套通用的表征,让不同药物、不同细胞系在同一个向量空间里具有可比性。
你可以把这一步理解成“先建立一套公共语言”。后续的每一个新任务,都不再是从零开始解释药物是什么、细胞系是什么,而是基于这套公共语言去刻画“这个具体场景下的组合行为”。没有预训练,少样本预测基本无从谈起。
2.2 Few-Shot 的实质:不是少样本乱猜
Few-Shot 不等于“样本少所以靠猜”。在常见的研究设定里,它指的是模型在预训练阶段见过大量任务,比如很多个细胞系上的筛选结果;到了测试阶段,只给少量标注样本,模型要通过这些少量样本快速识别当前任务的特殊性,并把预训练积累的知识迁移过来。
这和经验丰富的药理学家做实验的认知方式很像。老手看到一个陌生细胞系,不会把几万种组合全测一遍,而是先根据历史经验选十几个有代表性的组合,快速判断这个体系的药敏特征和耐药机制,再决定下一步怎么排查。Few-Shot 模型本质上是在把这条人类经验流程自动化。
2.3 为什么叫“ScreenShot”
项目名本身是一个值得玩味的双关。一方面,它对应 Few-Shot 里的 “Shot”;另一方面,“截屏”这个动作也很有意思——只取当前任务的一小段画面,而不是全量快照。这个命名其实点出了核心思想:用极小的成本记录当前场景的关键特征,剩下的交给先验知识去补全。
当然,这只是从命名角度做的推测。具体实现里它究竟用的是元学习、预训练加微调,还是类似上下文学习的方式,要以论文原文的实现为准。但这个命名至少说明,作者想强调的不是“海量数据堆模型”,而是“少量数据 + 强先验”的效率路线。
3. 一个可以照着走的最小落地流程
不管 ScreenShot 的具体实现是什么,这类模型要落地,通常都离不开下面几个环节。这里给出一套通用的处理框架,你可以把它当成一份工作流模板来用。
3.1 数据准备:先想清楚输入和标签
组合药物筛选模型的数据,通常包含四类信息:
| 数据类型 | 常见内容 | 常见格式 |
|---|---|---|
| 药物结构 | 分子指纹或 SMILES 序列 | Morgan 指纹、ECFP、SMILES |
| 细胞系信息 | 基因组、表达谱、组织来源 | 基因表达矩阵、突变标签 |
| 组合条件 | 单药浓度、配比、给药顺序 | 剂量梯度矩阵 |
| 标签 | 协同/拮抗/加和 | Loewe、Bliss、ZIP、HSA 得分 |
这里最关键的不是模型结构,而是标签的定义。不同协同分数定义对“协同”的判定标准完全不同,同一份剂量反应数据算出来的分数可能差异很大。如果你从多个来源收集数据,务必先统一标签口径,否则模型学到的东西很可能是噪声。
3.2 药物表征:从结构到向量
最常见的做法是用分子指纹或从 SMILES 预训练的分子向量编码器。如果只做组合预测,也可以直接把两个药物的表征拼接起来,再叠加上细胞系特征。下面是一个很常见的特征拼接写法,目的是先把样本向量组织起来:
import numpy as np def build_sample(drug1_fp, drug2_fp, cell_fp): # 特征拼接后,后续可以做归一化或降维 return np.concatenate([drug1_fp, drug2_fp, cell_fp])这部分真正的工程难点不是向量化,而是特征对齐:不同数据源里同一个药物的命名、结构表示是否一致,一定要先归一化。否则同一个药在不同批次里可能会被编码成两个完全不同的向量。
3.3 少样本适配:先跑通一条最小链路
在实际项目里,我建议按这个顺序跑通一遍:
- 选一个公开数据集,划分出预训练任务和测试任务。
- 在预训练任务上训练基础模型,确保它在“看过”的任务上有基本能力。
- 构造少样本测试:对目标细胞系,只随机抽取 10~20 个已知组合作为支持集,让模型做适配。
- 在剩余组合上评估排序效果,看真正协同的组合有没有被排到前面。
- 和普通深度模型、梯度提升树等基线做对比,确认少样本适配确实带来了增益。
注意:第一次验证不要把支持集数量设得太大。Few-Shot 的意义在于“少”,如果你用了 50% 的数据做支持集,那评估出来的不是少样本能力,而是半个有监督学习的效果。
3.4 评估指标:别只盯着准确率
在这个场景里,最实用的评估指标往往不是准确率,而是排序质量。因为实际使用中,你关心的是“哪些组合值得优先做实验”,而不是把所有组合的分数都精确预测出来。
| 指标 | 回答的问题 | 适合场景 |
|---|---|---|
| Top-K 命中率 | 排名前 K 里有多少真协同 | 实验预算有限,只看头部 |
| AUPRC | 正例稀少时模型的区分能力 | 协同组合稀疏时 |
| Spearman 相关 | 预测分数和真实分数是否同序 | 需要连续剂量排序时 |
一个简单的 Top-K 命中率计算示例:
def top_k_hit_rate(scores, true_labels, k=20): idx = sorted(range(len(scores)), key=lambda i: scores[i], reverse=True)[:k] hits = sum(true_labels[i] for i in idx) return hits / k注意这里 K 的选择应该由实验预算决定。如果一次实验最多验证 20 个组合,那 K=20 就代表“模型推荐的 20 个里有多少值得做”。
4. 落地时最容易踩的坑和排查链路
这类项目做多了会发现,模型效果不好,很多时候不是模型本身的问题,而是前面的数据处理和验证设计出了问题。把这些坑提前列出来,能省下大量返工时间。
4.1 数据层面的坑
- 标签口径不一致:不同数据库、不同批次用了不同的协同计算方式,直接混训等于引入噪声。
- 剂量缺失:有些组合只给了单一浓度结果,无法计算完整的剂量反应曲线。
- 批次效应:同一细胞系在不同实验室的数据分布差异很大,模型可能学到的是实验室偏好,而不是生物学规律。
- 数据泄漏:预训练和测试数据里存在同药或同细胞系的重叠,会让评估结果虚高。
4.2 模型层面的坑
- 过拟合支持集:Few-Shot 适配阶段如果更新轮数太多、学习率太大,模型会把少量样本背下来,失去泛化能力。
- 基线太弱:有些工作只对比了不经过预训练的复杂模型,却没有对比“直接在新任务上用少量数据训练一个简单模型”的基线。在少样本条件下,简单基线经常比想象中更可靠。
- 评估泄漏:少样本评估时,支持集里不能混入测试数据。这个规则说起来简单,但实际拆分数据时很容易出错。
4.3 工程层面的坑
- 随机种子不固定:少样本场景下采样方式对结果影响很大。不固定种子,结果可能无法复现。
- 依赖版本不一致:PyTorch、CUDA、数据处理库的版本差异都可能造成结果波动。
- 输出没有留痕:每次实验的配置、数据版本、模型权重如果没有完整保存,后面很难复盘。
4.4 一个可复用的排查顺序
如果模型效果异常,我一般按这个顺序排查:
- 先看数据:标签口径是否统一、特征是否对齐、有没有泄漏。
- 再看基线:在同一个数据划分上,简单模型表现如何。
- 再看适配过程:支持集数量、适配轮数、学习率是否合理。
- 再看评估:指标选对没有,是不是只看了准确率。
- 最后看工程:种子、版本、随机采样逻辑是否稳定。
从经验看,80% 的“模型效果差”最终都出在前两步,而不是模型结构本身。
5. 适用边界:谁该用、谁不该用、先验证什么
任何模型都不是万能药。ScreenShot 这类少样本基础模型有非常明确的适用边界,用之前要先对号入座。
5.1 适合的场景
- 同一个细胞系需要评估大量组合,但实验预算只够先测少量样本。
- 团队已经积累了较多历史筛选数据,想在新任务上省实验成本。
- 组合空间太大,传统全量筛选根本不现实。
- 你关注的是排序和优先级,而不是对每个组合给出绝对精确的分数。
5.2 不适合的场景
- 目标体系完全没有任何历史关联数据。预训练先验再强,也无法凭空理解一个与训练分布差距过大的领域。
- 实验预算充裕、组合数量不大。这时直接做全量实验,可能比模型筛选更可靠。
- 你只需要在一个固定数据集上做回归预测,不涉及跨任务泛化。简单模型通常更划算,维护成本也更低。
5.3 引入前的验证路径
如果你正考虑在团队里引入这类方案,我建议先用一个月做一次小规模验证:
- 从公开数据或自家历史数据里,选出 3~5 个不同细胞系的组合筛选结果。
- 对每个细胞系,模拟只给 20 个组合的观测结果。
- 用 ScreenShot 或同类方法做少样本预测,与随机选择、简单模型基线对比。
- 看 Top-50 推荐里,有多少被湿实验验证为真正协同。
如果这轮验证没有明显增益,说明你的数据特征或任务定义,可能和这类方法的适用条件不匹配。这时不要硬上,回头检查数据质量和任务划分,比换一个更大的模型更有效。
6. 这类模型真正改变的,是实验和计算的分工顺序
最后聊一个更大的视角。无论 ScreenShot 具体效果如何,“基础模型 + 少样本”这个组合,正在悄悄改变计算和实验之间的分工方式。
传统流程是:实验人员先做大规模筛选,再让计算模型去解释结果。这一套流程成本高、周期长,而且大量的实验精力被用在了低信息量的组合上。ScreenShot 这类模型提供的反 向流程是:先用历史数据预训练,再用极少量新实验数据做适配,最后让模型推荐下一个最值得做的实验。它的价值不在替代实验,而在减少无效实验。
这里还想提醒一件更接近底层经验的事:模型给你的不是答案,而是优先级。它把“从几万种组合里找到少数几个值得验证的选择”这件事,变成一个有先验支撑的推理过程。你可以把它理解成一个比随机猜测聪明很多的实验设计助手,但最终做决定、负责任、出结论的,仍然是你的孔板、细胞和剂量曲线。
如果你现在手上正好有一个组合筛选任务,与其到处找“万能模型”,不如先做一件事:把自己已有的历史数据整理好,标签口径统一,然后跑一次上面所说的最小验证。你会发现,少样本模型的收益,从来都不是靠参数堆出来的,而是靠数据组织、验证设计和实验闭环赢来的。