# LNP-ML + BioT5-plus 快速上手指南 适用于:拿到代码包、从未运行过任何代码的新组员。 --- ## 前提条件(收到代码包前确认) - Google Drive 的 `MyDrive/lnp_project/` 下已有以下两个文件夹: - `lnp_ml/`:项目代码 - `biot5-plus-base/`:BioT5-plus 权重(无需重新下载) - `lnp_ml/data/processed/` 下已有处理好的数据文件 --- ## Cell 1:挂载 Drive ```python from google.colab import drive drive.mount('/content/drive') ``` --- ## Cell 2:安装依赖 > 每次重新打开 Colab 都需要重跑这一步,依赖不会自动保留。 ```python !pip install rdkit loguru transformers sentencepiece optuna -q ``` --- ## Cell 3:配置路径 + 确认文件完整 > 所有 cell 都依赖这里定义的 `LNP_PATH` 和 `MODEL_PATH`,必须先运行。 ```python import os, sys LNP_PATH = "/content/drive/MyDrive/lnp_project/lnp_ml" MODEL_PATH = "/content/drive/MyDrive/lnp_project/biot5-plus-base" sys.path.insert(0, LNP_PATH) os.chdir(LNP_PATH) checks = [ f"{LNP_PATH}/lnp_ml/modeling/models.py", f"{LNP_PATH}/lnp_ml/modeling/encoders/llm_encoder.py", f"{LNP_PATH}/lnp_ml/modeling/encoders/__init__.py", f"{LNP_PATH}/lnp_ml/featurization/smiles.py", f"{MODEL_PATH}/config.json", f"{MODEL_PATH}/tokenizer_config.json", f"{LNP_PATH}/data/processed/train.parquet", f"{LNP_PATH}/data/processed/val.parquet", f"{LNP_PATH}/data/processed/test.parquet", f"{LNP_PATH}/data/processed/train_pretrain.parquet", f"{LNP_PATH}/data/processed/val_pretrain.parquet", ] for f in checks: print(f"{'✓' if os.path.exists(f) else '✗ 缺失'} {f}") ``` **所有文件都显示 ✓ 再继续。如果有 ✗,先补齐对应文件。** --- ## Cell 4:验证 LLM 模块(正式训练前必做) > 验证数据流、维度对齐、梯度链路、可复现性,四项全部通过再训练。 ```python !PYTHONPATH={LNP_PATH} \ python {LNP_PATH}/verify_llm_encoder.py \ --model_path "{MODEL_PATH}" \ --lnp_repo_path "{LNP_PATH}" ``` **正常输出:** ``` TEST 1 PASSED ✓ TEST 2 PASSED ✓ TEST 3 PASSED ✓ TEST 4 PASSED ✓ ALL TESTS PASSED ✓ ``` --- ## Cell 5:预训练(用外部 LiON 数据) > 在约 9000 条外部数据上预训练 delivery 任务,产出 `models/pretrain_delivery.pt`。 > 约需 10-15 分钟。 ```python !PYTHONPATH={LNP_PATH} \ python -m lnp_ml.modeling.pretrain main \ --train-path data/processed/train_pretrain.parquet \ --val-path data/processed/val_pretrain.parquet \ --epochs 50 \ --lr 1e-4 \ --device cuda ``` 完成后确认: ```python import os print("✓ 预训练权重存在" if os.path.exists(f"{LNP_PATH}/models/pretrain_delivery.pt") else "✗ 预训练权重未生成,检查上面的输出") ``` --- ## Cell 6:正式训练(含 LLM,约 20-25 分钟) > 使用 Optuna 做 3-fold 超参搜索(20 trials),然后全量数据训练。 > 产出 `models/final/model.pt`。 ```python !PYTHONPATH={LNP_PATH} \ python lnp_ml/modeling/final_train_optuna_cv.py \ --init-from-pretrain models/pretrain_delivery.pt \ --use-llm \ --llm-model-path "{MODEL_PATH}" \ --llm-device cuda \ --n-trials 20 \ --epochs-per-trial 30 \ --seed 42 \ --device cuda \ --output-dir models/final ``` 完成后确认: ```python print("✓ 模型权重存在" if os.path.exists(f"{LNP_PATH}/models/final/model.pt") else "✗ 模型未生成,检查上面的输出") ``` --- ## Cell 7:测试评估 ```python !PYTHONPATH={LNP_PATH} \ python lnp_ml/modeling/predict.py test \ --test-path data/processed/test.parquet \ --model-path models/final/model.pt \ --output-path models/final/test_results.json import json with open(f'{LNP_PATH}/models/final/test_results.json') as f: results = json.load(f) print("=== 分类任务 ===") for task in ['pdi', 'ee', 'toxic']: m = results['detailed_metrics'][task] print(f" {task}: acc={m['accuracy']:.4f}, f1={m['f1']:.4f}") print("\n=== 回归任务 ===") for task in ['size', 'delivery']: m = results['detailed_metrics'][task] print(f" {task}: R²={m['r2']:.4f}, RMSE={m['rmse']:.4f}") print("\n=== 分布任务 ===") m = results['detailed_metrics']['biodist'] print(f" biodist: KL={m['kl_divergence']:.4f}, JS={m['js_divergence']:.4f}") ``` **参考指标(基于已有实验结果):** | 任务 | 指标 | 参考值 | |---|---|---| | delivery | R² | ~0.63 | | size | R² | ~0.42 | | pdi | acc | ~0.69 | | ee | acc | ~0.68 | | toxic | acc | ~0.96 | | biodist | KL | ~0.70 | --- ## Cell 8:备份模型到 Drive ```python !cp -r {LNP_PATH}/models/final \ {LNP_PATH}/models/final_backup print("备份完成 ✓") ``` --- ## 常见问题 | 报错 | 原因 | 解决方法 | |---|---|---| | `No module named 'rdkit'` | 依赖未安装 | 重新运行 Cell 2 | | `No module named 'lnp_ml'` | 路径未配置 | 重新运行 Cell 3 | | `No such option '--use-llm'` | Drive 里的 `final_train_optuna_cv.py` 是旧版本 | 确认代码包里的文件是最新版本 | | `running_mean should contain 217 elements not 210` | `models.py` 里 `desc` 维度是旧值 210 | 把 `DEFAULT_INPUT_DIMS` 里的 `"desc": 210` 改为 `"desc": 217` | | `KeyError: attribute 'projection' already exists` | `llm_encoder.py` 是旧版本 | 确认代码包里的文件是最新版本 | | `RuntimeError: Unexpected key(s) in state_dict` | 加载模型时 strict=True | 确认 `predict.py` 里用的是 `strict=False` | | Colab 断开后重连 | 环境变量丢失 | 从 Cell 1 重跑,Cell 5/6 已有权重可跳过 | --- ## 如果已有训练好的模型,直接从 Cell 7 开始 只需运行 Cell 1 → Cell 2 → Cell 3 → Cell 7,跳过 Cell 4、5、6。