RDKit 分子多样性挑选实战:rdSimDivPickers 模块的 MaxMin、Leader 与层次聚类算法全解析 科学计算科研机器学习【免费下载链接】rdkitThe official sources for the RDKit library项目地址https://gitcode.com/gh_mirrors/rd/rdkit点击查看免费下载导读本文围绕 RDKit 的rdkit.SimDivFilters.rdSimDivPickers模块展开它是 RDKit 官方提供的多样性/相似性挑选diversity similarity pickingC 扩展模块适用于虚拟筛选、化合物库去冗余、代表性化合物子集选取等典型场景。读完本文你将掌握MaxMinPicker、LeaderPicker、HierarchicalClusterPicker三大核心类的完整 API、参数语义与算法原理并能在自己的化合物指纹数据上直接构造距离矩阵、运行挑选并校验结果。模块定位一个面向多样性挑选的 C 扩展rdSimDivPickers是rdkit.SimDivFilters包下的核心扩展模块。在 Python 侧rdkit/SimDivFilters/__init__.py通过from rdkit.SimDivFilters import rdSimDivPickers导入该扩展并将其中全部成员重新导出from rdkit.SimDivFilters.rdSimDivPickers import *如果扩展不可用例如编译时未启用 Python 包装则置为None以保证包可以正常导入。该模块的 Python 绑定入口定义在 Code/SimDivPickers/Wrap/rdSimDivPickers.cpp其模块级 docstring 为 Module containing the diversity and similarity pickers内部依次包装三个类MaxMinPicker基于 MaxMin 算法的多样性挑选器LeaderPicker基于 Roger Sayle 提出的 Leader 算法球排除法的类似物的挑选器HierarchicalClusterPicker基于层次聚类的多样性挑选器。C 侧的实现位于 Code/SimDivPickers 目录DistPicker.h定义了抽象基类与下三角距离矩阵的索引函数MaxMinPicker.h、LeaderPicker.h、HierarchicalClusterPicker.h分别实现三种挑选策略该目录的 CMakeLists.txt 将三个源文件编译为SimDivPickers库并在启用包装时递归构建WrapBoost.Python与nbWrapnanobind两套绑定。三种挑选器都共享同一个抽象基类DistPicker见 Code/SimDivPickers/DistPicker.h其虚函数pick(distMat, poolSize, pickSize)约定distMat一维下三角距离矩阵double 数组元素个数应为poolSize*(poolSize-1)/2poolSize候选池大小pickSize需要挑选的个数不得超过poolSize返回值为被选中的元素下标RDKit::INT_VECT。矩阵下标通过getDistFromLTM换算ij返回 0ij时取distMat[i*(i-1)/2 j]。MaxMinPicker最大化最小距离的贪心挑选MaxMinPicker是使用频率最高的多样性挑选器对应算法文献为 Ashton 等发表于Quant. Struct.-Act. Relat., 21 (2002), 598-604的 MaxMin 方法。其核心思想记录在 Code/SimDivPickers/MaxMinPicker.h 的类注释中用合适的种子化合物初始化子集置x 1对数据集中剩余的每个化合物计算它与子集中每个化合物之间的距离不相似度并保留每个化合物对应的最小距离选取最小距离最大的那个化合物移入子集x x 1若x k则回到第 2 步。最终结果是两两距离尽可能大的k个化合物这正是多样性子集选取的核心目标。Pick基于完整距离矩阵Python 绑定定义在 Code/SimDivPickers/Wrap/MaxMinPicker.cpp签名与参数如下MaxMinPicker().Pick(distMat, poolSize, pickSize, firstPicks(), seed-1)参数类型默认值说明distMatnumpy 一维数组float64必填下三角距离矩阵poolSizeint必填候选池大小pickSizeint必填挑选个数必须小于poolSize否则抛出ValueErrorfirstPicks序列()预先指定的首批种子下标seedint-1随机数种子小于 0 时使用系统随机源播种包装层要求distMat必须是 numpy 数组PyArray_Check检查失败即抛ValueError并通过PyArray_ContiguousFromObject将其转换为连续的一维 double 数组后才进入 C 的pick()。C 侧会校验池为空、pickSize poolSize或firstPicks中下标超出poolSize时均抛出ValueErrorException。未提供firstPicks时第一个种子由boost::mt19937随机数生成器在[0, poolSize-1]内随机选取Code/SimDivPickers/MaxMinPicker.h 中lazyPick的实现。LazyPick 与 LazyBitVectorPick按需计算距离对于距离矩阵过大、无法一次性驻留内存的场景MaxMinPicker 提供惰性接口——由用户提供一个距离函数算法按需调用LazyPick(distFunc, poolSize, pickSize, firstPicks(), seed-1, useCacheNone)distFunc接收两个下标(i, j)并返回两点间距离。绑定 docstring 特别注明实现内部会缓存距离值客户端无需也不应自行缓存useCache参数已被废弃并忽略调用时会打印 warning。LazyBitVectorPick(objects, poolSize, pickSize, firstPicks(), seed-1, useCacheNone)直接传入一个位向量指纹序列。包装层把序列抽取为std::vectorconst ExplicitBitVect *使用 Code/SimDivPickers/Wrap/PickerHelpers.h 中的pyBVFunctor以 Tanimoto 距离1 - TanimotoSimilarity为距离函数执行同样的 MaxMin 算法。LazyPickWithThreshold(distFunc, poolSize, pickSize, threshold, firstPicks(), seed-1)与LazyBitVectorPickWithThreshold(objects, poolSize, pickSize, threshold, firstPicks(), seed-1)额外接收一个threshold距离阈值当算法算出的候选最小距离 threshold时提前终止返回(picks, threshold)元组——threshold会更新为实际达到的距离值。C 实现中threshold 0表示不提前终止见MaxMinPicker::lazyPick中if (maxOFmin threshold threshold 0.0) break;。测试验证与使用要点测试文件 Code/SimDivPickers/Wrap/testPickers.py 提供了大量可复现的实证test0MaxMin对 1000 个二维随机点调用Pick(self.dMat, 1000, 80, (886, 112))前两个选中的正是种子886、112同时验证了Pick与LazyPick结果一致以及非法的firstPicks如(1012,)、(-1,)会抛出ValueErrortestBitVectorMaxMin同一批位向量分别用LazyPick自写 Tanimoto 距离函数与LazyBitVectorPick在相同seed42下得到完全一致的结果testBitVectorMaxMin3用chembl_cyps.head.fps位于 Code/SimDivPickers/Wrap/test_data挑选 20 个指纹固定seed42可复现确定的下标序列传入firstPicks[374, 720, 690, 339, 875]后结果保持不变说明种子序列被正确采纳testBitVectorMaxMin4验证阈值接口——threshold-1.0时挑选 20 个并返回实际阈值约0.8977threshold0.91时提前终止只返回 13 个且返回阈值 0.91。要点seed决定随机种子的选取固定seed可复现结果不同seed通常得到不同子集见testNonUniqueCrash中的断言。LazyBitVectorPick与等价的自定义距离函数LazyPick在相同种子下结果一致因此当数据是指纹序列时优先使用前者代码更简洁且无需手写距离函数。LeaderPicker球排除式的快速多样性挑选LeaderPicker实现 Roger Sayle 提出的 Leader 算法与球排除法 sphere exclusion 类似包装代码见 Code/SimDivPickers/Wrap/LeaderPicker.cpp算法实现位于 Code/SimDivPickers/LeaderPicker.h。核心 APILeaderPicker().LazyBitVectorPick(objects, poolSize, threshold, pickSize0, firstPicks(), numThreads1) LeaderPicker().LazyPick(distFunc, poolSize, threshold, pickSize0, firstPicks(), numThreads1)与 MaxMin 最大的不同在于threshold是必填位置参数且其含义是距离即1 - similarity而不是相似度。例如 Tanimoto 相似度阈值 0.8 对应 distance 阈值 0.2LeaderPicker 文档字符串中给出的测试均使用threshold0.8、0.9这类距离值。pickSize默认为 0此时算法会一直挑选直到池子耗尽等价于pickSize poolSize见LeaderPicker::lazyPick中if (!pickSize) pickSize poolSize;。numThreads参数当前被忽略绑定 docstring 明确注明。算法流程单线程实现维护一个未选列表每轮取出列表首个元素作为新 leader种子用距离函数将其与列表中所有剩余元素逐一比较凡是距离 threshold的元素全部从列表中剔除排斥进该 leader 的球内直到列表为空或达到pickSize。由于最终任意两个被选元素之间的距离都严格大于threshold结果天然满足多样性约束。测试验证Code/SimDivPickers/Wrap/testPickers.py 中testBitVectorLeader1提供了清晰的验证逻辑对同一批chembl_cyps.head.fps指纹threshold0.8距离时选出 146 个threshold0.9时仅选出 14 个——阈值越大每个 leader 的排斥半径越大子集越小测试随后遍历所有配对断言任意两两之间的 Tanimoto 距离 threshold直接验证了算法的核心不变量pickSize10时恰好返回 10 个且同样满足两两距离约束。testLazyLeader用简单函数i - j作为距离验证LazyPick(func, 100, 20)返回[0, 21, 42, 63, 84]——即每个新 leader 会把距离 20 以内的元素全部剔除间隔 21 的等差序列正是预期结果。HierarchicalClusterPicker先聚类、再取代表元HierarchicalClusterPicker基于层次聚类做多样性挑选头文件见 Code/SimDivPickers/HierarchicalClusterPicker.h实现沿用Code/ML/Cluster下的 Murtagh 聚类代码。聚类方法与构造参数构造函数接收clusterMethod参数Python 侧通过HierarchicalClusterPicker.ClusterMethod枚举暴露绑定见 Code/SimDivPickers/Wrap/HierarchicalClusterPicker.cpp枚举值C 常量说明ClusterMethod.WARDWARD 1Ward 法最小方差ClusterMethod.SLINKSLINK 2单连接最近邻ClusterMethod.CLINKCLINK 3完全连接最远邻ClusterMethod.UPGMAUPGMA 4非加权平均连接ClusterMethod.MCQUITTYMCQUITTY 5McQuitty 法ClusterMethod.GOWERGOWER 6Gower 法ClusterMethod.CENTROIDCENTROID 7质心法两个方法Pick 与 Clusterpkr rdSimDivPickers.HierarchicalClusterPicker(rdSimDivPickers.ClusterMethod.WARD) pkr.Pick(distMat, poolSize, pickSize) # 返回代表元下标列表 pkr.Cluster(distMat, poolSize, pickSize) # 返回 clusters每个簇为一个下标列表Pick先将整个池子按指定方法做层次聚类当簇的数目合并到pickSize时停止然后在每个簇内计算各元素到簇内其余元素距离的平方和选取平方和最小最接近质心的元素作为该簇代表元。Cluster直接返回聚类结果每个元素是一个下标列表可用作后续分析。注意两点源码与测试均有印证距离矩阵会被算法修改头文件注释明确指出 this matrix WILL BE ALTERED during the picking。Python 包装层因此在进入 C 前用PyArray_CopyFromObject拷贝一份避免破坏用户传入的矩阵见HierarchicalPicks与HierarchicalClusters中的注释与实现。Pick要求pickSize poolSize包装层在HierarchicalPicks中显式检查并抛ValueError。测试验证Code/SimDivPickers/Wrap/testPickers.py 中的test1HierarchPick使用测试数据 Code/SimDivPickers/Wrap/test_data/points.csv带标签的二维点集Cluster(self.dMat, n, 2)划分出的两个簇内标签完全一致聚类正确而Pick返回(1, 30)作为两个簇的代表元。testIssue208与testInts则验证了对相同输入重复调用结果稳定且整数距离矩阵也能正确处理。纯 Python 层的补充接口TopNOverallPicker 与 SpreadPicker除 C 扩展外rdkit.SimDivFilters包还提供纯 Python 实现的相似性挑选类定义在 rdkit/SimDivFilters/SimilarityPickers.py适用于给定探针指纹、从库中挑选最相似化合物的场景TopNOverallPicker(numToPick10, probeFpsNone, dataSetNone, simMetricDataStructs.TanimotoSimilarity)对库中每个指纹计算其与所有探针相似度的最大值作为该指纹得分用 rdkit/DataStructs/TopNContainer.py 维护 Top-N 容器最终返回得分最高的numToPick个(fp, score)对结果按得分降序排列。SpreadPicker(numToPick10, probeFpsNone, dataSetNone, simMetricDataStructs.TanimotoSimilarity, expectPicklesTrue, onlyNamesFalse)为每个探针维护一个独立 Top-N 列表再以轮转取每行当前最优、跳过已被取走的元素的方式挑选使结果在多个探针间分散分布这正是其名称含义。expectPicklesFalse时允许dataSet为可转换为位向量的字符串onlyNamesTrue时结果只保留_fieldsFromDb[0]名称。两类 picker 均为惰性求值构造时_picks为None首次调用len(picker)或picker[i]才触发MakePicks()见GenericPicker基类与 rdkit/SimDivFilters/UnitTestSimilarityPickers.py 的test_TopNOverallPicker、test_SpreadPicker对惰性行为的断言。其 docstring 自带完整的 doctest 示例连接RDTestDatabase的simple_mols1表、生成 RDKFingerprint、用COC与CC(O)O作探针可直接作为上手模板。端到端实战从指纹到多样性子集综合以上 API下面给出一个可直接运行的完整流程涵盖构建池子 → 计算距离 → 多样性与相似性挑选 → 结果校验import numpy from rdkit import Chem, DataStructs from rdkit.SimDivFilters import rdSimDivPickers as rdsimdiv from rdkit.SimDivFilters.SimilarityPickers import TopNOverallPicker # 1. 构建化合物池与指纹 smis [CCO, CCOC, CC(O)O, CCN, C1CCCCC1, c1ccccc1, C#N, CC(C)C] mols [Chem.MolFromSmiles(s) for s in smis] fps [Chem.RDKFingerprint(m) for m in mols] # 2. 位向量版本MaxMin 多样性挑选固定种子可复现 picker rdsimdiv.MaxMinPicker() picks picker.LazyBitVectorPick(fps, len(fps), 4, seed42) print(MaxMin picks:, picks) # 3. 阈值版本同时返回终止时达到的距离 picks, threshold picker.LazyBitVectorPickWithThreshold(fps, len(fps), 4, -1.0, seed42) print(threshold reached:, threshold) # 4. Leader 算法按距离阈值排斥结果两两距离必大于阈值 lp rdsimdiv.LeaderPicker() ids lp.LazyBitVectorPick(fps, len(fps), 0.5) # 注意0.5 是距离1-相似度 for i in range(len(ids)): for j in range(i): d 1.0 - DataStructs.TanimotoSimilarity(fps[ids[i]], fps[ids[j]]) assert d 0.5 print(Leader picks:, ids) # 5. 层次聚类挑选构造欧氏距离矩阵可改用 rdMetricMatrixCalc n len(fps) dist_mat numpy.zeros(n * (n - 1) // 2, d) for i in range(n - 1): for j in range(i 1, n): d 1.0 - DataStructs.TanimotoSimilarity(fps[i], fps[j]) dist_mat[i * (i - 1) // 2 j] d # 注意仅填充下三角 hp rdsimdiv.HierarchicalClusterPicker(rdsimdiv.ClusterMethod.WARD) print(Hierarchical representative picks:, hp.Pick(dist_mat, n, 2)) print(Hierarchical clusters:, hp.Cluster(dist_mat, n, 2)) # 6. 探针驱动的相似性挑选纯 Python 层 probe Chem.RDKFingerprint(Chem.MolFromSmiles(CCO)) top TopNOverallPicker(numToPick3, probeFps[probe], dataSetfps) for fp, score in top: print(top match, score , score)运行前提需要已安装并正确编译的 RDKitrdSimDivPickers为 C 扩展需在构建时启用 Python 包装参见 Code/SimDivPickers/CMakeLists.txt 中的RDK_BUILD_BOOST_PYTHON_WRAPPERS/RDK_BUILD_NANOBIND_WRAPPERS选项。欧氏距离矩阵可借助rdkit.DataManip.Metric.rdMetricMatrixCalc的GetEuclideanDistMat直接生成测试testPickers.py即采用此方式若使用Pick系列方法务必遵守下三角一维布局约定。参数速查与常见陷阱场景关键参数注意事项MaxMinPickdistMat为下三角一维数组pickSize poolSizefirstPicks下标越界或为负会抛ValueErrorMaxMinLazyPickdistFunc(i, j)返回距离内部缓存距离客户端不要重复计算useCache已废弃忽略MaxMin 位向量接口objects为ExplicitBitVect序列与等价LazyPick结果一致固定seed复现MaxMin 阈值接口threshold为距离达到阈值提前终止返回元组(picks, actual_threshold)Leaderthreshold是距离不是相似度结果任意两两距离 thresholdpickSize0表示选完HierarchicalclusterMethod枚举 7 选 1Pick会修改矩阵包装层自动拷贝Pick要求pickSize poolSizeTopNOverall / SpreadprobeFps、dataSet、simMetric惰性求值SpreadPicker在探针间分散结果最常见的两类错误其一把 Leader 的threshold当作相似度传入导致排斥半径错误其二distMat布局不按下三角一维填充或pickSize不小于poolSize均会触发ValueError。对照上述速查表即可快速定位。小结rdSimDivPickers模块以统一的下三角距离矩阵 距离函数抽象承载了三种互补的挑选策略MaxMin 以贪心方式最大化子集内部最小距离适合精确的多样性优化Leader 以距离阈值排斥邻近点速度快、结果天然满足距离下限适合大规模库快速去冗余层次聚类则把挑选问题转化为聚类 取代表元并能顺带产出簇划分。配合纯 Python 层的TopNOverallPicker/SpreadPicker做探针驱动的相似性挑选RDKit 的SimDivFilters家族可以覆盖化合物库设计的绝大多数挑选需求。想深入了解实现细节的读者可继续阅读 Code/SimDivPickers/MaxMinPicker.h、Code/SimDivPickers/LeaderPicker.h、Code/SimDivPickers/HierarchicalClusterPicker.h 及对应的包装与测试文件。赞分享科学计算科研机器学习【免费下载链接】rdkitThe official sources for the RDKit library项目地址https://gitcode.com/gh_mirrors/rd/rdkit点击查看免费下载相关推荐RDKit 层次聚类核心模块解析rdkit.ML.Cluster.Clustering 与 Murtagh 算法实战指南RDKit 层次聚类核心模块解析rdkit.ML.Cluster.Clustering 与 Murtagh 算法实战指南 导读 rdkit.ML.Cluste科学计算科研机器学习RDKit Murtagh 层次聚类模块解析从 Fortran 算法到 Python 聚类树RDKit Murtagh 层次聚类模块解析从 Fortran 算法到 Python 聚类树 导读 RDKit 的 rdkit.ML.Cluster.Murt科学计算科研机器学习RDKit 分子指纹聚类指南ClusterMols 模块 API 与 Murtagh 层次聚类实战RDKit 分子指纹聚类指南ClusterMols 模块 API 与 Murtagh 层次聚类实战 导读 本文围绕 RDKit 官方文档 rdkit.Chem科学计算科研机器学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考