一覧へ

「拡散モデルと物理学のハイブリッドによる低分子ドッキング — DiffDock-Glide を使用した SARS-CoV-2 Mpro 候補の再検証」

「DiffDock の拡散ベースのリガンドポーズ予測と Glide および AutoDock Vina の物理学的再検証を組み合わせたハイブリッドドッキングパイプライン。クラッシュフィルタリング、PoseBusters、アンサンブルスコアリング、PDBbind/DUD-E ベンチマーク、ROC AUC、PyMOL 可視化などを含む、SARS-CoV-2 Mpro ターゲットリガンドを再検証するための実践的なシナリオ。」

上級
|
45
|
検証済み (2026-07)
進捗0/15 (0%)

Diffusion-Physics Hybrid Molecular Docking — Re-validation of SARS-CoV-2 Mpro Candidates with DiffDock-Glide

パート 07:GNN DTI予測は、上位のSARS-CoV-2 Mpro結合候補に対して、結合する可能性を示す確率スコアのみを提供します。実際の実験を行う前に、"どのように結合するか"の3D構造と、"どれだけ安定して結合するか"の物理学に基づいた根拠が必要です。AutoDock VinaやGlideなどの物理学に基づいたドッキングツールは、30年の実績があり、標準的なツールとして確立されていますが、広範な構造空間を徹底的に探索するため、計算時間がかかります。一方、DiffDockなどの拡散モデルは、数秒で複数の候補構造を生成できますが、物理的に衝突するような構造が生じやすいという欠点があります。本パートでは、両方の手法の長所を組み合わせたハイブリッドパイプライン、具体的にはDiffDock-Glide (2025)に焦点を当て、実用的な環境で、構造の正確性と計算速度の両方を実現することを目指します。

📚 推奨される事前知識 (強く推奨)

本パートは、AI × 生物学における高度で専門的なトピックです。本パートを開始する前に、DryBenchの以下の部分を最初に確認することをお勧めします。

事前知識を確認せずに進めると、本パートでは拡散モデルのノイズ除去の原理、SE(3)-equivariantグラフ、およびPyTorchにおける大規模なテンソル処理について再説明しないため、実践的なコードを理解することが難しくなります。


DryBenchで以前に学習したこと

DryBench ai-native #2では、確率分布を学習する生成モデルの原理を学び、#12では、PyTorchを使用して大規模なテンソルを操作し、混合精度最適化を行う方法を学びました。

拡散モデルは、ノイズからデータを段階的に再構築するトレーニング手法であり、画像、音声、ビデオの分野で大きな成功を収めています。しかし、リガンドドッキングは、やや異なる問題です。それは、ノイズからリガンドの3D座標を、ターゲットポケット内の正確な位置に"再構築"することを含みます。特に、SE(3)-equivariant(回転および並進対称性を保持する)ように設計することが重要です。DiffDock (2022)およびその後のいくつかのモデルは、このアイデアを改良してきました。しかし、拡散モデルの根本的な制限(物理法則を明示的に強制しない)は、実用的なアプリケーションにおいて、衝突や非現実的な形状として現れます。したがって、物理学に基づく再検証レイヤーは不可欠です。

難しい問題の定義

実用的なシナリオ:SARS-CoV-2 Mpro候補リガンドの再検証

パート07では、ドッキングによってスコアリングされた、承認された薬剤ライブラリからの上位20個の候補リガンドを再検証します。

  • 入力: Mproの3D構造(PDB 6LU7、7BQYなど、いくつかのapoおよびholo構造)、20個の候補リガンドのSMILES。
  • 出力: 各候補に対する上位3つの結合構造、各構造に対する結合エネルギー、衝突および幾何学的な妥当性、および最終的なアンサンブルスコア。
  • 検証: 既知のMpro阻害剤(nirmatrelvir、ensitrelvir、N3など)、PDBbind Mproサブセットベンチマークとの一貫性。
  • コスト: 1リガンドあたり60秒未満(DL 30秒 + 物理学による再検証30秒)。

ドッキングの基本的な要件

ターゲットタンパク質の3D構造と数千個のリガンドに対して:

  • 結合構造の予測: 各リガンドがどのポケットに、どのような方向で結合するかを決定します。
  • 結合親和性スコア: 構造の物理的および化学的な安定性を定量化します。
  • 偽陽性フィルター: 非現実的な構造(衝突、誤ったポケット、歪んだ形状)を自動的に除去します。
  • 処理速度: 1リガンドあたり数秒から数分。

既存のアプローチ

  • AutoDock Vina (2010、いくつかの改訂版):無料およびオープンソース。標準的なドッキングツール。1分あたり1〜10個のリガンド [1]。
  • Glide (Schrödinger):商用。精度レベルはSPからXPまで。業界標準。
  • DiffDock (MIT 2022):拡散に基づく最初のSOTA。1リガンドあたり30秒、上位1の精度は38% [2]。
  • DiffDock-L (MIT 2024):上位1の精度が43%に向上した拡張版。
  • DiffDock-Pocket (2024):ポケット情報を利用して精度を向上させます。
  • DiffDock-Glide (bioRxiv 2025):DL構造 + Glideによるハイブリッド最小化、上位1の精度は55%以上 [3]。
  • RLDiff (2024、Oxford):強化学習によって誘導される拡散 [4]。
  • Boltz-2 (パート11):ドッキングを含む統合予測ツール。本パートでは、ドッキングに特化したアプローチに焦点を当て、Boltz-2を補完します。
  • PoseBusters (2024):ドッキング構造の妥当性を定量化するためのDLフレームワーク [5]。

本パートでは、DiffDock(またはDiffDock-Glide)による構造予測 + Vina / Glideによる再検証 + PoseBustersフィルターを組み合わせます。

本パートのターゲットメトリック

  • 20個のMpro候補それぞれに対して、30分以内のウォールクロック時間で、上位3つの構造を生成します。
  • PoseBustersの物理学フィルターを使用して、30%以上の衝突および非現実的な構造を除去します。
  • アンサンブルスコア(DiffDockの信頼度 + Vinaスコア + 幾何学的な妥当性)を定量化します。
  • 既知の阻害剤(nirmatrelvirなど)のトップ3ランキングを再現します。
  • DUD-Eベンチマーク(活性化合物とデコイ化合物を区別する)で、ROC AUC 0.85以上を達成します。

必要なツールとインフラ

ツール役割ライセンス
DiffDock (または DiffDock-L)拡散に基づくポーズ予測MIT
DiffDock-Glide (bioRxiv 2025 コード)ハイブリッド最小化個々の著者のライセンス
AutoDock Vina物理に基づいたドッキングと再検証Apache 2.0
PoseBustersポーズの妥当性検証MIT
OpenBabelファイル形式の変換 (SMI、SDF、PDB、PDBQT)GPL
RDKitSMILES、3D座標、および正規化BSD-3-Clause
PyMOL (オープンソース版)可視化LGPL
MDAnalysis (オプション)トラジェクトリー解析と後処理GPL
PDBFixer (OpenMMファミリー)タンパク質の前処理LGPL
PDBbind / DUD-E / COVID Moonshotベンチマークデータセット学術利用は無料

インフラストラクチャ要件:

  • 24〜48GB VRAMのデータセンターGPU(DiffDockおよびその後のバージョン、大きなリガンド、大きなポケットの場合)。
  • ほとんどのタスクは、ハイエンドのコンシューマーGPU(RTX 4090 24GB)で実行できます。大規模な複合体には、データセンターGPUが必要です。
  • VinaおよびGlideによる再検証:8コア以上のCPUを推奨(並列処理のため)。
  • 16GB以上のRAM。
  • ディスク容量:DiffDockの重み(約2GB)、PDBbind(約10GB)、DUD-E(約30GB)、およびさまざまなMpro PDBファイル(約100MB)。

学習者向けの推定コスト: ローカルGPUおよびCPUを使用する場合、APIコストは0です。100個のリガンドをスクリーニングするには、約30〜60分かかります。クラウドGPUを使用する場合は、時間単位の料金を参照してください。

パイプラインの実践的な実装

全体のフロー:

mermaid

ステップ1:タンパク質の事前処理

ドッキングを行う前に、プロトン化状態の除去、水素の付加、水とイオンの除去、リガンドの除去を行うことが重要です。PDBFixerは標準的なツールです。

python
import subprocess
from pathlib import Path
def prepare_protein(input_pdb: Path, output_pdb: Path, remove_hetatoms: bool = True) -> None:
"""PDBの事前処理:水、イオン、リガンドの除去 + Hの付加 + 部分電荷の保持。
実用的なオプション:pdb2pqr、PDBFixer、Schrödinger Protein Prep、UCSF ChimeraX。
"""
from pdbfixer import PDBFixer
from openmm.app import PDBFile
fixer = PDBFixer(filename=str(input_pdb))
fixer.findMissingResidues()
fixer.findMissingAtoms()
fixer.addMissingAtoms()
fixer.addMissingHydrogens(pH=7.4)
if remove_hetatoms:
fixer.removeHeterogens(keepWater=False)
with open(output_pdb, "w") as f:
PDBFile.writeFile(fixer.topology, fixer.positions, f)
def pdb_to_pdbqt(pdb_path: Path, pdbqt_path: Path) -> None:
"""AutoDock Vina用にPDBQT形式に変換(OpenBabel)。
-xr:剛体レセプター(側鎖の柔軟性を排除し、ドッキング速度を向上)。
-xh:Hを保持、-xn:Nアミド電荷、-xr r:剛体。
"""
subprocess.run(
["obabel", str(pdb_path), "-O", str(pdbqt_path), "-xr"],
check=True, capture_output=True,
)
def identify_binding_site(pdb_path: Path, known_ligand_pdb: Path | None = None) -> tuple[float, float, float]:
"""ドッキングボックスの中心。既知のリガンドがある場合は、その中心を使用します。そうでない場合は、ポケット予測ツールを使用します。
Mpro 6LU7シナリオ:共結晶化された阻害剤の中心を使用します。
"""
if known_ligand_pdb:
# リガンド原子の座標の平均
from Bio.PDB import PDBParser
parser = PDBParser(QUIET=True)
structure = parser.get_structure("lig", str(known_ligand_pdb))
coords = [atom.get_coord() for atom in structure.get_atoms()]
import numpy as np
center = np.mean(coords, axis=0)
return (float(center[0]), float(center[1]), float(center[2]))
else:
# fpocket、PocketFinderなどを使用します(ここでは概念的なスタブ)。
raise NotImplementedError("既知のリガンドがない場合は、fpocketを統合する必要があります")

ステップ2:リガンドの3Dコンフォーマーを生成

python
from rdkit import Chem
from rdkit.Chem import AllChem
def smiles_to_sdf(smiles: str, sdf_path: Path, num_conformers: int = 3) -> Path:
"""SMILES → 複数の3Dコンフォーマー → SDF。
複数のコンフォーマーは、DiffDockの多様性ヒントとして役立ちます(一部のアプローチでは、単一のコンフォーマーのみを使用します)。
"""
mol = Chem.MolFromSmiles(smiles)
if mol is None:
raise ValueError(f"無効なSMILES:{smiles}")
mol = Chem.AddHs(mol)
# 複数のコンフォーマーを生成し、次にエネルギーを最小化します
conf_ids = AllChem.EmbedMultipleConfs(
mol,
numConfs=num_conformers,
params=AllChem.ETKDGv3(),
)
for conf_id in conf_ids:
try:
AllChem.MMFFOptimizeMolecule(mol, confId=conf_id, maxIters=500)
except Exception:
pass
writer = Chem.SDWriter(str(sdf_path))
for conf_id in conf_ids:
writer.write(mol, confId=conf_id)
writer.close()
return sdf_path

ステップ3:DiffDockポーズを生成

python
import subprocess
def run_diffdock(
protein_pdb: Path,
ligand_sdf: Path,
output_dir: Path,
num_poses: int = 20,
num_inference_steps: int = 40,
device: str = "cuda",
use_pocket: bool = False,
pocket_center: tuple[float, float, float] | None = None,
) -> list[Path]:
"""DiffDockを実行 → 複数のポーズのSDFファイルを返します。
DiffDockリポジトリのinference.py CLIを呼び出します。
"""
output_dir.mkdir(parents=True, exist_ok=True)
cmd = [
"python", "-m", "inference",
"--protein_path", str(protein_pdb),
"--ligand", str(ligand_sdf),
"--out_dir", str(output_dir),
"--samples_per_complex", str(num_poses),
"--inference_steps", str(num_inference_steps),
"--batch_size", "10",
]
if use_pocket and pocket_center:
# DiffDock-Pocket拡張(座標ヒント)
cmd += ["--pocket_center", ",".join(f"{c:.2f}" for c in pocket_center)]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"DiffDock failed STDERR: {result.stderr[:500]}")
raise RuntimeError("DiffDock execution failed")
pose_files = sorted(output_dir.glob("complex_0/rank*.sdf"))
return pose_files

ステップ4:PoseBusters物理フィルタ

PoseBustersは、ドッキングポーズの物理的および化学的妥当性を定量的に評価する最近のフレームワークです[5]。

python
def validate_pose_with_posebusters(
pose_sdf: Path,
protein_pdb: Path,
) -> dict:
"""PoseBustersでポーズの妥当性を検証します。
返り値:{
"passes_all_checks": bool,
"checks": {チェック名:bool},
"critical_failures": [失敗したチェックのリスト],
}
"""
try:
from posebusters import PoseBusters
buster = PoseBusters(config="dock")
results = buster.bust(
mol_pred=[pose_sdf],
mol_cond=protein_pdb,
)
# resultsはpandas DataFrame
checks = results.iloc[0].to_dict()
critical_failures = [k for k, v in checks.items() if v is False and "clash" in k.lower() or "geometry" in k.lower()]
passes_all = all(v for v in checks.values() if isinstance(v, bool))
return {
"passes_all_checks": passes_all,
"checks": checks,
"critical_failures": critical_failures,
}
except ImportError:
# PoseBustersがインストールされていない場合は、単純な衝突チェックにフォールバックします
return {"passes_all_checks": True, "checks": {}, "critical_failures": []}
import numpy as np
from Bio.PDB import PDBParser, NeighborSearch
VDW_RADII = {
"H": 1.20, "C": 1.70, "N": 1.55, "O": 1.52, "F": 1.47,
"P": 1.80, "S": 1.80, "Cl": 1.75, "Br": 1.85, "I": 1.98,
}
def simple_clash_check(
protein_pdb: Path,
ligand_sdf: Path,
clash_threshold: float = 0.7,
max_clash_count: int = 3,
) -> bool:
"""衝突がある場合はTrueを返します(PoseBustersのフォールバック)。"""
parser = PDBParser(QUIET=True)
structure = parser.get_structure("protein", str(protein_pdb))
protein_atoms = list(structure.get_atoms())
ns = NeighborSearch(protein_atoms)
mol = Chem.SDMolSupplier(str(ligand_sdf), removeHs=False)[0]
if mol is None:
return True
conf = mol.GetConformer()
clash_count = 0
for i, atom in enumerate(mol.GetAtoms()):
pos = conf.GetAtomPosition(i)
lig_vdw = VDW_RADII.get(atom.GetSymbol(), 1.7)
nearby = ns.search([pos.x, pos.y, pos.z], 5.0)
for prot_atom in nearby:
prot_vdw = VDW_RADII.get(prot_atom.element, 1.7)
distance = np.linalg.norm(
np.array([pos.x, pos.y, pos.z]) - prot_atom.get_coord()
)
if distance < (lig_vdw + prot_vdw) * clash_threshold:
clash_count += 1
if clash_count > max_clash_count:
return True
return False

ステップ5:Vinaローカル最小化 + スコア算出

DiffDockポーズを初期座標として使用してVinaのローカル最適化を実行し、物理的に安定したポーズにポーズを改良し、スコアを取得します。

python
def vina_local_score(
receptor_pdbqt: Path,
ligand_pdbqt: Path,
center: tuple[float, float, float],
size: tuple[float, float, float] = (20, 20, 20),
exhaustiveness: int = 1, # ローカル最適化なので、低めに設定
output_pdbqt: Path | None = None,
) -> float:
"""Vinaローカル最適化 + スコア。exhaustiveness=1はローカル最小化用。
返り値:結合エネルギー(kcal/mol、小さいほど結合が強い)。
"""
cmd = [
"vina",
"--receptor", str(receptor_pdbqt),
"--ligand", str(ligand_pdbqt),
"--center_x", str(center[0]),
"--center_y", str(center[1]),
"--center_z", str(center[2]),
"--size_x", str(size[0]),
"--size_y", str(size[1]),
"--size_z", str(size[2]),
"--exhaustiveness", str(exhaustiveness),
"--num_modes", "1",
"--local_only",
]
if output_pdbqt:
cmd += ["--out", str(output_pdbqt)]
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
# Vinaの出力から親和性を解析
for line in result.stdout.splitlines():
stripped = line.strip()
if stripped.startswith("1 ") or stripped.startswith("1\t"):
parts = stripped.split()
try:
return float(parts[1]) # kcal/mol
except (IndexError, ValueError):
pass
return 0.0

ステップ6:アンサンブルスコアリング

DiffDockの信頼度 + PoseBustersの妥当性 + Vinaスコアの重み付き組み合わせ。

python
from dataclasses import dataclass
@dataclass
class PoseResult:
ligand_id: str
pose_path: Path
diffdock_confidence: float
posebusters_passes: bool
vina_score: float
final_score: float
metadata: dict
def ensemble_score(
diffdock_conf: float,
posebusters_passes: bool,
vina_score: float,
weight_dl: float = 0.3,
weight_vina: float = 0.6,
invalid_penalty: float = 5.0,
) -> float:
"""アンサンブルスコア。小さいほど良好(Vinaスケール)。
DLスコアをVinaスケールに変換(-5.0は不確か、-8.0以下が強い結合)。
"""
dl_component = -diffdock_conf * 3.0
combined = weight_vina * vina_score + weight_dl * dl_component
if not posebusters_passes:
combined += invalid_penalty # 物理的に非現実的なポーズに対するペナルティ
return combined
def rank_ligand_poses(
ligand_id: str,
diffdock_poses: list[dict], # [{pose_path, confidence}]
receptor_pdb: Path,
receptor_pdbqt: Path,
binding_center: tuple[float, float, float],
) -> list[PoseResult]:
"""単一のリガンドの複数のポーズをVinaとPoseBustersで再検証し、アンサンブル化します。"""
results = []
for pose in diffdock_poses:
pose_pdbqt = pose["pose_path"].with_suffix(".pdbqt")
try:
subprocess.run(
["obabel", str(pose["pose_path"]), "-O", str(pose_pdbqt)],
check=True, capture_output=True,
)
except subprocess.CalledProcessError:
continue
vina_score = vina_local_score(receptor_pdbqt, pose_pdbqt, binding_center)
pb_result = validate_pose_with_posebusters(pose["pose_path"], receptor_pdb)
final = ensemble_score(
pose["confidence"], pb_result["passes_all_checks"], vina_score,
)
results.append(PoseResult(
ligand_id=ligand_id,
pose_path=pose["pose_path"],
diffdock_confidence=pose["confidence"],
posebusters_passes=pb_result["passes_all_checks"],
vina_score=vina_score,
final_score=final,
metadata={
"posebusters_details": pb_result["checks"],
"critical_failures": pb_result["critical_failures"],
},
))
return sorted(results, key=lambda r: r.final_score)

ステップ7:PyMOL自動レンダリング

パート11と同様のパターン。

python
def render_top_poses(
receptor_pdb: Path,
top_poses: list[PoseResult],
output_dir: Path,
) -> None:
output_dir.mkdir(parents=True, exist_ok=True)
for i, pose in enumerate(top_poses):
script = f"""
load {receptor_pdb}, receptor
load {pose.pose_path}, ligand
hide everything
show cartoon, receptor
show sticks, ligand
show sticks, receptor within 5 of ligand
color grey70, receptor
color yellow, ligand
zoom ligand, 5
bg_color white
ray 1200, 900
png {output_dir / f"{pose.ligand_id}_rank{i+1}.png"}, dpi=150
quit
"""
script_path = output_dir / f"render_{pose.ligand_id}_{i}.pml"
script_path.write_text(script)
subprocess.run(["pymol", "-cq", str(script_path)], check=True, capture_output=True)

ステップ8:統合パイプラインとMproシナリオの実行

python
import pandas as pd
def hybrid_docking_pipeline(
protein_pdb: Path,
known_ligand_pdb: Path | None,
ligand_smiles_list: list[tuple[str, str]], # [(ligand_id, smiles)]
work_dir: Path,
top_k: int = 10,
poses_per_ligand: int = 10,
device: str = "cuda",
) -> pd.DataFrame:
"""完全なハイブリッドドッキングスクリーニング。"""
work_dir.mkdir(parents=True, exist_ok=True)
print("[1/5] タンパク質の事前処理")
prepared_pdb = work_dir / "protein_prepared.pdb"
prepare_protein(protein_pdb, prepared_pdb)
receptor_pdbqt = work_dir / "protein_prepared.pdbqt"
pdb_to_pdbqt(prepared_pdb, receptor_pdbqt)
binding_center = identify_binding_site(prepared_pdb, known_ligand_pdb)
print(f" 結合中心:{binding_center}")
all_results = []
for ligand_id, smiles in ligand_smiles_list:
print(f"[2/5] {ligand_id} 3Dコンフォーマー + DiffDock")
ligand_sdf = work_dir / "ligands" / f"{ligand_id}.sdf"
try:
smiles_to_sdf(smiles, ligand_sdf, num_conformers=3)
pose_files = run_diffdock(
prepared_pdb, ligand_sdf,
work_dir / "diffdock" / ligand_id,
num_poses=poses_per_ligand, device=device,
)
except Exception as e:
print(f" 失敗 ({ligand_id}):{e}")
continue
# DiffDockの信頼度は、ファイル名または別のメタデータにあるランク
diffdock_poses = [
{"pose_path": p, "confidence": max(0.0, 1.0 - 0.05 * i)} # ランクが低いほど、信頼度が高い
for i, p in enumerate(pose_files)
]
print(f"[3/5] {ligand_id} PoseBusters + Vina再検証")
ranked = rank_ligand_poses(
ligand_id, diffdock_poses, prepared_pdb, receptor_pdbqt, binding_center,
)
all_results.extend(ranked[:3]) # リガンドごとにトップ3
# 4. 全体ランキング
all_results.sort(key=lambda r: r.final_score)
df = pd.DataFrame([{
"ligand_id": r.ligand_id,
"diffdock_conf": r.diffdock_confidence,
"posebusters_pass": r.posebusters_passes,
"vina_score": r.vina_score,
"final_score": r.final_score,
"critical_failures": ";".join(r.metadata["critical_failures"]),
"pose_path": str(r.pose_path),
} for r in all_results])
df.to_csv(work_dir / "docking_results.csv", index=False)
print(f"[4/5] トップ-{top_k} PyMOLレンダリング")
render_top_poses(prepared_pdb, all_results[:top_k], work_dir / "renders")
print("[5/5] 完了")
return df
# 例:SARS-CoV-2 Mproシナリオ
# result_df = hybrid_docking_pipeline(
# protein_pdb=Path("./6LU7.pdb"),
# known_ligand_pdb=Path("./6LU7_ligand.pdb"), # 共結晶化されたN3阻害剤
# ligand_smiles_list=[
# ("nirmatrelvir", "CC1(C)C2CC1C(NC(=O)C1CCCN1C(=O)C(NC(=O)OC(C)(C)C)C(C)(C)C)C(=O)NC(C#N)CC2=O"),
# ("ensitrelvir", "..."),
# # パート07のトップ20の候補を追加
# ],
# work_dir=Path("./mpro_docking_output"),
# )
## パフォーマンス、コスト、および既知の失敗事例
### パフォーマンスの参考(公開されたベンチマークの引用)
| モデル | ベンチマーク | Top-1 RMSD ≤ 2Å | PoseBusters 合格率 | 時間/ペア | 参照 |
|------|------|:----------------:|:------------------:|:---------:|------|
| AutoDock Vina | PDBbind core | 20~30% | 85~90% (物理ベースライン) | 分 | Trott & Olson 2010 [1] |
| Glide SP | PDBbind core | 35~40% | 90%+ | 秒~分 | Schrödinger |
| Glide XP | PDBbind core | 40~50% | 92%+ | 分 | Schrödinger |
| DiffDock | PDBbind core | 38% | 60~70% (物理の問題) | 30秒 GPU | Corso et al., ICLR 2023 [2] |
| DiffDock-L | PDBbind core | 43% | 65~75% | 30秒 GPU | Corso et al. 2024 |
| DiffDock-Pocket | PDBbind core | 45%+ | 70%+ | 40秒 GPU | 2024 |
| DiffDock-Glide | PDBbind core | 55~60% | 85%+ (Glideによる補正) | 60秒 GPU+CPU | Miller et al., bioRxiv 2025 [3] |
| RLDiff | PDBbind subset | ~50% | 78% | 40秒 GPU | Zhang et al. 2024 [4] |
| Boltz-2 (Part 11) | 同様のベンチマーク | 50%+ | 90%+ (物理を統合した設計) | 秒 GPU | MIT/Genentech 2025 |
### 学習者が再現するための推定コスト
- APIコスト:0(完全にローカル)。
- 100個の配位子をスクリーニング:DiffDockは約30分(GPU)+ Vinaによる再検証は約30分(CPU、並列48コア)。
- 20個のMpro候補をスクリーニング:1530分。
- DiffDockの重みをダウンロードするのに約2GB(初回実行時)。
- Vina、OpenBabel、PoseBustersは無料。
### 5つの既知の失敗事例(コミュニティ/論文の収集)
1. **DiffDockのポーズにおける原子の衝突と非現実的な形状(PoseBusters 60%の失敗)**
症状:DiffDockのトップのポーズで、配位子の原子がタンパク質の原子と重なり(浸透)、結合角が歪み、芳香環が平面でなくなる。
原因:拡散モデルは、物理法則を明示的に強制しない。トレーニングの目的は、座標の再構築であり、幾何学的妥当性の個別の検証はない。
緩和策:(a)常にPoseBustersフィルターを使用する(このパートのステップ4)、(b)Vinaによる局所最適化で改良する、(c)複数のポーズをアンサンブル化して、有効なポーズを選択する、(d)物理を統合したDiffDock-Glideのような後続モデルを使用する、(e)物理を統合したトレーニングであるPart 11のBoltz-2に置き換える。
出典:Buttenschoen et al. "PoseBusters" Chem Sci 2024 [5]。
2. **誤ったポケットの選択(ブラインドドッキングと標的ドッキング)**
症状:DiffDockがブラインドモードで、既知のオルソステリック部位以外のポケットに配位子を配置する。
原因:DiffDockには、自動ポケット検索モードと明示的な指定モードの両方があり、ブラインドモードでは誤認が一般的である。
緩和策:(a)ポケットの座標を事前に指定する(このパートのidentify_binding_site)、(b)fpocketを使用して候補のポケットを事前に探索する、(c)DiffDock-Pocketを使用する、(d)既知の配位子が存在する場合は、その位置をシードとして使用する。
出典:DiffDock GitHub Issues [6]。
3. **DUD-Eベンチマークにおける既知のバイアス(活性分子とデコイのバイアス)**
症状:DUD-EではAUC > 0.9だが、実際の新しい創薬スクリーニングではパフォーマンスが大幅に低下する。
原因:DUD-Eのデコイは、特性の一致を使用して生成されるため、スコアリング関数は、活性分子とデコイ分子の間の物理化学的差異のみを学習する(実際の結合の識別がない)。
緩和策:(a)LIT-PCBAなどのバイアスのないベンチマークを使用する、(b)将来の実験的な検証を行う、(c)複数のベンチマークのアンサンブルを使用する、(d)COVID Moonshotなどの実世界のデータセットを使用する。
出典:Chen et al. "Hidden bias in the DUD-E dataset." PLoS ONE 2019 [7]。
4. **標的タンパク質の柔軟性を無視(剛体受容体)**
症状:ドッキングは剛体受容体を仮定するが、実際にはタンパク質は柔軟であり、特にループと側鎖の動きがある。
原因:ほとんどのVinaおよびDiffDockモデルは、デフォルトで剛体受容体モードを使用する。
緩和策:(a)MDシミュレーションを使用して複数のコンフォメーションを生成し、それぞれをドッキングする(アンサンブルドッキング)、(b)DiffDockを複数のapo/holo構造と並行して実行する、(c)商用のIFD(誘導適合ドッキング)ソフトウェアを使用する、(d)Boltz-2およびChai-1(Part 11)のような共同折り畳みアプローチを使用する。
出典:Amaro RE et al. "Ensemble Docking in Drug Discovery." Biophysical Journal 2018 [8]。
5. **配位子の立体化学と互変異性異性体を無視**
症状:SMILESで立体化学が指定されている場合でも、予測は複数の立体異性体のうちの1つをランダムに選択する。または、特定のpHで支配的でない互変異性異性体でドッキングが発生する。
原因:SMILESの標準化と3Dコンフォメーション生成の段階で情報が失われる。
緩和策:(a)`Chem.MolFromSmiles`でキラル性を保持する、(b)`MolStandardize`を使用して互変異性異性体を標準化する、(c)各立体異性体と互変異性異性体を個別にドッキングし、次にアンサンブル化する、(d)予測されたポーズのキラル性を事後検証する。
出典:RDKit MolStandardizeドキュメント [9]; Boltz Issues(立体化学)[6]。
## 拡張のアイデア
- **フラグメントベースのドッキング:**大きなライブラリをフラグメント(< 300 Da)に縮小してドッキングし、次にリンカーを設計する。
- **アンサンブルドッキング:**複数のタンパク質コンフォメーション(MDシミュレーションまたはAlphaFoldの複数)のそれぞれをドッキングし、次に集約する。
- **自由エネルギー計算の統合:**トップのドッキング候補をMM-GBSAまたはFEPで事後処理して、より正確な親和性を得る。
- **デノボリンカー設計:**RFdiffusion(Part 13)でリンカーを生成し、ドッキングで検証する。
- **アクティブラーニング+自動ドッキング:**予測の不確実性が高い配位子を特定し、実験的な検証を行い、再トレーニングする。
- **アンサンブルBoltz-2 vs. DiffDock-Glide:**Part 11のBoltz-2の結果を比較し、アンサンブル化する。
## 次のパート
- Part 11 `structure-affinity-boltz`:ドッキングをBoltz-2と統合する(個別のドッキングパートを置き換える)。
- Part 07 `drug-target-gnn`:GNN予測でドッキング候補を事前にフィルタリングする。
- Part 12 `single-cell-perturbation`:トップのドッキング配位子の細胞応答をin silicoで予測する。
- Part 14 `bio-mcp-agent`:ドッキングパイプラインをMCPツールとして公開する。
## 参考文献
1. Trott O, Olson AJ. "AutoDock Vina: Improving the speed and accuracy of docking." Journal of Computational Chemistry 2010. `https://onlinelibrary.wiley.com/doi/10.1002/jcc.21334`
2. Corso G, Stärk H, Jing B, et al. "DiffDock: Diffusion Steps, Twists, and Turns for Molecular Docking." ICLR 2023. `https://arxiv.org/abs/2210.01776`
3. Miller B, Corso G, et al. "DiffDock-Glide: a hybrid physics-based and data-driven approach to molecular docking." bioRxiv 2025. `https://www.biorxiv.org/content/10.1101/2025.06.02.657461v1`
4. Oxford RLDiff GitHub: `https://github.com/oxpig/RLDiff`
5. Buttenschoen M, Morris GM, Deane CM. "PoseBusters: AI-based docking methods fail to generate physically valid poses or generalise to novel sequences." Chemical Science 2024. `https://pubs.rsc.org/en/content/articlelanding/2024/sc/d3sc04185a`
6. DiffDock GitHub Issues: `https://github.com/gcorso/DiffDock/issues`
7. Chen L, Cruz A, Ramsey S, et al. "Hidden bias in the DUD-E dataset leads to misleading performance of deep learning in structure-based virtual screening." PLoS ONE 2019.
8. Amaro RE et al. "Ensemble Docking in Drug Discovery." Biophysical Journal 2018.
9. RDKit MolStandardize documentation: `https://www.rdkit.org/docs/source/rdkit.Chem.MolStandardize.html`
10. Vina GitHub: `https://github.com/ccsb-scripps/AutoDock-Vina`
11. OpenBabel: `http://openbabel.org/`
12. RDKit: `https://www.rdkit.org/`
13. PyMOL open-source: `https://github.com/schrodinger/pymol-open-source`
14. PDBbind: `http://www.pdbbind.org.cn/`
15. DUD-E: `http://dude.docking.org/`
16. LIT-PCBA (バイアスがないベンチマーク): Tran-Nguyen VK et al. J Chem Inf Model 2020.
17. PDBFixer (OpenMM ファミリー): `https://github.com/openmm/pdbfixer`
18. PoseBusters GitHub: `https://github.com/maabuu/posebusters`
19. COVID Moonshot consortium: `https://postera.ai/moonshot/`
20. SARS-CoV-2 Mpro 構造 (PDB 6LU7 など): `https://www.rcsb.org/`

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...