5.1 相似性测度:Tanimoto 与它的同行 本节摘要:相似性测度把两个指纹的交叠折算成零到一之间的分数,Tanimoto 系数是其中事实标准。本节先手算一笔比特账建立直觉,再认识 Dice、Cosine 等同行,最后用"给失去供货的先导物找替身"的完整案例演示 top-k 检索与得分判读,并把"相似性原理"的边界讲清楚。 排架间的第一堂实操课。4.2 节你学会了把分子压成比特串,本节回答下一个问题:两个比特串怎么比?这一步看似只差一个公式,实则是整个相似检索科学性的所在——比得没道理,检索就只是装饰。 先算一笔比特账 Tanimoto 系数的定义一句话说完:共同置位数除以两者置位数之和减去共同部分。
本节摘要:相似性测度把两个指纹的交叠折算成零到一之间的分数,Tanimoto 系数是其中事实标准。本节先手算一笔比特账建立直觉,再认识 Dice、Cosine 等同行,最后用"给失去供货的先导物找替身"的完整案例演示 top-k 检索与得分判读,并把"相似性原理"的边界讲清楚。
排架间的第一堂实操课。4.2 节你学会了把分子压成比特串,本节回答下一个问题:两个比特串怎么比?这一步看似只差一个公式,实则是整个相似检索科学性的所在——比得没道理,检索就只是装饰。
Tanimoto 系数的定义一句话说完:共同置位数除以两者置位数之和减去共同部分。设分子甲的指纹有 a 位为正,分子乙有 b 位为正,共同置位 c 位,则:
Tanimoto = c / (a + b - c)
代入真实一点的数字练一遍:某指纹长度两千位,甲置位 40 位,乙置位 55 位,逐位比对发现 32 位同时为正。共同部分 32,并集部分 40 加 55 减 32 等于 63,Tanimoto 等于 32 除以 63,约零点五一。注意这个分数的分母是并集不是全长度——分子级的细节在两千位的背景里会被稀释,用并集做分母等于是"在两者触及的范围内"衡量重合。
这个设计带来 Tanimoto 的招牌脾气:对小分子宽容、对大分子苛刻。小分子置位少,多一位共同特征,分数显著上涨;大分子指纹本来就密,同样的结构差异在分数上几乎不动。比较分子量悬殊的两个分子时,Tanimoto 会系统性偏低——不是 bug,是它对"比例"敏感的天性,判读时须记得。
它的两位同行也各有分工。Dice 系数把分母换成"两者置位数算术平均"(等价于 2c 除以 a 加 b),数值总比 Tanimoto 高半头,对共同部分更慷慨,生物学文献里更常见。Cosine 系数把分母换成几何平均(根号下 a 乘 b),介于两者之间,向量空间视角的产物。三者的排序大体一致,工程上通常"选一个、用到底、别中途换"——换系数导致的分数漂移,常被误判成检索质量变化。
背景。项目的一个先导化合物供应商突然断供,重新合成周期要半年。药化主管的备选方案是"在采购库里找长得像的分子直接买"——结构近似则活性近似(相似性原理),买回来直接进复筛。库存文件里有五万个可采购分子,人工翻看不可能。
操作。查询分子与全库全部生成摩根指纹(半径二、两千位),算批量相似度,取前五:
from rdkit import Chem from rdkit.Chem import AllChem from rdkit import DataStructs query = Chem.MolFromSmiles("CC(C)Cc1ccc(cc1)C(C)C(=O)O") # 布洛芬式先导物 qfp = AllChem.GetMorganGenerator().GetFingerprint(query) library_smiles = purchasable_list # 五万个可采购分子 lib_mols = [Chem.MolFromSmiles(s) for s in library_smiles] lib_fps = [AllChem.GetMorganGenerator().GetFingerprint(m) for m in lib_mols] scores = DataStructs.BulkTanimotoSimilarity(qfp, lib_fps) ranked = sorted(zip(scores, library_smiles), reverse=True)[:5] for s, smi in ranked: print(f"{s:.3f} {smi}")
结果。典型输出形如:零点八六的一个近亲(只在烷基链长上差一个碳)、零点七三的两个(苯环上多一个甲基取代)、零点五几的两个(羧酸换成了四氮唑等生物电子等排体)。分数梯度与结构差异完全同向:链长微调 > 单取代基增减 > 关键官能团替换。
解读。三点判读经验。其一,阈值看背景分布:五万分子的库相似度多在零点一以下,零点七以上通常只有个位数命中——绝对数值无意义,与背景拉开差距才有意义;业内常用的粗口径是零点八五以上算"极像",零点五到零点七算"骨架近邻"。其二,相似不等于同活性:相似性原理是概率陈述,四氮唑替换羧酸这类"电子等排"操作会动到酸性基团,pKa 与结合模式都可能翻车——替身买回来必须复筛,检索只是把命中率从大海捞针提到近海捞针。其三,指纹选择决定"像"的定义:摩根指纹偏拓扑相似,药效团指纹偏作用方式相似;找替身时若关心结合模式,值得两套指纹各跑一遍取交集。
变式。三个常用升级。子结构约束混合检索:"必须保留羧酸"用 SMARTS 先过滤,再在余集内做相似排序——硬约束与软相似各管一段。特征指纹加权:对药效关心的特征类型(氢键供体环境、芳香环)加权重,让"像"向药效倾斜。反向最近邻:不是找像查询的分子,而是问"这个分子最像库里谁"——数据清洗时识别录入错误分子的妙招。
单个 Tanimoto 分数几乎没有绝对含义,它的一切判读都要对照背景分布——这是相似检索最容易被忽略的统计常识。
把查询分子与全库逐一算分,画一张分布图,你会发现它强烈右偏:绝大多数分子挤在零点一以下(毕竟随便两个药物样分子拓扑重合有限),中部拖出长尾,右上角稀稀拉拉几个真正的高分。检索的全部艺术就在这张图的右上角。由此推出两个实用口径:阈值带——把分布的前千分之一位置当"极像带"(万级库里通常落在零点七附近),前百分之五当"近邻带";倍数口径——候选得分减去背景中位数再除以四分位距,类似标准分的读法,跨库比较时比绝对分数稳健得多。

这套背景化读法还有个副产物:分布形状本身是质检器。某个查询分子在库里拉出一片异常肥的高分尾巴,先别高兴——它多半是"超级常见骨架"(苯环、脂肪链这类万物皆像的分子),检索结果会被它的平庸相似度淹没;换掉查询或改用药效团指纹,名单质量立刻不同。分布是检索的诊断书,先看图再拿名单,是老手的顺序。