You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的分子Morgan指纹随比特数增加未呈现平台期?

关于Morgan指纹比特向量尺寸与占用比特数振荡问题的解答

问题背景

我是 cheminformatics 及编程领域新手,首个项目采用Morgan指纹作为机器学习模型的特征,但找不到合适的比特向量尺寸。我试图通过分析不同长度下的最大占用比特数来确定合适尺寸,具体步骤如下:

  1. 编写函数max_on_bits,输入SMILES列表和比特向量长度,生成所有SMILES的指纹并返回最大占用比特数:
def max_on_bits(smiles_list, nbits):
    on_bits = []

    for smiles in smiles_list:
        mol = Chem.MolFromSmiles(smiles)
        fp = AllChem.GetMorganFingerprintAsBitVect(mol, 
                                                   3, 
                                                   nBits=nbits, 
                                                   useChirality=True, 
                                                   useFeatures=True)

        num_on_bits = sum(np.array(fp))
        on_bits.append(num_on_bits)
        
    return max(on_bits)
  1. 遍历1024到20482、步长256的比特数范围,调用函数获取占用数据:
nbits_range = range(1024, 20483, 256)
occupancy = []
for nbits in nbits_range:
    occupancy.append(max_on_bits(smiles_list, nbits))
  1. 绘图展示结果:
import matplotlib.pyplot as plt

plt.plot(nbits_range, occupancy)
plt.xlabel("Bit Vector Size")
plt.ylabel("Maximum Number of bits occupied")
plt.grid()
plt.show()

但得到的曲线未呈现平台期,反而呈振荡状态,想问这是代码问题还是Morgan指纹的固有特性?


解答

振荡原因:Morgan指纹的固有特性,而非代码问题

振荡的核心是Morgan指纹的哈希映射机制导致的随机波动:

  • Morgan指纹先提取分子的子结构特征,再通过哈希函数将这些子结构映射到长度为nbits的比特向量中。哈希函数的输出会随nbits变化而改变——同一个子结构在不同nbits下会被映射到不同的比特位。
  • 当nbits增大时,理论上哈希冲突概率降低,但随机性可能导致某几个分子的子结构刚好在新的nbits下出现更多无重叠的映射,使占用比特数临时上升;反之,偶尔也会出现更多子结构被映射到同一比特位(冲突),导致占用比特数下降。这种随机波动就形成了振荡曲线。

代码优化建议(不影响振荡问题,仅提升效率与稳定性)

你的代码逻辑没问题,但可以做两处优化:

  1. 直接用fp.GetNumOnBits()获取占用比特数,无需转成numpy数组求和,更高效;
  2. 过滤无效SMILES(MolFromSmiles返回None的情况),避免报错。

优化后的函数示例:

def max_on_bits(smiles_list, nbits):
    max_bits = 0
    for smiles in smiles_list:
        mol = Chem.MolFromSmiles(smiles)
        if not mol:
            continue  # 跳过无效SMILES
        fp = AllChem.GetMorganFingerprintAsBitVect(
            mol, 3, nBits=nbits, useChirality=True, useFeatures=True
        )
        current_bits = fp.GetNumOnBits()
        if current_bits > max_bits:
            max_bits = current_bits
    return max_bits

如何选择合适的比特向量尺寸

不要仅关注最大占用比特数,建议从以下角度判断:

  • 看整体数据集的平均占用率(所有分子的平均占用比特数/nbits),维持在0.1~0.3之间可平衡冲突率和向量稀疏性;
  • 测试常用尺寸(如1024、2048、4096),结合你的ML模型性能(准确率、AUC等)选择——当性能不再随尺寸增大而提升时,该尺寸即为合适值;
  • 若追求更低冲突率,可使用计数型Morgan指纹(GetMorganFingerprint返回字典形式的计数指纹),再转换为固定长度向量,但计算成本更高。

内容的提问来源于stack exchange,提问作者Arko Mohari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:52:43