File size: 3,850 Bytes
5c5099a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #!/usr/bin/env python3
"""
SMI-TED BBBP 分类验证 — 启用 FlagGems 算子。
使用 encode() 提取嵌入 + XGBoost 分类,对标官方 notebook ROC-AUC = 0.9194。
用法:
python scripts/inference/validate_bbbp_flaggems.py
# 排除特定算子
python scripts/inference/validate_bbbp_flaggems.py --flaggems-exclude mm gelu
"""
import sys
import os
import time
import argparse
import warnings
warnings.filterwarnings("ignore")
_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
_PROJECT_ROOT = os.path.dirname(os.path.dirname(_SCRIPT_DIR))
sys.path.insert(0, _PROJECT_ROOT)
import torch
import pandas as pd
import numpy as np
from xgboost import XGBClassifier
from sklearn.metrics import roc_auc_score
import flag_gems
from models.smi_ted.smi_ted_light.load import load_smi_ted, normalize_smiles
def main():
parser = argparse.ArgumentParser(description="SMI-TED BBBP 分类验证 (FlagGems)")
parser.add_argument("--flaggems-exclude", type=str, nargs="*", default=["mm", "gelu"],
help="排除导致海光崩溃的算子 (默认: mm gelu)")
args = parser.parse_args()
model_dir = os.path.join(_PROJECT_ROOT, "models", "smi_ted", "smi_ted_light")
train_path = os.path.join(_PROJECT_ROOT, "models", "smi_ted", "finetune", "moleculenet", "bbbp", "train.csv")
test_path = os.path.join(_PROJECT_ROOT, "models", "smi_ted", "finetune", "moleculenet", "bbbp", "test.csv")
device = "cuda" if torch.cuda.is_available() else "cpu"
# ── 启用 FlagGems ──
exclude = set(args.flaggems_exclude)
log_path = os.path.join(_PROJECT_ROOT, "flag_gems_enable.txt")
flag_gems.enable(unused=exclude if exclude else None, record=True, once=True, path=log_path)
print(f"FlagGems 已启用 (version: {flag_gems.__version__})")
if exclude:
print(f" 排除: {exclude}")
print()
# ── 加载数据 ──
train_df = pd.read_csv(train_path)
test_df = pd.read_csv(test_path)
train_df["norm_smiles"] = train_df["smiles"].apply(normalize_smiles)
test_df["norm_smiles"] = test_df["smiles"].apply(normalize_smiles)
train_df = train_df.dropna()
test_df = test_df.dropna()
print(f"数据集: BBBP (血脑屏障渗透)")
print(f" 训练集: {len(train_df)} 分子")
print(f" 测试集: {len(test_df)} 分子")
# ── 加载模型 ──
print("加载模型...")
model = load_smi_ted(folder=model_dir, ckpt_filename="smi-ted-Light_40.pt")
model.eval()
if device == "cuda":
model = model.cuda()
# ── 提取嵌入 ──
print("提取训练集嵌入...")
t0 = time.time()
with torch.no_grad():
train_emb = model.encode(train_df["norm_smiles"].tolist())
print(f" 训练集: {train_emb.shape} 耗时: {time.time() - t0:.1f}s")
print("提取测试集嵌入...")
t0 = time.time()
with torch.no_grad():
test_emb = model.encode(test_df["norm_smiles"].tolist())
print(f" 测试集: {test_emb.shape} 耗时: {time.time() - t0:.1f}s")
# ── XGBoost 分类 ──
print("训练 XGBoost 分类器...")
xgb = XGBClassifier(n_estimators=2000, learning_rate=0.04, max_depth=8)
xgb.fit(train_emb, train_df["p_np"])
y_prob = xgb.predict_proba(test_emb)[:, 1]
roc_auc = roc_auc_score(test_df["p_np"], y_prob)
# ── 输出结果 ──
print(f"\n{'=' * 50}")
print(f"BBBP 分类验证结果 (FlagGems: 已启用)")
print(f"{'=' * 50}")
print(f" ROC-AUC: {roc_auc:.4f}")
print(f" 官方参考值: 0.9194")
print(f" 差异: {abs(roc_auc - 0.9194):.4f}")
if abs(roc_auc - 0.9194) < 0.02:
print(f"\n ✓ 验证通过 (差异 < 0.02)")
else:
print(f"\n ✗ 验证未通过!")
print(f"{'=' * 50}")
if __name__ == "__main__":
main()
|