Files
2026-07-12 21:41:12 +08:00

388 lines
18 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.
# alpamayo-0.5B
`alpamayo-0.5B` 是 [NVIDIA Alpamayo](https://github.com/NVlabs/alpamayo) 的最小复现,
面向单机、单样本的架构与接口验证。
项目使用带 Qwen2.5-0.5B 文本骨干的 VLM 和缩小版 diffusion expert,覆盖以下完整链路:
1. 图像、自然语言和 ego-relative 历史坐标进入 VLM;
2. VLM 生成驾驶指令,也可以在未截断验证分支中生成结构化指令、meta-action 和
离散轨迹 token;
3. VLM 的 24 层 past-KV 作为 expert 的前缀;
4. flow-matching diffusion 预测连续 action,再积分回未来 XY 位置。
项目目标是用可运行、可训练的最小实现验证连接方式和输出契约,而不是复刻
NVIDIA Alpamayo-R1 的完整规模、训练数据或模型能力。该实现不能用于真实车辆控制。
## 复现范围
| 范围 | 本项目 | 与 NVIDIA Alpamayo 的差异 |
| --- | --- | --- |
| VLM | Qwen2.5-0.5B 文本骨干,完整模型约 0.80B 参数 | 不使用 Alpamayo-R1 原始权重 |
| VLM–expert 连接 | 24 层 past-KV,保持 KV heads 与 head dimension 一致 | 只验证接口和缓存传递 |
| Diffusion expert | 105.6M Qwen2 expert,flow matching,10 步采样 | 使用缩小配置和二维 XY-delta action |
| 数据 | 一个 PAI `train` 事件,单样本过拟合 | 不覆盖多场景训练或泛化评估 |
| 输出 | 驾驶指令、离散轨迹 token、连续未来轨迹 | 不等同于上游完整 action space 与 tokenizer |
| 运行环境 | 单机 MPS、CUDA 或 CPU | 不包含分布式训练配置 |
最小复现包含模型下载、PAI 样本物化、两阶段训练、checkpoint 恢复、reload evaluation、
结构化 VLM cache handoff 和结果比较脚本。仓库不分发模型权重或 gated 数据。
## 架构
```mermaid
flowchart LR
A["前视图像"] --> V["LLaVA VLM"]
B["驾驶问题与历史 XY"] --> V
Q["CLIP vision tower"] --> V
L["Qwen2.5-0.5B text backbone"] --> V
V --> T["驾驶文字 / structured tokens"]
V --> K["24-layer past-KV"]
N["noisy normalized XY-delta"] --> E["105.6M Qwen2 expert"]
S["diffusion timestep"] --> E
K --> E
E --> F["flow-matching vector field"]
F --> D["10-step denoising"]
D --> X["16 x 2 continuous action"]
X --> P["ego-relative future XY"]
```
连接契约不是按 hidden size 复制 VLM。expert 采用自己的 `hidden_size=512`,但保持与
VLM KV cache 相同的 24 层、2 个 KV heads 和 `head_dim=64`,因此可以直接消费缓存。
expert 没有词嵌入层;noisy action 和 timestep 经 Fourier/MLP 投影成 token embeddings,
最后由线性层输出二维 vector field。
| 组件 | 本地配置 |
| --- | --- |
| VLM checkpoint | `thkim0305/qwen2.5_0.5B_vl`,revision `c318c4b464753d86ddffe065ba6df255ae354f41` |
| VLM 类型 | `LlavaForConditionalGeneration`;CLIP vision tower + Qwen2.5-0.5B text backbone |
| VLM 参数量 | 799,262,336(“0.5B”指文本骨干;加入视觉塔后完整 VLM 约 0.80B) |
| VLM text cache | 24 层,2 KV heads,`head_dim=64` |
| Expert | 105,575,170 参数;24 层,hidden 512,intermediate 2432,8 query heads,2 KV heads,non-causal |
| Diffusion 输出 | 16 个二维 normalized XY-delta action;10 个 flow-matching inference steps |
| 运行精度 | 当前产物为 MPS + float16;代码也可选择可用的 CUDA 或 CPU |
### Expert 参数量
参数量由 `configs/local_overfit.yaml` 中的 Stage 2 配置实例化
`KVCachedDiffusionExpert` 后直接统计:
| 模块 | 参数量 |
| --- | ---: |
| 24 层 Qwen2 expert | 105,425,408 |
| Action/time projection | 148,736 |
| Action output | 1,026 |
| **合计** | **105,575,170(约 105.6M)** |
全部 `105,575,170` 个参数参与 Stage 2 训练。仅模型权重约占 `201.37 MiB`(FP16)或
`402.74 MiB`(FP32),不包含梯度、优化器状态、VLM 权重和运行时 KV cache。
主配置位于 [`configs/local_overfit.yaml`](configs/local_overfit.yaml)。
## 单样本 PAI 数据
实验只使用 `nvidia/PhysicalAI-Autonomous-Vehicles` 的一个 `train` 事件。PAI 是 gated
dataset,使用前需要在 Hugging Face 接受其许可。
| 字段 | 值 |
| --- | --- |
| Clip ID | `314f59c2-e420-4fcd-9df2-a51d572e0c20` |
| `t0_us` | `1503899` |
| Camera | `camera_front_wide_120fov` |
| Event cluster | `WORK_ZONES_TEMP_TRAFFIC_CONTROL` |
| 指令来源 | `reasoning/ood_reasoning.parquet` 中的 `coc` 字段 |
| 驾驶指令 | “Steer left following the temporary lane delineated by traffic cones through the construction zone.” |
| History | 8 个点,最后一个点为当前 ego-local 原点 |
| Future source | egomotion 的 64 个未来点,时间步 0.1 s |
| Expert target | 从 64 点以索引 `[0,4,8,12,16,21,25,29,33,37,42,46,50,54,58,63]` 取 16 点 |
[`scripts/materialize_pai_subset.py`](scripts/materialize_pai_subset.py) 将世界坐标平移、旋转到
`t0` ego-relative frame,并把单样本 manifest、图像和轨迹写入本地 `data/processed/`。
原始/处理后的 PAI 数据都被 `.gitignore` 排除,不应提交到仓库。
## 训练阶段
### Stage 1:自然语言驾驶输出
[`scripts/train_stage1_vlm.py`](scripts/train_stage1_vlm.py) 冻结 vision tower、multimodal
projector 和 LM head,只训练最后 8 个 Qwen2 language layers 及 final norm。当前 checkpoint
训练 80 steps,共 119,299,968 个可训练参数:loss 从 `3.9338069` 降至
`0.0000216427`,greedy 输出与数据集驾驶指令逐字一致。
Stage 1 输出到本地 `outputs/stage1_vlm/`,供后续两个分支使用:
- plain-text KV 分支训练现有 diffusion expert;
- structured VLM 分支继续训练轨迹 logits。
### VLM structured 未截断轨迹-token 分支
[`scripts/train_vlm_trajectory_logits.py`](scripts/train_vlm_trajectory_logits.py) 从 Stage 1
checkpoint 继续训练,并添加:
- 128 个连续 token:`<i0>` … `<i127>`;
- `<|cot_start|>`、`<|cot_end|>`;
- `<|meta_action_start|>`、`<|meta_action_end|>`;
- `<|traj_future_start|>`、`<|traj_future_end|>`。
当前 Qwen LM head 已预留 151,936 行,而原 tokenizer 长度为 151,666;扩展后的 151,800
个 token 不需要增大权重矩阵。每个 16 x 2 normalized XY-delta action 被均匀量化到
`[-4, 4]` 的 128 bins,形成 32 个监督 token。
当前结构化 checkpoint 训练 160 steps,loss 从 `14.17349` 降至 `0.0000347825`,最终
训练 accuracy 为 1.0。未截断 greedy generation 生成 32/32 个正确轨迹 token。完整
输出格式如下;`cot` 是上游兼容标记,承载的是单句驾驶指令:
```text
<|cot_start|>Steer left following the temporary lane delineated by traffic cones through the construction zone.<|cot_end|>
<|meta_action_start|>STEER_LEFT<|meta_action_end|>
<|traj_future_start|><i9><i37><i71><i38><i70><i41><i68><i46><i66><i49><i84><i63><i63><i63><i65><i67><i66><i69><i65><i67><i82><i80><i61><i77><i60><i79><i59><i78><i56><i76><i72><i86><|traj_future_end|><|im_end|>
```
另有 source-style handoff 验证:generation 到 `<|traj_future_start|>` 后屏蔽全部 128 个
trajectory logits,并把 exact generation cache 交给 diffusion。这个模式验证了 KV 接口,
但不会把 VLM 离散轨迹 token 作为 diffusion 分支的可见输出。
### Stage 2:KV-conditioned diffusion expert
[`scripts/train_stage2_expert.py`](scripts/train_stage2_expert.py) 使用 Stage 1 plain-text prefix
的 past-KV,训练 105.6M expert 预测 flow-matching vector field。目标 action 是按单样本统计量
标准化的相邻 waypoint XY delta,预测 action 经反标准化和累积求和恢复未来轨迹。
当前产物记录为 1,000 total steps:早期 250-step 权重缺少 optimizer state,之后以 legacy
warm start 运行了剩余 750 steps。因此它是 1,000-step 参数训练记录,但不是严格连续、
optimizer 完整恢复的 1,000-step run。新 checkpoint 已保存 expert、optimizer、step 和 RNG,
后续中断可用 `--resume` 精确恢复。
普通 reload evaluation 仍使用训练 expert 时的旧 plain-text prefix(sequence length 770)。
structured exact-cache handoff 的 prefix 长度为 777;接口验证成功,但旧 expert 没有在这个
新 prefix 分布上联合训练,所以该分支的轨迹质量只作诊断。
## 目录
```text
alpamayo-0.5B/
├── configs/ # 单样本实验配置
├── scripts/ # 下载、数据准备、训练、评估和比较入口
├── src/alpamayo_lite/ # VLM、action space、expert、diffusion 实现
├── tests/ # 单元测试和产物一致性测试
├── results/complete_comparison/ # 仓库中保留的轻量比较 JSON、CSV 和三方图
├── references/alpamayo-upstream/# 可选的本地只读上游 checkout;gitignored
├── models/ # 本地模型;gitignored
├── data/ # gated/raw/processed 数据;gitignored
├── outputs/ # checkpoint 和评估产物;gitignored
└── .venv/ # Python 3.12 虚拟环境;gitignored
```
## 安装
需要 Python 3.12。以下命令把环境和所有运行产物留在仓库目录内:
```bash
git clone <repository-url> alpamayo-0.5B
cd alpamayo-0.5B
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
```
登录 Hugging Face 时使用交互式认证,不要把 access token 写进配置、脚本、README、日志或
shell history:
```bash
hf auth login
```
## Notebook 复现
[`notebooks/alpamayo_0_5b_minimal_reproduction.ipynb`](notebooks/alpamayo_0_5b_minimal_reproduction.ipynb)
提供从环境安装到实验结果的顺序执行流程,包含论文链接、架构说明、权重与数据准备、连接
验证、两阶段训练、结构化轨迹分支、checkpoint 重载和三方结果比较。
安装并启动:
```bash
python -m pip install -e '.[notebook]'
python -m jupyter lab notebooks/alpamayo_0_5b_minimal_reproduction.ipynb
```
Notebook 自动选择运行模式:本地存在完整产物时使用 `reuse`,全新 clone 使用 `full`。
设置 `ALPAMAYO_PROFILE=smoke` 可执行低步数连通性检查。外部模型、manifest 和 checkpoint
可通过 Notebook 中列出的环境变量直接导入。
## 运行
所有命令均从仓库根目录执行。
下载 0.5B VLM,并记录 checkpoint provenance:
```bash
python scripts/download_model.py --config configs/local_overfit.yaml
```
下载并物化一个 PAI 样本,然后验证 VLM KV 与 expert 的形状契约:
```bash
python scripts/materialize_pai_subset.py --config configs/local_overfit.yaml
python scripts/verify_connection.py --config configs/local_overfit.yaml
```
训练 Stage 1 自然语言 VLM:
```bash
python scripts/train_stage1_vlm.py \
--config configs/local_overfit.yaml \
--steps 80
```
训练并验证 VLM 的 structured/untruncated trajectory logits:
```bash
python scripts/train_vlm_trajectory_logits.py \
--config configs/local_overfit.yaml \
--output-dir outputs/stage1_vlm_trajectory \
--steps 160 \
--trajectory-vocab-size 128 \
--action-min -4 \
--action-max 4 \
--max-new-tokens 96
```
从头训练 Stage 2 到 1,000 total steps:
```bash
python scripts/train_stage2_expert.py \
--config configs/local_overfit.yaml \
--steps 1000
```
若 `outputs/stage2_expert/checkpoints/latest/` 中已有完整 checkpoint,则精确续训到总计
1,000 steps:
```bash
python scripts/train_stage2_expert.py \
--config configs/local_overfit.yaml \
--steps 1000 \
--resume
```
重新加载 VLM/expert,固定从 seed 12 开始做 16 个 diffusion rollouts:
```bash
python scripts/evaluate_pipeline.py \
--config configs/local_overfit.yaml \
--stage2-dir outputs/stage2_expert \
--num-rollouts 16 \
--base-seed 12 \
--output outputs/reload_evaluation.json
```
验证 source-style structured VLM exact cache 能直接进入旧 expert:
```bash
python scripts/verify_structured_vlm_handoff.py \
--config configs/local_overfit.yaml \
--vlm-dir outputs/stage1_vlm_trajectory \
--stage2-dir outputs/stage2_expert \
--output-dir outputs/structured_vlm_handoff
```
汇总 GT、VLM direct trajectory 和 diffusion seed 12:
```bash
python scripts/build_complete_comparison.py \
--diffusion-seed 12 \
--output-dir outputs/complete_comparison
```
## 当前结果
两条预测使用逐字节相同的 GT action 和 GT XY。下表由保存的 NPZ 重新计算;action MSE 的
单位是 normalized-action squared,轨迹指标单位是米。
| 输出 | 解码协议 | Action MSE | ADE | FDE | Max error |
| --- | --- | ---: | ---: | ---: | ---: |
| Ground truth | GT 对自身 | 0 | 0 m | 0 m | 0 m |
| VLM trajectory tokens | greedy、未截断、128-bin | 0.0003439452 | 0.026104664 m | 0.045444489 m | 0.054956669 m |
| Diffusion | flow matching、seed 12、10 steps | 0.7453363983 | 1.125946622 m | 0.258275141 m | 2.925430649 m |
VLM 的 32 个生成 token 与量化 GT 全部匹配,因此其非零轨迹误差完全来自 128-bin
反量化。Diffusion 是随机采样;seed 12 只代表一个 rollout。16 个 seed 的平均 ADE 为
`1.530302633 m`,不应把 seed 12 当作总体均值。
![GT、VLM 与 diffusion 三方比较](results/complete_comparison/trajectory_comparison.png)
### 文字对比
| 字段 | Ground truth | 模型输出 | Exact match |
| --- | --- | --- | ---: |
| 驾驶指令 | Steer left following the temporary lane delineated by traffic cones through the construction zone. | Steer left following the temporary lane delineated by traffic cones through the construction zone. | 是 |
| Meta-action | `STEER_LEFT`(由驾驶指令规则派生) | `STEER_LEFT` | 是 |
| Diffusion conditioning text | 同上方驾驶指令 | 同上方驾驶指令 | 是 |
## 本地产物
仓库保留以下不含权重或 gated 样本的轻量结果,可直接审计完整三方对比:
- [GT/VLM/diffusion 完整比较 JSON](results/complete_comparison/comparison.json)
- [16 个 waypoint 的完整 CSV](results/complete_comparison/waypoints.csv)
- [GT/VLM/diffusion 三方比较图](results/complete_comparison/trajectory_comparison.png)
`models/`、`data/` 和 `outputs/` 默认不进入 Git。运行完成后,以下链接仅在本地工作区存在;
不要为了让它们在 GitHub 页面可用而提交 gated data 或 checkpoint 权重。
- [Stage 1 文字训练指标](outputs/stage1_vlm/stage1_metrics.json)
- [Structured VLM 训练、logits、cache 与生成指标](outputs/stage1_vlm_trajectory/trajectory_logits_metrics.json)
- [Structured VLM trajectory vocabulary](outputs/stage1_vlm_trajectory/trajectory_vocabulary.json)
- [Structured VLM 轨迹图](outputs/stage1_vlm_trajectory/vlm_discrete_trajectory.png)
- [Stage 2 训练指标](outputs/stage2_expert/stage2_metrics.json)
- [Stage 2 expert 配置](outputs/stage2_expert/expert_config.json)
- [Stage 2 seed-12 reload 轨迹图](outputs/stage2_expert/reload_trajectory.png)
- [16-seed reload 评估](outputs/reload_evaluation.json)
- [Structured exact-cache handoff 指标](outputs/structured_vlm_handoff/handoff_metrics.json)
- [Structured exact-cache handoff 轨迹图](outputs/structured_vlm_handoff/handoff_trajectory.png)
- [本地 GT/VLM/diffusion 完整比较 JSON](outputs/complete_comparison/comparison.json)
- [本地 16 个 waypoint CSV](outputs/complete_comparison/waypoints.csv)
- [本地 GT/VLM/diffusion 比较图](outputs/complete_comparison/trajectory_comparison.png)
没有列出或链接任何 checkpoint 权重文件。
## 测试状态
发布或提交结果前运行:
```bash
pytest -q
ruff check src scripts tests
```
| 检查 | 最近结果 |
| --- | --- |
| `pytest -q` | `11 passed` |
| `ruff check src scripts tests` | `All checks passed` |
## 已知限制与安全边界
- 这是一个 PAI `train` 样本的显式过拟合实验,没有验证跨 clip、跨场景或真实驾驶泛化。
- 本地 VLM 轨迹词表只有 128 bins,action 是 normalized per-waypoint XY delta;它不是上游
使用的 768-token vocabulary 或约 4,000-bin delta-tokenizer 配置,也不是上游
unicycle acceleration/curvature action space。
- action mean/scale 由同一个单样本目标轨迹拟合;VLM direct trajectory 的 32 个监督 token
也来自该目标,因此其近零误差只证明记忆和输出链路。
- `STEER_LEFT` 是 [`_infer_meta_action`](scripts/train_vlm_trajectory_logits.py) 从驾驶指令
规则派生的标签,不是 PAI 中独立提供的 meta-action ground truth。
- 当前 expert 用旧 plain-text `"Continuous action:"` prefix 训练,并未与 structured VLM
prefix 或 exact generation cache 联合训练。structured handoff 证明 24-layer KV 兼容,
不代表该 prefix 下的轨迹质量已经收敛。
- source-style handoff 会在 `<|traj_future_start|>` 屏蔽 VLM 离散轨迹 logits;未截断 VLM
轨迹输出是一个单独的能力验证分支。
- 当前 1,000-step expert 包含一次缺少 optimizer state 的 legacy warm start;需要全新、严格
连续的训练曲线时应删除本地旧产物并从头运行。
- 模型输出和本项目都不能用于控制真实车辆或做安全决策。
- 不要提交或发布 Hugging Face access token、认证缓存、gated PAI 原始/处理数据、下载的模型
权重、训练 checkpoint 或可能包含私有路径/凭据的日志。公开前应再次检查 `git status` 和
Git 历史;仅提交有权再分发的代码与文档。
本项目代码按 [Apache-2.0](LICENSE) 发布。上游归属、修改说明及不随仓库分发的模型/数据
声明见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。本地工作区可另行检出
`references/alpamayo-upstream/` 进行接口研究,但该目录不会随本仓库分发。