ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

组合药物筛选中的少样本基础模型:从原理到工程实现

组合药物筛选中的少样本基础模型:从原理到工程实现 ScreenShot 这个名字初看容易误认为是截图工具但在组合药物筛选中它指向的是一个少样本基础模型方向。组合药物筛选combination drug screening的目标是从大量候选药物对中找出协同效果显著、且毒性可控的组合传统做法依赖高通量实验成本高、搜索空间大。ScreenShot 这类基础模型要解决的问题是用已有的大规模组合筛选数据学习可迁移的药物-细胞相互作用先验当新任务只有少量实验数据时依然能给出可靠的协同预测和排序。这篇文章不会逐字复现原论文的全部细节而是从工程和复现角度拆解这个方向需要用到的数据、编码器、预训练目标、少样本适配、评估方式和排查路径并给出一个最小可运行的模型骨架。无论你是在自己的课题里做药物组合预测还是想把基础模型范式迁移到生物信息相关任务都可以按这套思路落地。1. 组合药物筛选为什么需要基础模型1.1 传统组合筛选的流程和成本瓶颈药物组合筛选通常先用棋盘稀释法获得两种药物在不同浓度下的联用响应再根据单药响应计算协同分数。常用判定参考模型包括 Loewe、Bliss 和 HSA 等它们的核心思想都是比较“联用实测效应”与“单药效应叠加后的期望值”之间的差值。差值超过阈值就认为存在协同效应接近或低于期望则可能只是加和甚至拮抗。问题在于一个组合实验往往涉及多浓度梯度、多重复、多细胞系。假设两个药物各测 8 个浓度一个 8x8 棋盘矩阵就是 64 个实验点再乘以细胞系和重复次数单个组合的成本并不低。当候选单药数量达到几千种时两两组合的搜索空间会膨胀到几十万甚至上百万量级传统高通量筛选只能覆盖其中很小一部分。这意味着组合筛选本质上是一个少样本问题实验覆盖的组合数量相对于完整搜索空间非常稀疏而新进入研究的药物组合或新细胞系往往只有几十到几百个标注样本。1.2 为什么不能只依赖单药响应预测一个直观的朴素做法是如果两个单药都有效那么组合也大概率有效。实际中这个假设经常失效。协同效应来自复杂的信号通路交叉作用两个单药单独效果一般联用后反而可能产生强烈的协同反过来两个强效单药联用可能因重叠靶点而只表现为加和效应甚至伴随不可接受毒性。因此组合筛选模型不能只从单药响应线性外推而需要建模更丰富的交互特征。这些特征包括药物侧分子结构、靶点、物理化学性质。细胞侧基因表达谱、通路活性、组织来源。交互侧两个药物在同一个细胞背景下产生的通路扰动。1.3 基础模型范式如何缓解数据稀疏基础模型Foundation Model通常指在海量通用数据上预训练再通过微调或提示适应下游任务的模型。在组合筛选场景中这种范式有三个实际价值。第一预训练阶段可以利用大量不包含组合标签的数据例如单药分子结构、单药对细胞系的响应、基因表达谱。这些数据比组合协同标签容易获得得多。第二预训练可以帮助模型建立“分子结构到生物效应”的通用表征。下游新任务即使只有少量组合样本模型也不需要从零学习化学和生物学基础只需要学习新的任务头或对表征做轻量适配。第三少样本适配和基础模型天然契合。新细胞系、新药物组合可以视为一个新的下游任务沿用支持集、查询集或者少样本微调的训练方式使模型在几十个样本上也能较快收敛。注意这里的“基础模型”不是说一定要用几十亿参数的大模型。重点在于预训练-微调范式而不是参数量。实际复现时一个中等规模的编码器加上良好的预训练任务往往比盲目堆参数更有效。2. 从标题拆解 ScreenShot 的技术路线ScreenShot 这个方向涉及三个核心模块输入表示、预训练主干、少样本预测层。下面按工程实现顺序拆解。2.1 药物分子表示从 SMILES 到特征向量药物分子最常用的原始输入是 SMILES 字符串例如布洛芬的CC(C)CC1CCC(CC1)C(C)C(O)O。模型不能直接消费字符串需要先转换为向量。常见做法有两类。第一类是分子指纹。RDKit 可以快速生成 Morgan 指纹ECFP。ECFP 把分子中每个原子周围环境编码成固定长度的位向量不考虑分子的空间构象适合作为浅层模型的输入特征。第二类是基于图的编码器。把分子看成图原子是节点化学键是边用 GIN、GCN 或消息传递网络学习分子级向量。图编码器表达能力更强也更适合预训练但实现和调试成本更高。复现 ScreenShot 类工作时建议先同时保留两种表示小规模实验中用指纹快速验证流程模型架构跑通后再替换成图编码器对比表示方式带来的效果差异。from rdkit import Chem from rdkit.Chem import AllChem def smiles_to_ecfp(smiles: str, radius: int 2, n_bits: int 2048): mol Chem.MolFromSmiles(smiles) if mol is None: return None fp AllChem.GetMorganFingerprintAsBitVect(mol, radius, nBitsn_bits) return list(fp) smiles CC(C)CC1CCC(CC1)C(C)C(O)O ecfp smiles_to_ecfp(smiles) print(len(ecfp), sum(ecfp))这段代码把单个分子转成 2048 维的 0/1 位向量。MolFromSmiles返回None时说明 SMILES 无法解析训练前需要过滤这类脏数据。2.2 细胞状态表示基因表达特征和细胞系特征组合药物筛选效果与细胞背景强相关。同一个药物组合在肺癌细胞系和肝癌细胞系上的表现可以截然不同。因此模型输入中必须有细胞状态表示。常用特征是从基因表达谱中提取的向量。公开细胞系数据库一般提供标准化后的表达量可以直接作为 Dense 输入。实际操作时需要注意特征维度要对齐。不同来源表达谱的基因数量可能不同需要统一到同一个基因集合。要区分训练集和测试集是否来自同一批细胞系。如果测试集中出现从未见过的细胞系模型行为会有很大差异。表达特征需要做标准化推荐使用 z-score 或 max-min 归一化避免数值范围过大影响训练稳定性。如果拿不到完整表达谱也可以用细胞系名称经过嵌入层生成一个低维向量。但这种方式泛化能力弱只适合原型验证。2.3 预训练目标掩码恢复与跨模态对齐基础模型的预训练目标决定了它能学到什么信息。ScreenShot 从论文标题看强调“基础模型”和“少样本”复现时可以尝试以下几种目标组合。第一种是掩码分子结构恢复。随机掩码药物分子指纹的一部分位点或图节点的属性让模型预测被掩码部分促使编码器理解分子结构规律。这与自然语言处理中的掩码语言模型思路一致。第二种是跨模态对齐。同一细胞系中将药物分子表示和细胞状态表示映射到同一向量空间。可以用对比学习实现例如 InfoNCE 损失让相关样本的表示更接近不相关样本的表示更远。第三种是协同分数回归。利用已有的组合筛选数据直接预测协同分数。这种方式最贴近下游任务但风险是预训练数据过少模型容易过拟合到已知组合上削弱迁移能力。实现时不要一股脑加入所有损失建议先只用协同分数回归跑一个基线再逐步加入对比学习或掩码恢复观察少样本验证集效果是否有提升。2.4 少样本适配微调、元学习与任务头少样本阶段的目标是在新任务上利用少量已标注组合数据快速适配。常见方案有三种。简单微调冻结预训练编码器只训练一个新的预测头用新任务的少量样本收敛。适合新任务与预训练数据分布差异不大时。全量微调编码器和预测头一起在少量样本上训练需要配合早停和正则化否则很容易过拟合到几十个样本上。元学习在预训练阶段按任务划分数据模拟“少量样本更新 查询集评估”的训练过程让模型学会快速适应新任务。适合新细胞系或新组合频繁出现的场景但训练复杂度明显更高。从复现角度看先实现微调路径最稳妥。新任务样本太少时再加一个简单的岭回归或逻辑回归预测层往往也能对比出预训练表征的质量。3. 最小可复现骨架数据、代码与训练流程3.1 数据格式设计复现组合筛选模型前先把数据整理成统一格式。下面是一个 JSON 示例用于说明字段组织方式。实际项目可以换成 CSV 或 Parquet但字段语义保持一致。{ sample_id: demo_0001, drug_a_id: D001, drug_b_id: D002, drug_a_smiles: CC(C)CC1CCC(CC1)C(C)C(O)O, drug_b_smiles: CN1CCC[CH]1C2CNCCC2, cell_line: A549, cell_expression: [0.12, -0.05, 1.23, 0.77, -0.34], synergy_score: 0.78, synergy_label: 1 }字段含义如下表。字段类型说明sample_idstring样本唯一标识drug_a_id / drug_b_idstring两个药物 ID用于组合分组drug_a_smiles / drug_b_smilesstring药物分子 SMILEScell_linestring细胞系名称cell_expressionlist[float]细胞系表达特征向量synergy_scorefloat连续协同分数synergy_labelint是否协同的二分类标签drug_a_id和drug_b_id不能省。后续做数据划分时必须按药物对进行分组避免同一个组合的数据同时出现在训练集和测试集中。3.2 环境准备这里以 Python PyTorch RDKit 作为最小环境。需要安装以下内容conda create -n screenshots python3.10 -y conda activate screenshots conda install -c conda-forge rdkit2023.9.6 pip install torch2.1.2 pip install pandas numpy scikit-learn tqdm版本选择说明Python 3.10 兼容性较好PyTorch 2.x 在该版本下生态稳定。RDKit 版本建议锁定。不同版本的 RDKit 生成指纹结果可能略有差异复现论文结果时必须固定版本。PyTorch 版本根据 GPU 和 CUDA 版本选择。没有 GPU 时先减小数据规模跑通流程。3.3 模型骨架实现下面代码是一个可运行的轻量预测模型。ScreeningHead接收药物 A、药物 B 的指纹和细胞表达向量输出协同分数。import torch import torch.nn as nn class ScreeningHead(nn.Module): def __init__(self, fp_bits2048, cell_dim128, hidden_dim256): super().__init__() self.proj_a nn.Sequential( nn.Linear(fp_bits, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim) ) self.proj_b nn.Sequential( nn.Linear(fp_bits, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim) ) self.proj_c nn.Sequential( nn.Linear(cell_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim) ) self.pred nn.Sequential( nn.Linear(hidden_dim * 3, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, 1) ) def forward(self, fp_a, fp_b, cell): ha self.proj_a(fp_a) hb self.proj_b(fp_b) hc self.proj_c(cell) h torch.cat([ha, hb, hc], dim-1) return self.pred(h).squeeze(-1)这个结构把两个药物和细胞系分别投影到hidden_dim维拼接后进入预测头。它假设协同效应主要由三部分特征的交互决定用一个前馈网络去拟合交互规律。代码没有使用图神经网络也没有预训练阶段。这是刻意控制复杂度先跑通一条完整链路再逐步替换组件。如果你想加入预训练可以先用自编码器或对比学习单独训练proj_a和proj_b再把参数迁移到当前模型。3.4 训练循环训练时使用回归损失预测连续协同分数。数据规模较小时建议用较小的 batch size 和较慢的学习率。def train_epoch(model, loader, optimizer, criterion, device): model.train() total_loss 0.0 for fp_a, fp_b, cell, label in loader: fp_a fp_a.to(device) fp_b fp_b.to(device) cell cell.to(device) label label.to(device) optimizer.zero_grad() pred model(fp_a, fp_b, cell) loss criterion(pred, label) loss.backward() optimizer.step() total_loss loss.item() return total_loss / len(loader) model ScreeningHead(fp_bits2048, cell_dim128, hidden_dim256).to(device) optimizer torch.optim.AdamW(model.parameters(), lr1e-3, weight_decay1e-4) criterion nn.MSELoss()训练命令可以直接封装成脚本python train.py --model screening_head --epochs 50 --lr 1e-3 --seed 42训练过程中要同时观察训练损失和验证损失。如果训练损失下降但验证损失上升说明过拟合优先减小学习率、增加 dropout 或提前停止。4. 评估少样本效果划分策略、指标与真实含义4.1 划分策略决定结论是否可信组合筛选领域的评估最容易犯错的地方是数据划分。错误做法是按样本随机划分。这样会导致同一个药物组合在不同 split 中重复出现模型表面效果很好实际却没有见过新的组合评估值虚高。正确做法是按组合分组划分。以(drug_a_id, drug_b_id, cell_line)作为分组键确保同一个组合的全部样本只出现在一个集合中。# 关键思路先构造 group key再按 group 做 split samples[group_key] ( samples[drug_a_id] _ samples[drug_b_id] _ samples[cell_line] ) groups samples[group_key].unique() train_groups, test_groups train_test_split(groups, test_size0.2, random_state42) train_df samples[samples[group_key].isin(train_groups)] test_df samples[samples[group_key].isin(test_groups)]如果目标任务是预测新细胞系中的组合效果划分方式要更严格所有训练和测试样本的细胞系不能重叠。这能测试模型对未见细胞背景的迁移能力。4.2 评估指标选择组合筛选预测通常同时关注排序性能和分类性能。推荐同时报告多个指标。指标用途注意点Pearson 相关系数衡量协同分数预测值与真实值的线性相关性对离群点敏感需要看散点图Spearman 相关系数衡量排序一致性适合筛选排名场景AUROC二分类协同标签的区分能力需要提前确定协同阈值命中率 / PrecisionK前 K 个预测组合中有多少真实协同更贴近实际筛选流程平均精度 AP综合精确率和召回率正负样本不平衡时有参考价值只报告 AUROC 不够因为协同分数预测的最终用途是排序也就是从一万个组合中挑出最值得做实验的前 100 个。这种场景下 PrecisionK 和 Spearman 比 AUROC 更直接。4.3 预期结果和基线对比基线选择至少要包含以下三个层次。随机预测把测试集协同分数随机打乱作为最差参考。单药响应线性模型把两个单药各自响应、分子指纹拼接后线性回归验证“加入交互建模是否真的有用”。简单指纹 浅层网络不加预训练直接用小网络预测协同分数。如果 ScreenShot 类模型相对这个基线没有提升说明增益来自预训练表征或更精细的模型结构而非单纯增加参数。日志示例epoch30 train_loss0.112 valid_loss0.198 epoch31 train_loss0.108 valid_loss0.197 epoch32 train_loss0.105 valid_loss0.203 test_spearman0.41 test_precision_at_1000.36如果验证损失稳定而 Spearman 低于预期优先检查数据划分是否泄漏、特征是否对齐、正负标签是否均衡。注意少样本场景下测试集样本量很小单次评估结果方差很大。建议固定多个随机种子重复实验报告均值、标准差观察评估结果是否稳定。5. 复现过程中最常见的坑和排查路径5.1 数据泄漏导致评估虚高现象训练集和测试集 AUROC 都很高但换一个新批次数据后效果大幅下降。原因划分时没有按药物组合分组同一个组合的不同浓度、不同重复样本被切散到训练集和测试集中。检查方式抽样检查测试集中是否存在与训练样本完全相同的(drug_a_id, drug_b_id, cell_line)组合。解决方式按分组键重新划分并考虑细胞系隔离划分。问题现象常见原因检查方式处理建议训练和测试指标都高但实际效果差组合级样本泄漏统计训练/测试分组重叠数量按组合分组划分必要时按细胞系划分新细胞系上效果暴跌训练和测试细胞系重叠检查测试集中细胞系是否在训练集中出现做跨细胞系评估训练集细胞系隔离5.2 分子特征不一致导致结果不可复现现象同一批数据换一台机器或更新 RDKit 后指纹维度或部分样本结构发生变化结果无法复现。原因RDKit 不同版本对 SMILES 解析、芳香性判断、指纹生成逻辑存在差异另一个常见原因是 SMILES 没有做标准化同一个分子有不同写法。检查方式python -c import rdkit; print(rdkit.__version__)在训练脚本里记录 RDKit 版本、Python 版本、PyTorch 版本。对 SMILES 做 canonical 化过滤MolFromSmiles失败的样本。解决方式固定环境版本使用同一个 RDKit 环境完成特征生成和训练把特征预先计算并保存为 numpy 数组或 parquet 文件避免每次训练都重新计算指纹。5.3 少样本评估中随机种子和采样方差现象只跑一次实验Spearman 从 0.45 变成 0.25无法判断模型是否真的有效。原因测试集只有几十个样本抽样种子不同结果波动很大甚至数据加载顺序不同也会引起微小波动。检查方式固定数据划分种子和模型初始化种子分别跑 3 到 5 次统计均值与标准差。解决方式把随机种子作为训练脚本参数结果输出中记录 seed、指标均值、标准差。报告少样本评估结果时必须包含这些信息否则结论不可信。5.4 排查链路从训练发散到指标虚高的通用路径如果训练过程中出现问题按下面的顺序排查先检查输入数据是否有空值、NaN、无效 SMILES。再检查特征维度是否一致药物 A、B、细胞系三个输入维度是否匹配模型定义。输出训练前几步的 loss。如果 loss 不下降检查学习率、数据顺序和标准化。检查训练集和测试集是否按组合分组隔离。检查评估代码中是否对标签做过不同变换例如训练用归一化分数评估却用原始分数。最后检查随机种子是否固定。6. 从论文复现到生产实践工程化建议6.1 学习环境与生产环境的差异论文复现阶段关注的是“模型能不能学出来”生产实践阶段关注的是“模型能不能稳定地用起来”。两者在任务目标上有明显差别。维度学习和研究环境生产环境数据规模少量公开数据集持续接入新组合实验数据特征计算每次训练时临时计算提前离线计算并缓存模型更新重训整个模型支持增量微调和版本回滚评估频率训练完成后评估每次数据更新后自动评估可解释性指标好即可需要输出候选组合与原因说明权限安全本机实验数据权限隔离、模型版本追踪日志监控打印 loss记录指标、数据分布漂移、失败样本组合筛选的生产系统通常需要对接实验数据库新组合数据以天或周为单位进入系统。模型不能每次重新全量训练建议采用定期更新的方式每天用新数据增量微调每周用全量数据重新训练一个候选版本做对比评估后决定是否灰度发布。6.2 落地时可复用的检查清单在论文复现和生产化过程中可以使用下面这份清单做上线前检查。数据检查SMILES 解析通过率是否达到 100%表达特征是否标准化是否存在重复样本。划分检查训练、验证、测试集是否按组合分组隔离是否做了跨细胞系评估。表示检查分子指纹是否统一由固定版本 RDKit 生成特征文件是否缓存。模型检查是否需要预训练编码器预测头是否匹配输出空间。训练检查是否固定随机种子是否记录训练环境版本是否有 early stopping。评估检查是否同时报告 Spearman、AUROC、PrecisionK是否重复多次实验。上线检查是否保存模型版本是否有推理日志是否监控新数据与训练数据分布差异。6.3 扩展方向主动学习、剂量响应和不确定性建模ScreenShot 类模型的最终价值不仅要预测协同分数还要指导下一次实验做哪些组合。因此有几个扩展方向值得关注。主动学习模型在少样本场景下应该主动挑选信息量最大的组合推荐给实验人员例如不确定性高的样本、与已知协同组合差异大的样本。这样可以减少实验次数。剂量响应预测当前示例只预测离散组合的协同分数但真实筛选要求预测多浓度下的完整剂量响应曲线。把输出从标量扩展成曲线参数信息量更大。不确定性建模少样本预测天然存在不确定性。用 MC Dropout 或深度集成估算预测方差可以让实验人员知道哪些预测可信、哪些预测仅供参考。复现 ScreenShot 类基础模型时不要一开始就追求完整复刻全部模块。最低成本路线是先按组合分组划分数据用指纹作为特征训练一个浅层模型记录基线指标然后用同一个数据量做预训练-微调对比指标是否提升最后再逐步引入图编码器、对比学习和不确定性估计。这样每一步的改动都有对照组问题也更容易定位。少样本组合药物筛选的真正门槛不在模型名字而在数据划分、表示一致性和评估方式。先把一个最小骨架跑通再逐步把预训练编码器、大规模筛选数据和新任务适配加进来是更稳妥的技术路线。
返回列表