lnp_ml/docs/colab_biot5_quickstart.md

210 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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。