2. QSAR基本原理与建模流程

这一章,我们聊聊QSAR最核心的东西——它凭什么能预测分子活性?以及我们到底该怎么一步步把模型搭起来。

我记得刚入行那会儿,带我的前辈丢给我一堆化合物结构和一个Excel表,说“做个QSAR看看”。我当时一脸懵:就这么几个分子,能预测出啥?后来做多了才发现,QSAR这套逻辑,说白了就靠一个假设:结构相似的分子,性质也相似。听起来简单对吧?但就是这个假设,撑起了整个计算化学的预测体系。

2.1 定量构效关系的三个基本假设

QSAR能成立,靠三根柱子。我做过不少项目,凡是模型翻车的,基本都是这三根柱子里至少有一根没立稳。

  1. 相似性假设:结构相似的化合物,其生物活性也相似。这个假设是QSAR的基石。你想想看,如果把苯环上的甲基换成乙基,活性大概率不会从纳摩尔跳到毫摩尔。
  2. 线性假设:分子的结构变化与其活性变化之间存在可量化的线性(或可建模的非线性)关系。说白了,就是分子的某个数值属性(比如脂水分配系数LogP)和活性之间,能用数学方程描述。
  3. 可计算假设:分子结构可以用一组数值(也就是描述符)完整表征,这些数值能够涵盖影响活性的关键因素。

我曾经踩过一个坑:有一批化合物,骨架完全不同,强行用同一个QSAR模型去预测。结果交叉验证R²有0.85,但外部测试集的预测值跟实验值完全对不上。为什么?因为这些化合物压根就不满足“相似性假设”。你拿汽油车的参数去预测电动车的油耗,能准吗?

2.2 建模流程全景图

QSAR的建模流程,我习惯把它分成五个阶段。每个阶段都有它自己的坑和技巧。下面这张图,把整个流程串起来了。

QSAR建模标准流程 数据准备 描述符计算 模型构建 验证 预测 ⚠ 验证不通过 → 回到描述符计算 或模型构建阶段,迭代优化

2.3 第一步:数据准备

数据质量决定模型上限。这句话我重复了无数遍。很多初学者一上来就急着算描述符、跑模型,结果数据里一堆错误值,模型跑出来的R²再高也是假的。

数据收集:一般从公共数据库(ChEMBL、PubChem、BindingDB)或者自己实验测的活性数据来。我个人建议优先用ChEMBL,数据标注相对规范,而且有活性类型(IC₅₀、Kᵢ、EC₅₀)和单位标注。

数据清洗:这是最花时间、但也最容易被忽视的一步。我会做这么几件事:

  • 剔除没有明确活性值的条目(比如只写了“active”却没给具体数值的)
  • 统一活性单位(全部转成nM,或者全部转成pIC₅₀)
  • 检查化合物结构是否合理(比如有没有明显的不成键原子、电荷不平衡)
  • 处理重复结构——同一个化合物有两组活性数据,选哪个?我的习惯是取平均值,如果偏差太大(超过一个数量级),两个都扔掉。

一个小技巧:我一般会把活性值转成pIC₅₀(-log₁₀(IC₅₀)),这样数据分布更接近正态,后续建模时误差项更稳定。代码实现很简单:

import numpy as np
# 假设 ic50_list 是原始 IC50 值(单位 nM)
pIC50_list = [-np.log10(ic50 * 1e-9) for ic50 in ic50_list]
数据问题类型 处理方法 我遇到过的典型案例
活性值缺失 直接删除该条数据 文献里只写了"inactive",没给具体IC₅₀
单位不一致 统一换算为nM或pIC₅₀ 同一批数据里混着μM和nM,没换算就建模
结构重复 取平均值或保留高质量来源 同一个化合物在ChEMBL和PubChem里都有数据,活性差了100倍
SMILES格式错误 用RDKit校验和标准化 SMILES里出现了非法字符或未配对的括号

2.4 第二步:描述符计算

描述符,就是把分子结构翻译成数字的语言。选什么描述符、算多少维,直接决定了模型能不能抓得住关键信息。

常见的描述符类型有这三种:

  • 0D/1D描述符:分子量、原子数目、氢键供体/受体数等。这些最基础,但信息量有限。
  • 2D描述符:拓扑指数(比如Wiener指数、Zagreb指数)、分子指纹(ECFP、MACCS)。我项目里最常用的是ECFP4指纹,计算快,效果也不错。
  • 3D描述符:需要分子构象,计算成本高。比如量子化学参数(HOMO/LUMO能级)、分子表面积、分子体积。

我个人习惯先用2D描述符快速建模,如果效果不满意,再把3D描述符加进去试。这样能节约大量计算时间。你用RDKit算MACCS指纹,代码就几行:

from rdkit import Chem
from rdkit.Chem import MACCSkeys

smi = "CC(=O)Oc1ccccc1C(=O)O"
mol = Chem.MolFromSmiles(smi)
maccs_fp = MACCSkeys.GenMACCSKeys(mol)
print(maccs_fp.ToBitString()[:50])  # 打印前50位

2.5 第三步:模型构建

模型选型这事儿,我建议你是“先试后选”。不要一上来就上深度学习,很多时候一个简单的多元线性回归或者随机森林就够用了。

常用的模型:

  • 多元线性回归(MLR):适合描述符少、数据关系近似线性的情况。解释性强,但预测能力有限。
  • 偏最小二乘(PLS):处理描述符多但样本少的情况,能自动降维。我早期做激酶抑制剂的QSAR,经常用PLSR。
  • 随机森林(RF):抗过拟合能力强,能处理非线性和特征交互。是我项目中的“万金油”。
  • 支持向量回归(SVR):在小样本高维场景下表现不错。但调参比较麻烦。

我的经验:如果你的数据量小于100个化合物,优先试PLS或随机森林。深度学习至少需要有几千个样本才撑得起来,否则很容易过拟合。记住,模型越复杂,需要的数据量就越大,这个trade-off你必须有数。

2.6 第四步:验证

验证这一步,说白了就是给你的模型打分——到底能不能用?我见过不少人交叉验证R²做到0.9,就以为模型完美了,结果一到外部预测就崩。为什么?因为验证集没选对。

验证的方法,从上到下可靠性递增:

  1. 内部验证:留一法交叉验证(LOOCV)、K折交叉验证。适合初步评估,但容易高估模型泛化能力。
  2. 外部验证:用独立于建模的外部测试集来评估。这才是真正检验模型好坏的“照妖镜”。
  3. Y-随机化验证:把活性值打乱,重新建模。如果模型仍然有较好的R²,说明你的模型学到的是噪声,不是真实规律。

我一般会用R²来评估拟合好坏,用Q²(交叉验证的R²)和RMSE来评估预测能力。一个靠谱的QSAR模型,至少要求Q² > 0.5,且外部测试集的R²_pred > 0.6。

我曾经就吃过这亏:做了一组化合物库的QSAR,留一法交叉验证R²到0.88,当时很开心,觉得可以交差了。结果拿外部测试集一测,R²只有0.32。后来查原因,发现训练集和外部测试集的化合物骨架分布差异太大,模型其实只学会了训练集内部的“模式”,完全没学到通用的规律。从那以后,我做任何项目都强制要求先分割外部测试集,模型建好之前绝对不看外部测试集的数据。

2.7 第五步:预测

模型验证通过,就可以用来预测新化合物的活性了。但这里还有一个关键问题——预测的可靠性。你的模型在它的“舒适区”内预测是准的,但如果拿来预测一个结构完全不一样的分子,结果就可能离谱。

应用域(Applicability Domain, AD)就是用来回答这个问题的。我建议每个预测结果都带上应用域标记:

  • 如果新化合物在应用域内,预测值可以信任
  • 如果不在,预测值仅供参考,最好建议人家再做实验验证

计算应用域最常用的方法是看新化合物与训练集分子的距离。比如用欧氏距离或Tanimoto相似度,设定一个阈值(比如距离超过训练集平均距离的3倍,就算域外)。

我强烈建议:在输出预测结果时,同时输出置信度指标。比如这样:

# 伪代码示例
compound_id | predicted_pIC50 | in_applicability_domain | confidence_score
C001        | 7.25            | True                    | 0.89
C002        | 6.12            | False                   | 0.34  # 域外,不可靠

这样实验人员一看就知道该重点验证哪些分子,而不是所有预测结果都当真。

2.8 小结

QSAR建模,说难不难,说简单也不简单。五个步骤环环相扣,任何一个环节出了纰漏,最后的结果都可能经不起推敲。数据准备决定了模型的天花板,描述符计算决定了模型能看到什么信息,模型构建是选工具的过程,验证是最后的“质检”,预测则是输出的终点。

我见过太多人把时间花在调超参数和选模型上,却忽略了最基础的数据清洗和验证设计。希望你读完这章,能有一个明确的认知:QSAR的成功,90%靠数据和流程,10%靠算法。把前90%的事做扎实了,后面的10%自然水到渠成。