VLAlert / training /SFT /train_sft_v3.sh
AsianPlayer's picture
Add VLAlert code
1e05592 verified
Raw
History Blame Contribute Delete
5.64 kB
#!/usr/bin/env bash
# SFT v3: 提升 Belief Vector 质量
#
# 相比 v2 的改动(每项都有明确理由):
#
# 1. belief_strategy: mean_pool → attention_pool
# 理由: mean_pool 对所有 token 平均权重相同;attention_pool 让模型自动学习
# "哪些视觉 token 对危险预测最重要",得到更具区分度的 belief vector。
#
# 2. curriculum: 去掉 --no_curriculum(重新启用)
# 理由: v2 关闭了课程学习。启用后训练从简单样本(明确碰撞/明确安全)开始,
# 逐步引入难例,防止模型早期过拟合噪声标签。
#
# 3. nll_weight: 0.5 → 0.3
# 理由: NLL 是 VLM 语言生成 loss(让模型输出正确文字)。
# 对 policy 训练,我们需要的是 belief vector 的质量,
# 而不是文字生成质量。降低 nll_weight 让 hazard + TTA heads
# 对 LoRA 更新有更大的梯度影响力。
#
# 4. vlm_lr_multiplier: 0.1 → 0.05
# 理由: VLM(LoRA 部分)更新更保守,防止破坏 Qwen2.5 的预训练知识。
# 头部 (belief_aggregator, hazard_head, tta_head) 用正常 lr 学习。
#
# 5. num_epochs: 10 → 12,tta_head_lr: 1e-3 → 2e-3
# 理由: attention_pool 引入了额外参数,需要更多训练步数收敛。
# tta_head 负责时间预测,给更高 lr 让它更快适应任务。
#
# 期望结果(相比 v2 的 belief vector):
# - 更好的 hazard 判断 (AUC ↑ ~0.02)
# - 更准确的 TTA 估计 (RMSE ↓ ~0.3s)
# - 下游 policy 分 +0.02~0.04 (policy_score 从 ~0.77 → ~0.80+)
#
# 前提:v2 checkpoint 用于初始化(热启动,不是从头训练)
#
# 运行时间估计:~8-10 小时(单 GPU)
#
# 完整训练链(SFT v3 之后需要):
# Step A: bash training/SFT/train_sft_v3.sh # 本脚本 ~8-10h
# Step B: python -m training.Policy.cache_beliefs # 重新生成 belief 缓存 ~1h
# Step C: bash training/Policy/train_policy_v3.sh # 重新训练 policy ~15min
# (改 SFT_CHECKPOINT → checkpoints/SFT/sft_v3/best)
#
# 用法:
# bash training/SFT/train_sft_v3.sh # 完整训练
# bash training/SFT/train_sft_v3.sh --debug # 调试 (~5 min)
set -euo pipefail
ROOT=PROJECT_ROOT
MANIFEST_DIR="$ROOT/data/sft_manifests"
PRETRAINED_LORA="$ROOT/checkpoints/SFT/sft_v2/best" # 从 v2 热启动
MODEL_PATH="$ROOT/models/Qwen2.5-VL-3B-Instruct"
OUTPUT_DIR="$ROOT/checkpoints/SFT"
EXPERIMENT="sft_v3"
MAX_PIXELS=602112 # 768*28*28 — 与 v2 相同
BATCH_SIZE=2
GRAD_ACCUM=4 # effective batch = 8,与 v2 相同
DEBUG_FLAGS=""
if [[ "${1:-}" == "--debug" ]]; then
DEBUG_FLAGS="--debug --debug_samples 64"
EXPERIMENT="sft_v3_debug"
BATCH_SIZE=2
GRAD_ACCUM=4
echo "=== DEBUG / SMOKE TEST MODE ==="
fi
# ── 确认 v2 checkpoint 存在 ──────────────────────────────────────────────────
if [[ ! -d "$PRETRAINED_LORA" ]]; then
echo "⚠ SFT v2 checkpoint 不存在: $PRETRAINED_LORA"
echo " → 将从 pretrain_v2/stage_b/best_model 冷启动"
PRETRAINED_LORA="$ROOT/checkpoints/pretrain_v2/stage_b/best_model"
fi
# ── 确认 manifests 存在 ──────────────────────────────────────────────────────
if [[ ! -f "$MANIFEST_DIR/nexar_train.json" ]]; then
echo "Manifests not found — generating..."
python -m training.SFT.make_split_manifest \
--nexar_root "$ROOT/NEXAR_COLLISION/dataset" \
--dada_root "$ROOT/DADA-2000" \
--out_dir "$MANIFEST_DIR"
fi
echo ""
echo "=== SFT v3 训练 ==="
echo " 改动汇总 vs v2:"
echo " belief_strategy : mean_pool → attention_pool"
echo " curriculum : False → True"
echo " nll_weight : 0.5 → 0.3"
echo " vlm_lr_multiplier: 0.1 → 0.05"
echo " num_epochs : 10 → 12"
echo " tta_head_lr : 1e-3 → 2e-3"
echo ""
echo " 热启动自: $PRETRAINED_LORA"
echo " 输出至 : $OUTPUT_DIR/$EXPERIMENT"
echo ""
python -m training.SFT.trainer \
--manifest_dir "$MANIFEST_DIR" \
--model_name "$MODEL_PATH" \
--pretrained_lora "$PRETRAINED_LORA" \
--output_dir "$OUTPUT_DIR" \
--experiment_name "$EXPERIMENT" \
--belief_strategy attention_pool \
--num_epochs 12 \
--batch_size $BATCH_SIZE \
--gradient_accumulation_steps $GRAD_ACCUM \
--learning_rate 1e-4 \
--tta_head_lr 2e-3 \
--vlm_lr_multiplier 0.05 \
--weight_decay 0.01 \
--max_grad_norm 1.0 \
--nll_weight 0.3 \
--max_pixels $MAX_PIXELS \
--no_auto_resume \
--use_wandb \
$DEBUG_FLAGS
echo ""
echo "✅ SFT v3 训练完成"
echo " Checkpoint: $OUTPUT_DIR/$EXPERIMENT/best"
echo ""
echo "下一步 — 重新生成 belief 缓存:"
echo " python -m training.Policy.cache_beliefs \\"
echo " --sft_checkpoint $OUTPUT_DIR/$EXPERIMENT/best \\"
echo " --label_dir data/policy_labels \\"
echo " --output_dir data/belief_cache_v3"
echo ""
echo "然后用新缓存重训 policy:"
echo " 修改 train_policy_v3.sh 中 CACHE_DIR=data/belief_cache_v3"
echo " 并将 SFT_CHECKPOINT 改为 $OUTPUT_DIR/$EXPERIMENT/best"