3. 化合物数据集:ChEMBL、ZINC、PubChem
做化合物生成,数据就是你的燃料。没有高质量的数据集,GAN学出来的东西就是一堆乱码。我个人最早踩过的坑,就是拿了一个小样本库去训模型,结果生成的分子全是环丙烷和乙烷的排列组合——毫无生物活性价值。
今天咱们聊聊三个最常用的公开数据集:ChEMBL、ZINC、PubChem。它们各有侧重,就像工具箱里的不同扳手,用对了地方才能省力气。
3.1 三个数据集的核心差异
先说结论:ChEMBL主打药物相关活性数据,ZINC主打类药性分子库,PubChem则是最全的公共化学数据库。咱们做GAN生成化合物,通常优先考虑ChEMBL或ZINC的子集。
| 维度 | ChEMBL | ZINC | PubChem |
|---|---|---|---|
| 数据规模 | ~200万 (活性化合物) | ~2亿 (类药分子) | ~1.1亿 (全部公开) |
| 数据来源 | 已发表的药物、临床候选 | 商业/学术供应商库 | 全球研究者提交+数据库对接 |
| 注释丰富度 | 高 (靶点、IC50、Kd等) | 中 (理化性质、可购买性) | 高 (活性+文献+谱图) |
| 适用GAN场景 | 活性分子生成、靶点优化 | 虚拟筛选、先导化合物优化 | 全库对比、监督学习补充 |
我一般建议新手从ChEMBL入手。为什么?因为它包含的化合物都经过生物活性验证,你生成的分子找ChEMBL里的结构做相似性分析,可信度更高。当然,如果你需要海量负样本做对比,ZINC的“化合物药性过滤子集”就是更好的选择。
3.2 ChEMBL:活性数据的金标准
ChEMBL由欧洲生物信息学研究所维护,每半年更新一次。它的核心优势是活性数据经过人工校验,不像PubChem那样很多数据是自动爬取的,质量参差不齐。
下载方式很简单,直接去官网或者用Python库。我习惯用chembl_webresource_client,一行代码就拉数据:
from chembl_webresource_client.new_client import new_client
molecules = new_client.molecule
# 获取具有明确SMILES且分子量在250-500之间的化合物
results = molecules.filter(
molecule_structures__canonical_smiles__isnull=False,
mw_freebase__gte=250,
mw_freebase__lte=500
).only(['molecule_chembl_id', 'molecule_structures'])
这里要注意,ChEMBL的SMILES字段是canonical_smiles,但有时候它会返回多个同分异构体,建议你只保留parent_chembl_id对应的那条。我曾经没做这个去重,结果数据里混了30%重复结构,训出来的GAN几乎把每个分子都生成了两次。
docker run -d --name chembl -p 5432:5432 \
-e POSTGRES_PASSWORD=chembl \
chembl/chembl:latest
3.3 ZINC:类药性分子的大超市
如果说ChEMBL是精品店,那ZINC就是批发市场。ZINC目前有2亿多个可购买或可合成的分子,按“药性”做了不同筛选层级:ZINC20、ZINC Clean Leads、ZINC Drug-like。每个层级都有不同的过滤条件。
我最常用的是ZINC Clean Leads,大约2千万分子,直接满足类药五原则。而且它自带“可购买性”标签,这对后期做化合物合成验证非常有用。你想想看,模型生成了100个分子,最终只能合成10个,那前期的数据质量就决定了这10个的下限。
ZINC的数据格式很友好,每个分子都有:
- ZINC ID(唯一标识)
- SMILES(标准异构简写)
- LogP、MW、tPSA(理化性质)
- Purchasable Flag(可购买标记)
下载整个ZINC Clean Leads的SMILES文件:
wget https://zinc15.docking.org/substances/subsets/clean-leads.smi.gz
gunzip clean-leads.smi.gz
然后你就可以用RDKit直接读取了。对了,ZINC的SMILES里有时会带[C@H]这样的立体化学标记,如果你想做GAN生成,建议先RemoveStereochemistry,否则模型学到的空间复杂度太高,生成容易失败。我刚开始就栽在这上面了。
3.4 PubChem:大而全的数据沼泽
PubChem是美国NCBI维护的,收录了1.1亿化合物。说实话,我不太建议直接用PubChem全集训GAN,因为数据太杂了:有农药、有电池材料、有食品添加剂,甚至有些是重复提交的假结构。但PubChem的价值在于辅助验证和结果对比。
比如你GAN生成了一批分子,想知道它们是不是全新的?可以拿PubChem的Compound ID(CID)列表做唯一性检查。PubChem提供FTP下载,也有REST API。
# 查询一个SMILES在PubChem中是否存在
import requests
smiles = "CCO" # 乙醇
url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/smiles/{smiles}/cids/JSON"
resp = requests.get(url)
if resp.status_code == 200:
data = resp.json()
print("CID:", data['IdentifierList']['CID'][0])
else:
print("Not found")
3.5 数据集选择与预处理流程
讲到这里,你应该明白三个数据集怎么用了。下面这张图总结了从原始数据到GAN训练集的典型流程:
这里有一个关键步骤很多人会忽略:把清洗后的SMILES去重并标准化。我经常用RDKit来做:
from rdkit import Chem
from rdkit.Chem import SaltRemover
def clean_and_standardize(smiles):
mol = Chem.MolFromSmiles(smiles)
if mol is None:
return None
# 移除盐和溶剂
remover = SaltRemover.SaltRemover()
mol = remover.StripMol(mol, dontRemoveEverything=True)
# 规范化:去立体化学
Chem.RemoveStereochemistry(mol)
# 重新生成规范SMILES
return Chem.MolToSmiles(mol, canonical=True, isomericSmiles=False)
嗯,这一步之后,你会发现数据量能减少10%-30%——但质量提升了一个量级。我自己的项目里,预处理前GAN的FID(Fréchet Inception Distance)是15.2,预处理后降到了7.8。
3.6 三个数据集的实战组合拳
最后分享一个我目前在用的组合策略,供你参考:
- 用ChEMBL做种子训练:取10万个活性分子(IC50 ≤ 100nM),生成第一批GAN候选。
- 用ZINC Clean Leads做负样本:随机抽20万个与正样本分子量分布一致的非活性分子,训练判别器。
- 用PubChem做唯一性验证:每次生成后,拿5000个候选结构去PubChem查CID,确保没有已知化合物。
这样做下来,你的GAN既有活性引导,又有类药性约束,还能保证新颖性。我之前带的一个实习生,用这套流程做出来一个全新骨架的EGFR抑制剂候选,对接打分比已知药物还高0.3 kcal/mol。
核心要点:
- ChEMBL → 活性数据,适合正样本
- ZINC → 类药性数据,适合负样本或大库
- PubChem → 全库对比,适合新颖性检查
- 别偷懒,预处理(去盐、去立体化学、去重)至少跑一遍