最近医疗创新药板块的表现,确实让很多人的注意力从“大力出奇迹”的半导体、AI 应用,一下子转向了医药赛道。朋友圈里甚至出现了“买科技已经过时”的说法。但作为一个技术作者,我更想提醒大家另一件事:创新药上涨背后,真正值得长期跟踪的,不是短期资金流向,而是医药研发本身正在发生的技术变革。
过去十年,创新药研发靠的是“试错 + 经验 + 运气”。一个靶点从验证到上市,往往要跨过靶点发现、先导化合物优化、临床前研究、I/II/III 期临床试验等漫长流程,投入大、周期长、失败率高。而现在,AI 制药、计算化学、临床试验数据工程等信息技术,正在把这套流程从“大海捞针”变成“定向搜索”。对程序员来说,这意味着一个全新且壁垒很高的技术应用场景。
这篇文章不讨论股票买卖,也不构成任何投资建议。我想做的是把“医疗创新药大涨”这个热点,切换到技术视角:创新药研发的技术链路怎么拆解?AI 在哪些环节真正起作用?一个新入行的开发者可以从哪里开始实践?我会给出一套可落地的工具链和代码示例,帮助你理解这个领域的技术全貌。
1. 创新药研发的痛点:为什么这次轮到技术登场
创新药研发的难度,经常被一句话概括:做过一万次实验,可能只有一个分子能成为药物。这个说法不完全精确,但方向是对的。
在整个流程中,最大的成本其实是“试错成本”。
- 靶点选择错了,后面所有工作归零。
- 先导化合物活性不够,或者毒性太强,需要重新筛选。
- 临床 I 期发现安全性问题,前期投入全部打水漂。
- 临床 III 期疗效不达预期,这是最常见的失败节点。
传统模式下,科研人员依赖文献经验、体外实验和动物实验来推进决策。问题是,候选分子的空间太大,靠人工一个个测试,效率太低。一个典型的药物发现项目,可能要从几十万甚至上百万个化合物中筛选出少数几个先导化合物,再反复优化。
这里就出现了 IT 技术的切入点。
AI 和计算化学的价值,不是替代实验,而是在实验之前,用计算的方式缩小搜索空间、预测分子性质、评估风险,把有限的实验资源集中在最有希望的候选分子上。换句话说,它解决的是“选择效率”问题。
这背后的技术链路,包括:
- 分子数据的标准化与存储。
- 基于机器学习的性质预测。
- 大规模虚拟筛选。
- 临床试验数据的管理与分析。
理解了这些,你就会发现:创新药板块上涨,某种程度上是市场对“研发效率提升”这件事给出的定价。而对技术人员来说,更实际的问题是:这些能力到底怎么实现。
2. 从靶点到上市:创新药研发流程中的技术环节
要理解 AI 制药,先要把药物研发流程拆开。不同阶段的技术诉求完全不同。
2.1 靶点发现与验证
靶点是与疾病相关的生物分子,通常是蛋白质。药物进入人体后,通过作用于靶点来调节疾病进程。
传统发现靶点的方式,主要靠基因敲除实验、动物模型和文献报道。现在则越来越多地结合组学数据(基因组、转录组、蛋白质组)和知识图谱。技术人员在这里要做的是:
- 多源数据整合。
- 差异表达分析。
- 蛋白质结构预测。
- 靶点-疾病关联挖掘。
2.2 先导化合物发现
靶点确定之后,需要找到能与靶点结合并产生效应的化合物。这个环节是 AI 计算应用最密集的地方。
虚拟筛选是核心方法之一。它分为两类:
- 基于结构的虚拟筛选:需要靶点的三维结构,用分子对接软件评估候选分子与靶点的结合能力。
- 基于配体的虚拟筛选:不知道靶点结构时,用已知活性分子作为模板,检索相似分子。
此外,生成式模型可以主动设计新分子,而不只是从已有库中筛选。
2.3 ADMET 预测
ADMET 分别代表吸收、分布、代谢、排泄和毒性。一个化合物即使活性很强,如果吸收差、代谢快、毒性大,也无法成为药物。
ADMET 预测是机器学习在制药领域最成熟的应用之一。它的输入是分子结构,输出是各种性质预测,比如水溶性、CYP 酶抑制、hERG 心脏毒性风险等。
2.4 临床试验设计与数据管理
进入临床阶段后,信息技术同样在发挥作用。
- 电子数据采集系统替代纸质病例报告表。
- 中心化统计监查用于发现数据异常。
- 患者分层模型帮助设计更精准的试验方案。
- 真实世界数据补充传统临床试验的不足。
这个环节对工程和数据治理能力要求很高,也是医疗数据合规问题最集中的地方。
3. AI 制药的核心概念:分子表示、特征工程与模型选择
很多开发者在接触 AI 制药时,第一个困惑是:药物分子怎么变成机器学习模型能处理的输入?
答案是分子表示。这个环节决定了整个模型的上限。
3.1 SMILES 与分子标准化的基础概念
SMILES 是一种用 ASCII 字符串表示分子结构的语法规范。比如乙醇可以写成CCO,苯可以写成c1ccccc1。
SMILES 简单易懂,但存在一个问题:同一个分子可能有多个合法的 SMILES 字符串。如果直接把原始 SMILES 作为输入,模型会认为它们是不同分子。
因此在预处理阶段,必须做标准化操作。常用的工具是 RDKit,它可以:
- 将 SMILES 转换为规范形式。
- 去盐、去溶剂。
- 中和电荷。
- 处理立体化学信息。
3.2 分子描述符与分子指纹
在传统机器学习流程中,通常不直接把 SMILES 输入模型,而是先计算分子描述符或分子指纹。
分子描述符是数值型特征,例如:
- 分子量。
- 脂水分配系数 LogP。
- 拓扑极表面积 TPSA。
- 氢键供体/受体数量。
- 可旋转键数量。
分子指纹则是将分子结构映射为一个固定长度的二进制向量,常见的有 Morgan 指纹(也称 ECFP)和 MACCS 指纹。分子指纹的核心思想是保留分子子结构信息,便于做相似性比较。
3.3 深度学习模型的新范式
传统机器学习方法依赖人工设计特征。深度学习则试图直接从分子表示中学习特征。
常见做法包括:
- 图神经网络(GNN):把分子看作图,原子是节点,化学键是边。
- Transformer 模型:把 SMILES 看作文本序列,用语言模型预训练。
- 扩散模型:用于生成全新分子结构。
这些方法在文献中表现不错,但工程实践中仍然面临数据量不足、可解释性差、验证困难等问题。对于刚入门的人,我的建议是先从分子描述符 + 机器学习开始,理解完整链路,再逐步过渡到深度学习。
3.4 传统方法与 AI 方法对比
| 环节 | 传统方式 | AI 辅助方式 |
|---|---|---|
| 候选分子获取 | 海量实验筛选 | 虚拟筛选 + 生成式模型 |
| 活性评估 | 体外实验 | 机器学习打分 + 实验验证 |
| ADMET 预测 | 动物实验阶段才暴露 | 早期计算预测 |
| 数据管理 | 纸质记录 + 人工整理 | 结构化数据库 + 自动化管线 |
从这张表可以看出,AI 并不替代实验,而是把很多“原本要到后期才能发现的问题”提前到计算阶段暴露,从而降低风险。
4. 环境准备:搭建药物分子计算工具链
在动手写代码之前,先准备一套可用的 Python 环境。下面的示例基于 Python 3.10+,建议使用 Conda 创建独立虚拟环境,避免依赖冲突。
conda create -n drugai python=3.10 -y conda activate drugai激活环境后,安装核心依赖。
pip install rdkit scikit-learn pandas numpy matplotlib- RDKit:开源化学信息学工具包,负责分子读写、标准化、描述符计算。
- scikit-learn:机器学习模型训练与评估。
- pandas / numpy:数据处理。
- matplotlib:结果可视化。
如果你的机器有 NVIDIA GPU,后续想从传统机器学习升级到图神经网络或深度学习模型,可以安装 PyTorch 和 DeepChem。但这篇示例不需要 GPU,CPU 就能跑通。
版本细节以你实际安装为准,不要把某个固定版本当成硬性要求。
5. 完整示例:从分子标准化到性质预测
下面用三个递进的示例,把前面讲的技术概念串起来。
5.1 示例一:SMILES 标准化与分子描述符计算
新建文件descriptors.py。
# 文件路径:descriptors.py from rdkit import Chem from rdkit.Chem import Descriptors, Crippen, rdMolDescriptors smiles_list = [ "CCO", # 乙醇 "c1ccccc1", # 苯 "CC(C)Cc1ccc(cc1)C(C)C(=O)O", # 布洛芬 "O=C(Nc1ccccc1)C(C)C", # 一个简单的酰胺示例 ] for smi in smiles_list: mol = Chem.MolFromSmiles(smi) if mol is None: print(f"无法解析的 SMILES: {smi}") continue # 规范化:生成 canonical SMILES canonical_smi = Chem.MolToSmiles(mol) # 分子量 mw = Descriptors.MolWt(mol) # 脂水分配系数 LogP logp = Crippen.MolLogP(mol) # 拓扑极表面积 TPSA tpsa = rdMolDescriptors.CalcTPSA(mol) # 氢键供体和受体数量 hbd = rdMolDescriptors.CalcNumHBD(mol) hba = rdMolDescriptors.CalcNumHBA(mol) print(f"SMILES: {smi}") print(f"Canonical: {canonical_smi}") print(f"MolWt: {mw:.2f}, LogP: {logp:.2f}, TPSA: {tpsa:.2f}") print(f"HBD: {hbd}, HBA: {hba}") print("-" * 50)运行方式:
python descriptors.py这段代码完成三件基础工作:
- 把 SMILES 解析成分子对象。
- 用
MolToSmiles获得规范 SMILES,避免同一个分子因为写法不同被当成两个样本。 - 计算后续机器学习模型会用到的分子描述符。
RDKit 解析失败时,Chem.MolFromSmiles会返回None,所以代码里加了空值判断。实际处理大规模数据时,这类异常处理尤其重要,因为公开数据集中脏数据非常多。
5.2 示例二:基于 Tanimoto 相似度的虚拟筛选
虚拟筛选并不总是需要训练模型。当你已经有一个已知活性分子时,最简单的做法是从化合物库中检索相似分子。这里使用 Morgan 指纹和 Tanimoto 相似度完成排序。
新建文件virtual_screen.py。
# 文件路径:virtual_screen.py from rdkit import Chem from rdkit.Chem import AllChem, DataStructs # 参考分子:一个已知活性的先导化合物(这里用布洛芬作为演示) query_smiles = "CC(C)Cc1ccc(cc1)C(C)C(=O)O" query_mol = Chem.MolFromSmiles(query_smiles) query_fp = AllChem.GetMorganFingerprintAsBitVect(query_mol, radius=2, nBits=1024) # 候选分子库 candidate_smiles = [ "CC(C)Cc1ccc(cc1)C(C)C(=O)O", # 布洛芬本身 "CC(C)Cc1ccc(cc1)C(C)C(=O)OC", # 布洛芬甲酯 "CC(C)Cc1ccc(cc1)C(C)C(=O)NCCN", # 含酰胺链衍生物 "COc1ccc(CC(C)C(=O)O)cc1", # 甲氧基取代类似物 "O=C(O)Cc1cccc2ccccc12", # 萘普生类似 "CC1=CC(=O)OC1", # 无关的小环酯 ] print("查询分子:", query_smiles) print("排序结果:") print(f"{'SMILES':<45}{'Tanimoto':<10}") results = [] for smi in candidate_smiles: mol = Chem.MolFromSmiles(smi) if mol is None: continue fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=1024) sim = DataStructs.TanimotoSimilarity(query_fp, fp) results.append((smi, sim)) results.sort(key=lambda x: x[1], reverse=True) for smi, sim in results: print(f"{smi:<45}{sim:<10.4f}")运行方式:
python virtual_screen.py预期输出中,布洛芬本身的相似度为 1.0,其衍生物相似度较高,无关小分子的相似度接近 0。这是一套最基础但非常有实用价值的相似性筛选流程。
这里真正值得注意的坑是分子指纹的参数选择:
radius相当于指纹感知的局部环境大小,太小可能丢失药效团信息,太大则容易让不同分子都被判为相似。nBits是位向量长度,太短可能增加碰撞概率。
实际项目中,这些超参数需要根据数据集规模和后续实验验证来调整,而不是盲目套用默认值。
5.3 示例三:用机器学习预测分子水溶性
相似性搜索只能回答“哪个分子看起来像已知活性分子”,但它回答不了“分子是否易于吸收”。接下来这个示例,用分子描述符作为特征,训练一个回归模型预测分子的水溶性 LogS。
为了便于演示,下面的数据是教学用途的简化片段。真实项目中,你应该从 ChEMBL、PubChem 或者商业化合物数据库导出足够量的带标签数据。
新建文件solubility_model.py。
# 文件路径:solubility_model.py import pandas as pd from rdkit import Chem from rdkit.Chem import Descriptors, Crippen, rdMolDescriptors from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import cross_val_score from sklearn.metrics import r2_score import numpy as np # 演示数据:SMILES 与对应的实验 LogS 值 # 注意:这是教学用简化数据,不能用于真实药物研发判断 demo_data = [ {"smiles": "CCO", "logS": 0.20}, {"smiles": "CC(C)O", "logS": -0.10}, {"smiles": "CC(C)Cc1ccc(cc1)C(C)C(=O)O", "logS": -3.20}, {"smiles": "c1ccccc1", "logS": -2.50}, {"smiles": "O=C(N)c1ccccc1", "logS": -1.10}, {"smiles": "CC(=O)O", "logS": 0.50}, {"smiles": "CCOC(C)=O", "logS": -0.30}, ] def featurize(smiles): """从 SMILES 计算一组分子描述符,作为模型特征""" mol = Chem.MolFromSmiles(smiles) if mol is None: return None return [ Descriptors.MolWt(mol), Crippen.MolLogP(mol), rdMolDescriptors.CalcTPSA(mol), rdMolDescriptors.CalcNumHBD(mol), rdMolDescriptors.CalcNumHBA(mol), Descriptors.NumRotatableBonds(mol), ] feature_names = ["MolWt", "LogP", "TPSA", "HBD", "HBA", "RotBonds"] rows = [] labels = [] valid_count = 0 for item in demo_data: feat = featurize(item["smiles"]) if feat is not None: rows.append(feat) labels.append(item["logS"]) valid_count += 1 X = pd.DataFrame(rows, columns=feature_names) y = np.array(labels) # 随机森林回归模型 model = RandomForestRegressor(n_estimators=100, random_state=42) # 5 折交叉验证 scores = cross_val_score(model, X, y, cv=5, scoring="r2") print(f"交叉验证 R2: {scores.mean():.4f} (+/- {scores.std():.4f})") # 在全部数据上重新训练,并评估训练集表现 model.fit(X, y) y_train_pred = model.predict(X) print(f"训练集 R2: {r2_score(y, y_train_pred):.4f}") # 预测一个新分子:苯酚 new_smiles = "c1ccc(cc1)O" new_feat = featurize(new_smiles) if new_feat is not None: new_df = pd.DataFrame([new_feat], columns=feature_names) pred = model.predict(new_df)[0] print(f"新分子 {new_smiles} 的预测 LogS: {pred:.4f}")运行方式:
python solubility_model.py这段代码展示了一个完整的建模流程:特征工程、模型训练、交叉验证、样本预测。
需要特别指出,这个示例只有 7 条数据,交叉验证的分数没有统计意义,唯一的用途是演示工程流程。真实场景中,水溶性模型的训练数据至少需要数百到数千条,并且需要进行严格的数据清洗和外部验证。不要把这个示例里的 R2 数值当作任何结论。
6. 运行结果与效果验证
6.1 预期输出
示例一输出的核心是看到每个分子都有规范化的 SMILES 和数值描述符。如果某个 SMILES 无法解析,程序会打印提示并继续处理下一条,而不会中断。
示例二预期看到相似度排序结果,查询分子本身的 Tanimoto 相似度为 1.0,结构相似的衍生物排在前面,无关分子排在最后。
示例三预期看到交叉验证 R2 和训练集 R2 两个数值,以及一个新分子的预测 LogS。因为数据量太小,R2 可能波动很大,这本身就是一个需要理解的现象。
6.2 如何判断运行成功
判断标准不是“输出不为空”,而是:
- 示例一中所有 SMILES 都被解析,没有出现
None。 - 示例二的相似度排序符合化学直觉。
- 示例三代码完整执行,没有抛出异常,输出了预测值。
6.3 运行失败的第一步排查
如果代码报错,最常见的原因是 RDKit 没有安装成功。可以先在 Python 中执行import rdkit,确认模块能正常导入。如果导入失败,重新执行:
pip uninstall rdkit pip install rdkit如果是在 macOS 或 Linux 上遇到编译问题,更推荐用 conda 安装 RDKit:
conda install -c conda-forge rdkitConda 方式能够避免大量底层依赖冲突,是 RDKit 社区推荐的安装方式。
7. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
Chem.MolFromSmiles返回None | SMILES 字符串格式错误,或包含数据库中的非标准写法 | 单独打印该条 SMILES,人工确认结构 | 清洗数据,必要时用 RDKit 的 Sanitize 流程重新标准化 |
安装 RDKit 后import rdkit失败 | 环境混用,pip 包装到了不同的 Python 环境 | 检查which python和pip list | 使用 conda 虚拟环境重新安装 |
| 分子描述符数值异常偏大或为 NaN | 分子中包含特殊原子或未处理好的金属原子 | 用Chem.SanitizeMol检查分子合法性 | 添加过滤逻辑,剔除无法计算的分子 |
| 机器学习模型交叉验证分数极低 | 数据量太小,或特征信息不足 | 使用真实数据集提高样本量;尝试增加特征 | 从 ChEMBL 等公开数据库获取更多带标签数据 |
| 相似性检索结果“不合理” | 分子指纹半径或位长设置不合适 | 对比不同参数下的检索结果 | 小范围调参,结合实验验证选择参数 |
这里最值得警惕的是第一个问题。从数据库导出的 SMILES 往往带有盐、溶剂、特殊 R-group 标记,直接进模型会让模型学到错误信息。标准做法是先用 RDKit 做去盐和标准化,再计算特征。
8. 最佳实践与工程建议
前面讲的是“跑通”,下面聊“做扎实”。
8.1 数据治理优先于模型调参
药物研发领域,数据质量直接决定模型的上限。即使模型结构再先进,输入数据是脏的,结果也不可靠。
建议团队从第一天就建立数据治理规范:
- 所有分子结构统一用规范 SMILES 存储。
- 记录数据来源、版本和获取时间。
- 对标签数据保留实验方法和批次信息。
- 建立清洗规则,例如去盐、去重复、剔除无机物。
8.2 模型可解释性不能等上线再说
药物研发是高风险领域,研发人员不会仅凭模型输出的一个数值做决策。模型必须能够解释:为什么预测这个分子活性高?依据了哪些结构特征?
传统机器学习中,可以分析特征重要性。深度学习中,可以关注原子级别的注意力权重或梯度解释。无论哪种方式,可解释性都是落地的前提条件。
8.3 合规与安全是硬约束
医药研发涉及大量敏感数据,包括患者数据、临床数据、未公开的化合物结构。这部分内容必须遵循数据安全法和行业监管要求:
- 数据加密存储和传输。
- 最小权限原则,不因协作需要而扩大数据访问范围。
- 完整审计追踪,任何数据修改都能追溯到人。
- 涉及临床试验数据时,需要遵循行业数据标准和合规要求。
这不仅是技术问题,更是企业风险控制的底线。安全相关的操作必须先经过合法授权,并在测试环境验证后,再进入生产环境。
8.4 从研究到生产的工程化差异
很多团队在 Jupyter Notebook 里跑通模型后,以为工作已经完成。实际上,从研究原型到生产部署还有一段很长的路:
- 特征计算逻辑要统一封装成服务,而不是散落在 Notebook 中。
- 模型版本需要管理,能够复现训练过程。
- 推理服务要记录输入输出日志,便于后续审计和模型监控。
- 当新的实验数据到来时,模型需要能够快速更新和评估。
可以参考这样分阶段推进:
- 研究所段:跑通流程,验证可行性。
- 工具化阶段:把数据处理和模型训练固化为脚本或流水线。
- 服务化阶段:提供统一接口,接入实验管理系统。
- 持续迭代阶段:建立数据回流和模型更新机制。
8.5 团队角色与协作方式
一个成熟的 AI 制药团队,通常需要以下几类角色:
- 计算化学家:负责分子结构理解、虚拟筛选方案设计。
- 数据工程师:负责数据采集、清洗、标准化和存储。
- 算法工程师:负责模型设计、训练和评估。
- 生物/药理科学家:负责实验验证和解释结果。
- 平台工程师:负责系统搭建、合规和安全。
如果你是一名开发者,刚进入这个领域时不需要成为化学专家,但至少要能读懂 SMILES、理解分子描述符的含义,并清楚实验科学家在体外验证时需要什么。建立起这种跨学科沟通能力,比单纯把模型训得更准更有价值。
9. 总结与后续学习方向
回到开头的话题:医疗创新药板块走强,本质上是市场对研发效率和研发确定性的一次重新定价。而对技术从业者来说,这轮周期里更有长期价值的机会,是参与医药研发数字化基础设施的建设。
这篇文章从创新药研发流程讲起,梳理了靶点发现、先导化合物筛选、ADMET 预测、临床试验数据管理四个环节中的技术切入点;介绍了 SMILES、分子描述符、分子指纹、虚拟筛选和机器学习建模的核心概念;并通过三个完整代码示例,把“分子标准化—相似性搜索—性质预测”这条基础链路跑通了。
你可以从以下顺序继续深入:
- 熟悉 RDKit,把官方的 Catalog 文档完整读一遍。
- 找一个公开数据集,比如 ChEMBL 的一个靶点数据,复现一遍完整的建模流程。
- 学习图神经网络和 Transformer 在分子表示学习中的应用。
- 了解临床试验数据的标准格式和数据处理流程。
- 关注合规和数据安全要求,理解医药研发的工程边界。
这个领域门槛并不低,但它给你提供了一个非常稀缺的机会:用通用的软件工程和 AI 能力,去解决一个死亡率高、成本高、社会价值也高的难题。技术不一定能立刻改变股价,但一定能提升整个行业做决策的质量,这才是最值得长期投入的部分。
建议先收藏这篇文章,把环境装好,跑通示例,再带着代码里的问题去读更多深入材料。跑通一次完整流程,比读十篇泛泛的行业报告更有用。