基于片段的3D分子生成扩散模型 - AutoFragDiff 评测

AutoFragDiff 是一个基于片段的,自回归的,口袋条件下的,3D分子生成扩散模型。

AutoFragDiff方法来源于文章《Autoregressive fragment-based diffusion for pocket-aware ligand design》,由加州大学的Mahdi Ghorbani等人于2023年11月3日发表在OpenReview,是NeurIPS2023 Poster文章。

其中,有两名作者来自罗氏。

文章链接为:Autoregressive fragment-based diffusion for pocket-aware ligand design | OpenReview。

一、AutoFragDiff 模型介绍

传统的,基于口袋的3D分子生成网络的常用方法是自回归模式,模型放置原子和原子键是迭代的,逐个进行。

但是这种方式会导致误差的积累,同时生成速度较慢,生成苯环分子也需要6个步骤。而使用基于分子片段的自回归方法可以避免这个问题。

作者使用使用几何矢量感知器和自回归扩散模型 Autoregressive Diffusion Models (ARDMs),以自回归的模式,分子骨架和蛋白质口袋为条件下,逐个预测新分子片段的原子类型和空间坐标。

 在这一过程中,AutoFragDiff允许每个片段经历去噪过程,预测原子坐标和原子类型。该方法改善了生成的3D 分子的局部几何形状,同时保持与蛋白质靶标的高预测结合亲和力。 如下示意图:

此外,AutoFragDiff不是依赖固定的片段库,而是动态生成片段,为生成的片段多样性提供了灵活性。

该模型可以从用户提供的起始分子骨架进行支架延伸,即适用于骨架生长/延伸任务,既可以使用于口袋限制下,也可以使用在没有口袋限制的情况。即,AutoFragDiff可以依据提供的分子片段,在有口袋和没有口袋的条件下,进行分子扩展生成完整分子。

二、模型性能

作者统计了AutoFragDiff生成分子中环的键角与二面角分布与CrossDock数据集中分布的Jensen-Shannon Divergence(JSD,该值越小越好),结果显示,AutoFragDiff生成环与真实数据的更像,生成的分子结构更真实,要优于其他模型。如下表:

除了环状的原子键,作者在SI中也提供了其他原子键的JSD相似度结果,如下表。

从表中看,TargetDiff的结果更好一些,但是AutoFragDiff和TargetDiff都优于3DSBDD和Pocket2Mol。

作者同时比较了AutoFragDiff模型与3D-SBDD,Pocket2Mol等模型的Vina score, 多样性,可合成性和成药性指标,如下图。

其中,AutoFragDiff生成分子的Vina score要优于其他对比模型,但是成药性,可合成性,多样性指标上,弱于其他对比模型。

然后作者给了一个具体的例子,1a2g,如下图。感觉生成的分子还行。对比原有的骨架,Vina score也下降很多。

由于是会议的poster文章,作者给出的结果并不多。在SI中,提供了生成分子与口袋原子“碰撞”个数,strain energy,和相互作用原子的信息。

AutoFragDiff 分子与口袋原子的平均冲突为 6.7 次,优于其他基于扩散的模型(TargetDiff 9.2 和 DiffSBDD 平均 11.8)。 

非扩散模型 Pocket2Mol 和 3DSBDD 每个分子平均有 5.7 次和 3.9 次冲突,而 CrossDock 数据集的测试集平均有 4.8 次冲突, 如下图:

同样,非扩散模型Pocket2Mol 和 3DSBDD 通常生成比基于扩散的模型具有更低应变能的分子,构象更加合理,如下图。

考虑到相互作用类型,TargetDiff 分子具有最多的氢键供体和受体,而 AutoFragDiff 和 TargetDiff 都显示出最多的疏水性和范德华相互作用,与 CrossDock 测试集分子相当,如下图。

三、模型评测

3.1 环境安装

作者提供了github 链接:

GitHub - keiserlab/autofragdiff

复制代码:

git clone https://github.com/keiserlab/autofragdiff.git

项目目录结构:

.
├── LICENSE
├── README.md
├── __init__.py
├── analysis
├── analyze_generated_pocket_mols.py
├── analyze_scaffolds_generated.py
├── assets
├── data
├── extend_scaffold_crossdock.py
├── fpscores.pkl.gz
├── generate_pocket_molecules.py
├── notebooks
├── sample_crossdock_mols.py
├── sample_from_pocket.py
├── sampling
├── src
├── train_anchor_predictor.py
├── train_frag_diffuser.py
└── utils8 directories, 12 files

环境安装

conda create -n AutoFragDiff python=3.10
conda activate AutoFragDiff 

选择python=3.10避免pytroch_lightning的版本兼容问题。

安装 rdkit, biopython等。

pip3 install rdkit
conda install -c conda-forge openbabel
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.8 -c pytorch -c nvidiapip install biopython==1.75
pip install biopandas
pip install networkx
pip install py3dmol
pip install scikit-learn
pip install tensorboard
pip install wandb
pip install tqdm
conda install pytorch-lightning# 以下是pytorch_lightning的参考模块
conda install pytorch-lightning=1.6 -c conda-forge
conda install -c conda-forge packaging
pip install tqdm
pip install pyyaml
pip install protobuf
pip install absl-pyconda install pyg -c pyg
pip install meeko
conda install -c bioconda vina

Meeko 读取 RDKit 分子对象并写入 PDBQT 字符串,将对接输出转换为 RDKit 分子和 SD 文件,而不会丢失键序,在python中经常用于Vina对接的预处理和结果处理。

安装QuickVina2需要另外创建一个环境MGLTools:

wget https://github.com/QVina/qvina/raw/master/bin/qvina2.1
chmod +x qvina2.1 conda create -n MGLTools -c bioconda mgltools

安装AutoDockTool

python -m pip install git+https://github.com/Valdes-Tresanco-MS/AutoDockTools_py3

安装fpocket,在生成分子时用于确定口袋:

conda config --add channels conda-forge
conda install fpocket

注意,在macOS下面mgltools源和fpocket没有符合的包,不适配macOS系统。。。因此,建议本项目使用ubuntu系统测试。

以下均为ubuntu的测试结果。另外,这个项目由于提供的是pip安装方式,并且没有明确的版本信息,pyg,torch等安装包是相互之间有版本依赖关系的,因此安装起来会困难一些,多尝试就好。

3.2 下载作者训练好的checkpoint

作者训练完成的checkpoint文件下载

作者提供了训练好的模型checkpoint,链接为:https://drive.google.com/drive/folders/1DQwIfibHIoFPGJP6aHBGiYRp87bCZFA0

将两个checkpoint都下载,然后放置在./目录下。

3.3 生成分子测试 - 2z3h

作者提供了一个notebook形式的,里面展示了crossdocked_pocket10第一个体系,即2z3h,的基于口袋的分子生成,文件名为sample_for_pocket.ipynb。

sample_for_pocket.ipynb放置在./notebook文件夹内吗。因此,首先将工作目录切换到./notebook内。

测试体系2z3h.pdb,我已经提前下载到文件内,其口袋附近结构如下图(在晶体中,原口袋内有一个小分子BLO,我这里一并放上去了,只作为展示用途,作者提供的案例中并没有):

首先使用fpcoket寻找口袋,在终端运行:

fpocket -f 2z3h.pdb

由于这里的2z3h.pdb只包含了口袋,因此,找到的口袋数量不多,一个是小分BEO所在的位置,序号为1,一个在其背后,序号为2,如下图:

对口袋进行加H,生成2z3h_H.pdb,终端运行如下命令:

reduce -Quiet -NOFLIP 2z3h.pdb > 2z3h_H.pdb

注:我这的reduce是之前安装的AmberTools23。如果没有安装过,需要安装reduce或者AmberTools23。当然,也可以另外使用pymol等工具加氢以后保存成2z3h_H.pdb。

以下为sample_for_pocket.ipynb里面的内容。

首先导入相关模块:

import numpy as np
import pandas as pd
import os
from tqdm import tqdm 
from itertools import combinationsfrom rdkit import Chem
import torch
import time
import shutil
from pathlib import Path
import torch.nn.functional as F
import syssys.path.append('../')from utils.volume_sampling import sample_discrete_number
from utils.volume_sampling import remove_output_files, run_fpocket, extract_values
from utils.templates import get_one_hot, get_pocket
from utils.templates import add_hydrogens, extract_hydrogen_coordinatesfrom src.lightning_anchor_gnn import AnchorGNN_pl
from src.lightning import AR_DDPM
from src.const import prot_mol_lj_rm, CROSSDOCK_LJ_RM
from src.noise import cosine_beta_schedule
from scipy.spatial import distance
from Bio.PDB import PDBParser
from Bio.PDB.Polypeptide import is_aa, three_to_onefrom analysis.reconstruct_mol import reconstruct_from_generated
from analysis.vina_docking import VinaDockingTaskfrom rdkit.Chem import rdmolfiles
from sampling.sample_mols import generate_mols_for_pocketfrom openbabel import openbabel
import tempfilefrom utils.volume_sampling import extract_alpha_spheres_coords
from utils.visuals import write_xyz_file, visualize_3d_pocket_molecule, get_pocket_mol

设定原子,电荷,氨基酸的索引字典,还有就是原子的范德瓦尔斯半径。

atom_dict =  {'C': 0, 'N': 1, 'O': 2, 'S': 3, 'B': 4, 'Br': 5, 'Cl': 6, 'P': 7, 'I': 8, 'F': 9}
idx2atom = {0:'C', 1:'N', 2:'O', 3:'S', 4:'B', 5:'Br', 6:'Cl', 7:'P', 8:'I', 9:'F'}
CROSSDOCK_CHARGES = {'C': 6, 'O': 8, 'N': 7, 'F': 9, 'B':5, 'S': 16, 'Cl': 17, 'Br': 35, 'I': 53, 'P': 15}
pocket_atom_dict =  {'C': 0, 'N': 1, 'O': 2, 'S': 3} # only 4 atoms types for pocket
amino_acid_dict = {'A': 0, 'C': 1, 'D': 2, 'E': 3, 'F': 4, 'G': 5, 'H': 6, 'I': 7, 'K': 8, 'L': 9, 'M': 10, 'N': 11, 'P': 12, 'Q': 13, 'R': 14, 'S': 15, 'T': 16, 'V': 17, 'W': 18, 'Y': 19}
vdws = {'C': 1.7, 'N': 1.55, 'O': 1.52, 'S': 1.8, 'B': 1.92, 'Br': 1.85, 'Cl': 1.75, 'P': 1.8, 'I': 1.98, 'F': 1.47}

定义一个从PDB文件提取口袋的函数get_pocket, 输出是pdb文件,以及原子编号的字典,即上述中的pocket_atom_dict ,提取口袋原子的坐标(pocket_coords)以及原子one-hot(pocket_one_hot)。

def get_pocket(pdbfile, pocket_atom_dict, remove_H=True, ca_only=False):pdb_struct = PDBParser(QUIET=True).get_structure('', pdbfile)# find interacting pocket residues based on distance cutoff# 输入文件已为口袋的PDB文件,无需进行距离判断,仅需提取氨基酸即可pocket_residues = []for residue in pdb_struct[0].get_residues():# 氨基酸坐标res_coords = np.array([a.get_coord() for a in residue.get_atoms()])# 氨基酸,仅使用标准氨基酸if is_aa(residue.get_resname(), standard=True):pocket_residues.append(residue)# 氨基酸排序和对应的氨基酸类型pocket_ids = [f'{res.parent.id}:{res.id[1]}' for res in pocket_residues]if ca_only:# 口袋仅使用CA原子表示try:pocket_one_hot = []pocket_coords = []for res in pocket_residues:for atom in res.get_atoms():if atom.name == 'CA':pocket_one_hot.append(np.eye(1, len(amino_acid_dict),amino_acid_dict[three_to_one(res.get_resname())]).squeeze())pocket_coords.append(atom.coord)pocket_one_hot = np.stack(pocket_one_hot)pocket_coords = np.stack(pocket_coords)except KeyError as e:raise KeyError(f'{e} not in amino acid dict ({pdbfile})')else: # 全原子full_atoms = np.concatenate([np.array([atom.element for atom in res.get_atoms()]) for res in pocket_residues], axis=0)full_coords = np.concatenate([np.array([atom.coord for atom in res.get_atoms()]) for res in pocket_residues], axis=0)full_atoms_names = np.concatenate([np.array([atom.get_id() for atom in res.get_atoms()]) for res in pocket_residues], axis=0)pocket_AA = np.concatenate([([three_to_one(atom.get_parent().get_resname()) for atom in res.get_atoms()]) for res in pocket_residues], axis=0)# removing Hs if presentif remove_H:# 删除H原子h_mask = full_atoms == 'H'full_atoms = full_atoms[~h_mask]pocket_coords = full_coords[~h_mask]full_atoms_names = full_atoms_names[~h_mask]pocket_AA = pocket_AA[~h_mask]try:pocket_one_hot = []for i in range(len(full_atoms)):a = full_atoms[i]aa = pocket_AA[i]atom_onehot = np.eye(1, len(pocket_atom_dict), pocket_atom_dict[a.capitalize()]).squeeze()amino_onehot = np.eye(1, len(amino_acid_dict), amino_acid_dict[aa.capitalize()]).squeeze()is_backbone = 1 if full_atoms_names[i].capitalize() in ['N','CA','C','O'] else 0# 关于pocket_one_hot使用了原子类型,氨基酸类型,是否是骨架三种信息pocket_one_hot.append(np.concatenate([atom_onehot, amino_onehot, (is_backbone,)]))pocket_one_hot = np.stack(pocket_one_hot)except KeyError as e:raise KeyError(f'{e} not in atom dict ({pdbfile})')pocket_one_hot = np.array(pocket_one_hot)return pocket_one_hot, pocket_coords

定义输入的pdb名字以及运行设备

pdb = '2z3h.pdb'
dev = 'cuda:0' # cuda device 

指定口袋(fpocket找到的序号为1的口袋,上文中canya色)

定义生成分子数

k = 1 # pocket number identified by fpocket
pqr_file = pdb[:-4] + '_out/pockets/pocket' + str(k) + '_vert.pqr'
n_samples = 20 # number of samples to generate 生成10个分子

提取口袋原子坐标以及原子的one-hot,以及fpocket填充的球的坐标

pocket_onehot, pocket_coords = get_pocket(pdb, pocket_atom_dict, remove_H=True, ca_only=False)# use fpocket to identify the protein pocket
# NOTE: --------------------------
# fpocket can sometimes give you the wrong pocket, make sure to check the output and visualize the pockettry:if  not os.path.exists(pdb[:-4] + '_out'):#shutil.rmtree(pdb[:-4] + '_out', ignore_errors=Trueprint('running fpocket...')run_fpocket(pdb)pqr_file = pdb[:-4] + '_out/pockets/pocket' + str(k) + '_vert.pqr'alpha_spheres = np.array(extract_alpha_spheres_coords(pqr_file))except:raise ValueError('fpocket failed!')

创建口袋的grid, 分辨率为1.5A:

# ---------------  make a grid box around the pocket ----------------
min_coords = pocket_coords.min(axis=0) - 2.5 #
max_coords = pocket_coords.max(axis=0) + 2.5# 每个球的半径都是1.5
x_range = slice(min_coords[0], max_coords[0] + 1, 1.5) # spheres of radius 1.5 (vdw radius of C)
y_range = slice(min_coords[1], max_coords[1] + 1, 1.5)
z_range = slice(min_coords[2], max_coords[2] + 1, 1.5)grid = np.mgrid[x_range, y_range, z_range]
grid_points = grid.reshape(3, -1).T  # This transposes the grid to a list of coordinates

提取fpocket生成的α球的坐标:

# make sure the pocket-number is correct and you identified the correct pocket
pqr_file = pdb[:-4] + '_out/pockets/pocket' + str(k) + '_vert.pqr'
# 提取fpocket填充的α球的坐标
alpha_spheres = np.array(extract_alpha_spheres_coords(pqr_file))

计算小分子生长空间的grid,利用fpocket的α球的3A范围内,且不得与口袋的grid距离小于2A。

distances_spheres = distance.cdist(grid_points, alpha_spheres)
mask_spheres = (distances_spheres < 3).any(axis=1) 
filtered_alpha_points = grid_points[mask_spheres]# remove grid points that are close to the pocket
# 删除小分子空间中距离口袋太近的格点,阈值为2A。
pocket_distances = distance.cdist(filtered_alpha_points, pocket_coords)
mask_pocket = (pocket_distances < 2).any(axis=1)
grids = filtered_alpha_points[~mask_pocket]# 小分子生长空间的格点
grids = torch.tensor(grids)

口袋H原子,以及grid list

# 生长分子时,口袋加H,含有H原子
add_H = Trueif add_H:#add_hydrogens(pdb)prot_name_with_H = pdb[:-4] + '_H.pdb'# 提取H原子的坐标H_coords = extract_hydrogen_coordinates(prot_name_with_H)H_coords = torch.tensor(H_coords).float().to(dev)all_grids = [] # list of grids
all_H_coords = [] 
for i in range(n_samples):all_grids.append(grids) all_H_coords.append(H_coords)

口袋大小,采样生成的每个分子的最大原子数:

pocket_vol = len(grids)
max_mol_sizes = []
# 采样每个分子最大原子数
for i in range(n_samples):max_mol_sizes.append(sample_discrete_number(pocket_vol))pocket_size = len(pocket_coords)max_mol_sizes = np.array(max_mol_sizes)
print('maximum molecule sizes', max_mol_sizes)

定义一个LJ相互作用的调度器和参数,因为在分子生成过程中,使用到了LJ相互作用的引导,以避免分子与口袋的碰撞。

# scheduler and parameters for LJ guidance (avoiding clashes with pocket)
prot_mol_lj_rm = torch.tensor(prot_mol_lj_rm).to(dev)
mol_mol_lj_rm = torch.tensor(CROSSDOCK_LJ_RM).to(dev) / 100lj_weight_scheduler = cosine_beta_schedule(500, s=0.01, raise_to_power=2)
weights = 1 - lj_weight_scheduler 
weights = np.clip(weights, a_min=0.1, a_max=1.)

从口袋原子中采样anchor原子的序号,条件是:与fpocket中的α球的距离小于4.5A,距离最近的7个口袋原子中随机产生。

alpha_spheres_pocket_distances = distance.cdist(pocket_coords, alpha_spheres)
possible_pocket_anchors = np.argsort((alpha_spheres_pocket_distances < 4.5).sum(1))[::-1][:7]
pocket_anchors = np.random.choice(possible_pocket_anchors, size=n_samples, replace=True)

先可视化一下口袋:

创建口袋的mol对象

pocket_mol = get_pocket_mol(pocket_coords, pocket_onehot)

可视化口袋:

visualize_3d_pocket_molecule(pocket_mol, mol=None, spin=False, optimize_coords=False, sphere_positions2=alpha_spheres.tolist(), sphere_positions1=pocket_coords[possible_pocket_anchors].tolist())

按照默认配置,口袋原子为灰色,anchor原子为绿色,fpocket产生的α球为黄色:

加载模型,加载口袋原子的坐标,one-hot。

注意, checkpoint要先下载完毕,然后放置在./目录上,不是当前的运行目录。

pocket_onehot = torch.tensor(pocket_onehot).float()
pocket_coords = torch.tensor(pocket_coords).float()model = AR_DDPM.load_from_checkpoint('../pocket-gvp.ckpt', device=dev)
model = model.to(dev)anchor_model = AnchorGNN_pl.load_from_checkpoint('../anchor-model.ckpt', device=dev)
anchor_model = anchor_model.to(dev)

有了口袋原子坐标机器one-hot, 还有口袋anchor原子的one-hot,生成每个分子的最大原子数,以及口袋的grid范围,然后,可运行autodifffrag生成分子。

设定每个分子最多由8个片段组成。

# 运行autofragdiff最大生成8个片段
max_num_frags = 8
x, h, mol_masks = generate_mols_for_pocket(n_samples=n_samples,num_frags=max_num_frags,pocket_size=pocket_size,pocket_coords=pocket_coords,pocket_onehot=pocket_onehot,lig_coords=None,anchor_model=anchor_model,diff_model=model,device=dev,return_all=False,max_mol_sizes=max_mol_sizes,all_grids=all_grids,rejection_sampling=False,pocket_anchors=pocket_anchors,lj_guidance=True,prot_mol_lj_rm=prot_mol_lj_rm,mol_mol_lj_rm=mol_mol_lj_rm,all_H_coords=all_H_coords,guidance_weights=weights)

将AutoFragDiff生成的原子坐标及原子one-hot转化为rdkit的mol对象

x = x.cpu().numpy()
h = h.cpu().numpy()
mol_masks = mol_masks.cpu().cpu().numpy()# convert to SDF
all_mols = []
for k in range(len(x)):mask = mol_masks[k]h_mol = h[k]x_mol = x[k][mask.astype(np.bool_)]atom_inds = h_mol[mask.astype(np.bool_)].argmax(axis=1)atom_types = [idx2atom[x] for x in atom_inds]atomic_nums = [CROSSDOCK_CHARGES[i] for i in atom_types]try:mol_rec = reconstruct_from_generated(x_mol.tolist(), atomic_nums)all_mols.append(mol_rec)except:continue

查看生成的分子

visualize_3d_pocket_molecule(pocket_mol, mol=all_mols[0], spin=False, optimize_coords=False)

输出:

将生成的分子rdkit对象保存成sdf文件,命名为generated_mols.sdf。

# 保存成sdf文件
sdf_path = './generated_mols.sdf'
writer = Chem.SDWriter(sdf_path)
for mol in all_mols:writer.write(mol)
writer.close()

虽然定义让AutoFragDiff生成20个分子,但实际上只生成了19个。生成的19分子见如下视频:

上传审核中

这个体系在之前的DrugGPS测评的文章中,有测试过,DrugGPS生成的分子严重偏小,而AutoFragDiff很好的解决了这个问题。

3.4 生成分子测试-3WZE

接下来,对我们之前的3WZE体系进行测试。3WZE是一个激酶底物口袋,如下图。

采样与之前3.3类似的方法,生成分子如下视频:

上传审核中

生成分子的2D结构如下图:

参考分子如下图:

从上述结果来看部分分子还有有点类药,同时有的分子的位置很好位于参考分子的空间。生成分子的构象还是比较合理。

但是大量的分子不类药,同时存在很多C=O基团。此外,也存在明显的为完全占据口袋的情况。

3.5 命令行生成分子

注意,reduce的路径,要先设置好,否则会报错如下:

  File "/home//AutoFragDiff/sampling/sample_mols.py", line 103, in generate_mols_for_pocket

    all_H_coords[l] = all_H_coords[l] - anchor_pos[l]

RuntimeError: The size of tensor a (0) must match the size of tensor b (3) at non-singleton dimension 0

这是因为口袋没有加氢成功。

在输出信息中,会出现:sh: reduce: command not found

在utils.templates.py文件中,设置好reduce的路径。即,将add_Hydrogens函数修改为:(reduce的路径按照自己的环境设置)

def add_hydrogens(pdf_file):"""Add hydrogens to a PDB file using reduce."""#print('adding hydrogens')out_pdb = pdf_file[:-4] + '_H.pdb'os.system(f'~/anaconda3/envs/AmberTools23/bin/reduce -Quiet -NOFLIP {pdf_file} > {out_pdb}')

然后再./目录上运行如下命令,为3WZE口袋生成分子。3WZE.pdb要先放置在./目录中:

python sample_from_pocket.py \--results-path results \--pdb 3WZE.pdb \--anchor-model \anchor-model.ckpt \--diff-model pocket-gvp.ckpt \--n-samples 10 \--device cuda:0 \--pocket-number 1

生成输出信息如下:

生成的分子保存在./results路径中,sdf文件名为:pocket__mols.sdf。因为用的上面的3WZE体系,生成结果类似,就不重复展示了。

3.6 扩展分子骨架

作者提供了为crossdock扩展分子骨架的代码,在./目录下运行如下函数:(注:这一部分需要先下载好数据集)

python extend_scaffold_crossdock.py \--data-path ./data/CROSSDOCK \--results-path scaffold-gen \--anchor-model anchor-model.ckpt \--n-samples 20 \--exp-name scaffold-gen \--diff-model pocket-gvp.ckpt \--device cuda:0

每个体系生成20个分子。运行输出示例:

每个体系生成的分子保存在.//scaffold-gen/scaffold-gen路径中,默认crossdock测试集中的每个体系生成20个分子。

这里,我选择测试集中的第二个体系:GLMU_STRPN_2_459_0, 口袋为4aaw_A_rec_4ac3_r83_lig_tt_min_0_pocket10.pdb, 原先的小分子为:4aaw_A_rec_4ac3_r83_lig_tt_min_0.sdf,如下图:

代码会自动识别骨架,然后,在骨架基础上进行拓展。拓展生成的20个分子的2D结构如下图:

大部分的骨架拓展都失败了,只成功扩展了4个分子。

而之前的参考分子为:

首先,分子扩展的范围不完整,成功率也比较低。扩展的程度未达到参考分子的状态。更多例子,大家可以在./scaffold-gen/scaffold-gen文件夹内查看。

四、测评总结

在口袋条件下,基于自回归扩散模型的3D分子生成方法很多,例如:TargetDiff,很常见。基于分子片段库的3D分子生成方法也有,例如: FLAG和DrugGPS。

基于分子片段的,3D分子生成扩散模型,比较少见,AutoFragDiff将基于分子片段和扩散模型结合起来了,允许分子库中每一个分子片段在采样过程中经历去噪过程。这一点还是比较有意思的,创新性十足。AutoFragDiff既不是传统扩散模型的直接(0,1)采样噪声也不是基于片段那样子预测是哪一个片段。

AutoFragDiff充分利用了扩散模型的强可扩展性与基于分子片段生成分子的高可成药性。但是,在文章展现的结果中,并没有那么理想,成药性上,还有SA打分上,并没有超越SBDD等模型,这一点值得思考。我们的案例测试结果也显示生成的分子比较奇怪。

感觉是分子库中每一个分子片段经历去噪过程的方式不对,只用在了初始化中,在后面的去噪过程中,这些分子片段的信息,被覆盖了,所以效果不佳。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676838.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java EE初阶十一】文件操作(IO)

1. 认识文件 所谓的文件是一个广义的概念&#xff0c;可以代表很多东西&#xff1b;在操作系统里面&#xff0c;会把很多的硬件设备和软件设备都抽象成“文件”&#xff0c;统一进行管理&#xff1b;但是大部分情况下&#xff0c;我们读到的文件&#xff0c;都是指硬盘的文件&a…

MYSQL笔记:约束条件

MYSQL笔记&#xff1a;约束条件 主键约束 不能为空&#xff0c;值必须是不同的&#xff08;唯一性&#xff09; 一个表只能修饰一个主键 PRIMARY KEY自增约束 AUTO_INCREMENT唯一键约束 可以为空 unique非空约束 not null 默认值约束 default 外键约束 foreign key …

CMD常用命令

目录 1.简介 2.基本功能 3.打开方式 4.常用命令 5.练习——通过CMD打开QQ 1.简介 CMD&#xff08;Command Prompt&#xff09;是Windows操作系统中的命令行界面工具&#xff0c;它允许用户通过键入文本命令来与操作系统进行交互。CMD提供了一种不依赖图形用户界面的方式来…

详解格式化输入函数scanf

大家好&#xff0c;今天给大家介绍详解格式化输入函数scanf&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 C语言中常用的输入可以有多种方式&#xff0c;如scanf(),getchar(),g…

centos中docker操作

一、安装docker 确保系统是CentOS 7并且内核版本高于3.10,可以通过uname -r命令查看内核版本。 更新系统软件包到最新版本,可以使用命令yum update -y。 安装必要的软件包,包括yum-utils、device-mapper-persistent-data和lvm2。使用命令yum install -y yum-utils devic…

Mysql制作数据表

一.注意&#xff1a; 1.&#xff08;Mysql尽量用大写&#xff0c; 2.结尾为‘&#xff1b;’&#xff0c; 3.‘’与“”效果一样&#xff0c; 4.数据表名称显示时定为小写&#xff0c; 5.很多人教的时候喜欢用英文&#xff0c;我觉得麻烦&#xff0c;于是我用中文举例&…

moduleID的使用

整个平台上有很多相同的功能&#xff0c;但是需要不同的内容。例如各个模块自己的首页上有滚动新闻、有友好链接等等。为了公用这些功能&#xff0c;平台引入了moduleID的解决方案。 在前端的配置文件中&#xff0c;配置了模块号&#xff1a; 前端页面请求滚动新闻时&#xff0…

微软AD域替代方案,助力企业摆脱hw期间被攻击的窘境

在红蓝攻防演练&#xff08;hw行动&#xff09;中&#xff0c;AD域若被攻击成功&#xff0c;是其中一个扣分最多的一项内容。每年&#xff0c;宁盾都会接到大量AD在hw期间被攻击&#xff0c;甚至是被打穿的企业客户。过去&#xff0c;企业还会借助2FA双因子认证加强OA、Exchang…

ChatGPT高效提问—prompt常见用法(续篇七)

ChatGPT高效提问—prompt常见用法&#xff08;续篇七&#xff09; 1.1 零样本、单样本和多样本 ​ ChatGPT拥有令人惊叹的功能和能力&#xff0c;允许用户自由向其提问&#xff0c;无须提供任何具体的示例样本&#xff0c;就可以获得精准的回答。这种特性被称为零样本&#x…

每日一题——LeetCode1417.重新格式化字符串

方法一 个人方法&#xff1a; s里的字符只有小写字母和数字两种情况&#xff0c;我们可以把s里的字母和数字分隔成两个字符串&#xff0c; 比较两个字符串的长度&#xff0c;只有当两个字符串的长度差值的绝对值为1或0才能满足题意。 长度更长的要放在结果字符串的第一位&am…

嵌入式学习之Linux入门篇笔记——18,makefile基本语法(下)

配套视频学习链接&#xff1a;http://【【北京迅为】嵌入式学习之Linux入门篇】 https://www.bilibili.com/video/BV1M7411m7wT/?p4&share_sourcecopy_web&vd_sourcea0ef2c4953d33a9260910aaea45eaec8 1.wildcard 函数 格式&#xff1a;$&#xff08;wildcard PAT…

SQL如何实现数据表行转列、列转行?

SQL行转列、列转行可以帮助我们更方便地处理数据&#xff0c;生成需要的报表和结果集。本文将介绍在SQL中如何实现数据表地行转列、列转行操作&#xff0c;以及实际应用示例。 这里通过表下面三张表进行举例 SQL创建数据库和数据表 数据表示例数据分别如下&#xff1a; data_…

数据湖的整体思路

湖本质上是一个集中化&#xff0c;中心化的&#xff0c;一体化的存储技术&#xff0c;并且在其之上追求技术架构的统一化&#xff0c;如流批一体&#xff0c;服务分析一体化。 当数据湖成为中心&#xff0c;那么就可以围湖而建“数据服务环”&#xff0c;环上的服务包括了数仓、…

鸿蒙开发(六)布局概述

迄今为止&#xff0c;我还没有正式提到布局的概念。但其实我之前的demo里面&#xff0c;已经默认使用到了一种布局&#xff0c;那就是线性布局&#xff08;Row、Column&#xff09;&#xff0c;这也是DevEco创建项目默认页面里面默认采用的布局。那么本篇&#xff0c;带着大家一…

微服务介绍、使用 Nacos 实现远程调用以及 OpenFeign 的使用

1 微服务的概念 区别于单体项目 单体项目拆分成微服务项目的目标&#xff1a;高内聚、低耦合 拆分思路 纵向拆分&#xff1a;根据功能模块 横向拆分&#xff1a;抽取可复用模块 2 微服务拆分——远程调用 背景&#xff1a;微服务单一职责&#xff0c;每个服务只有自己的功能…

[PYthon] 字典

如题&#xff0c;这篇博客将带大家来学习Python中的字典~ 那么&#xff0c;是我们想象中的那种字典嘛&#xff1f;接下来跟着可莉去一探究竟吧~ 可莉将这篇文章收录在了&#xff1a;《Python》 可莉推荐的优质博主主页&#xff1a;Keve ’ s blog Python 中的字典&#xff08;D…

-转换流-

它是字节流和字符流之间转换的桥梁 转换流本身其实是字符流&#xff1b; 转换流的位置&#xff1a; 分为两个&#xff1a;字符转换输入流&#xff1a;InputStreamReader将InputStream转换为Reader字符转换输出流&#xff1a;OutputStreamWriter将Writer转换为OutputStream 作用…

4.2 Verilog 过程赋值

关键词&#xff1a;阻塞赋值&#xff0c;非阻塞赋值&#xff0c;并行 过程性赋值是在 initial 或 always 语句块里的赋值&#xff0c;赋值对象是寄存器、整数、实数等类型。 这些变量在被赋值后&#xff0c;其值将保持不变&#xff0c;直到重新被赋予新值。 连续性赋值总是处…

LeetCode Python - 6.Z字形变换

文章目录 题目答案运行结果 题目 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1a; P A H N A P L S I I G Y I R 之后&#xff0c;你的输…

Qualcomm 蓝牙耳机 FAQ(41)---------Audio 问题分析之 ACAT Tools安装

大家好&#xff01; 新的一年&#xff0c;在此祝大家&#xff1a;新年快乐&#xff01;工作上步步高升&#xff01;&#xff01;龙年大吉&#xff01;&#xff01;&#xff01; 也欢迎大家登录大大通平台&#xff0c;春节期间正常更新文章&#xff0c;期待你的到来&#xff0…