fix(train): 首次正式预训练(21850 步闭环到达 0%)排查后修正——FK/平滑改加在配对去噪估计上(原加在随机噪声一步采样上=回归条件均值,多峰塌成单峰,实测候选标准差 0.030/幅度 0.151);时间嵌入最高角频率 1000→50、MF 分支 fp32、p_neq 前 5000 步为 0(实测 du/dt 均方根 6–12 vs v 1.1);增广 40%/3°/12 步收回;新增 dagger 阶段(策略闭环状态请老师重规划 ×2 轮微调);开训前老师轨迹回放自检;评估加开环误差与候选多样性,best/早停按到达率+开环误差

This commit is contained in:
Hark
2026-10-18 15:56:39 +00:00
parent c2732fb3cd
commit 979a5814c1
19 changed files with 386 additions and 61 deletions
+16 -4
View File
@@ -7,6 +7,7 @@
# gen 生成老师轨迹(NPROC 进程;CONSENSUS=1 时加共识过滤;样本不足 TARGET_SAMPLES 自动补生成)
# prep 打包训练样本 + R2 标签一致性检查
# train 预训练(先 2000 步摸吞吐,再正式训练);输出目录随头分开:ml/runs/<CFG 名>
# dagger DAgger 纠偏(2026-10-18 新增):策略闭环走到的状态请老师重新规划、并入数据微调 DAG_ROUNDS 轮(ml/dagger/run.sh)
# m5 头门禁:贴立柱集穿柱率 ≤ 2%(纯策略口径),同时报仿真安全层口径;通过则记为选定模型,不过自动训 WTA 头再判
# apg APG 首轮微调(从选定模型开始)
# mine 挖错循环(3–6 轮,含门禁回滚)
@@ -45,10 +46,11 @@ SEL=ml/runs/selected_ckpt
ckpt() { if [ -n "${CKPT:-}" ]; then echo "$CKPT"; elif [ -f $SEL ]; then cat $SEL; else echo ml/runs/$TAG/best.pt; fi; }
stage=${1:-help}
run() { echo "== $*" >&2; "$@"; } # 回显走 stderr:gate1 用 tee 把 stdout 存成 consistency.json,回显混进去会让后面读它时 JSONDecodeError
ALL_STAGES="setup kin r4 gate1 gen prep train m5 apg mine export bench accept"
ALL_STAGES="setup kin r4 gate1 gen prep train dagger m5 apg mine export bench accept"
stage_info() { case $1 in
gen) echo "target_tasks=$(( (N_TASKS + NPROC - 1) / NPROC * NPROC ))" ;;
train) echo "tag=$TAG bench_steps=2000" ;;
dagger) echo "tag=$TAG rounds=${DAG_ROUNDS:-2}" ;;
m5) echo "tag=$TAG" ;;
mine) echo "rounds=$ROUNDS apg_steps=$APG_STEPS" ;;
esac; }
@@ -78,13 +80,21 @@ trap 'exit 143' TERM INT HUP # 被停止 / 超时:先走 on_exit 记返
# ---- 训练与门禁的单元(m5 自动分支要对两种头各调一次)
train_one() { # $1 = 配置文件
local cfg=$1 tag; tag=$(basename "$1" .json)
# 2026-10-18:开训前先把老师轨迹放进 PyTorch 仿真口径里回放——口径对不上时闭环指标不可信,训多少步都白训(rc 5 停)
[ -f ml/runs/replay_teacher.json ] || run $PY -m ml.eval.replay_teacher --n 512 --out ml/runs/replay_teacher.json
if [ -f ml/runs/bench_$tag/last.pt ]; then echo "吞吐摸底 ml/runs/bench_$tag 已有,跳过"
else run $PY -m ml.train --samples ml/data/samples --out ml/runs/bench_$tag --steps ${BENCH_STEPS:-2000} --no-eval --config $cfg; fi
local res=""; [ -f ml/runs/$tag/last.pt ] && { res="--resume ml/runs/$tag/last.pt"; echo "发现 ml/runs/$tag/last.pt → 续训"; }
run $PY -m ml.train --samples ml/data/samples --out ml/runs/$tag --config $cfg $res
}
m5_one() { # $1 = 头标签;返回 0 通过 / 3 不通过
local tag=$1 ck=${CKPT:-ml/runs/$1/best.pt} o
dagger_one() { # $1 = 头标签:从该头的预训练 best.pt 起做 DAgger,最终模型路径写进 ml/runs/<tag>_dagger.ckpt
local tag=$1
[ -f ml/runs/$tag/best.pt ] || { echo "DAgger:ml/runs/$tag/best.pt 不存在(预训练没完成)"; return 3; }
run bash ml/dagger/run.sh $tag ml/runs/$tag/best.pt
}
m5_one() { # $1 = 头标签;返回 0 通过 / 3 不通过。起点模型:CKPT > DAgger 结果 > 预训练 best.pt
local tag=$1 ck o
if [ -n "${CKPT:-}" ]; then ck=$CKPT; elif [ -f ml/runs/${1}_dagger.ckpt ]; then ck=$(cat ml/runs/${1}_dagger.ckpt); else ck=ml/runs/$1/best.pt; fi
[ -f "$ck" ] || { echo "M5:$ck 不存在(训练发散或没训完)→ 按不通过处理"; return 3; }
# 断点续跑:结果文件比检查点新 → 这一半已经评过,跳过
o=ml/runs/m5_${tag}_policy.json; [ -f $o ] && [ $o -nt "$ck" ] && echo "M5:$o 已有,跳过" || run $PY -m ml.sim.closed_loop --ckpt $ck --tasks ml/runs/nc_gate.jsonl --n ${M5_N:-1000} --out $o
@@ -154,6 +164,7 @@ case $stage in
echo "警告:R2 不通过(近邻标签不自洽,见 ml/data/r2.json)。按默认继续训练,验收汇总会列出"
fi ;;
train) train_one $CFG ;;
dagger) dagger_one $TAG ;;
m5) [ -f ml/runs/nc_gate.jsonl ] || run $PY -m ml.mining.mine_round --make-gate ${M5_N:-1000} --seed 4321 --mix 0,0,1,0 --name nc_gate.jsonl --out ml/runs
if m5_one $TAG; then :
elif [ "$TAG" != wta ] && [ "${AUTO_WTA:-1}" = 1 ] && [ -z "${CKPT:-}" ]; then
@@ -161,11 +172,12 @@ case $stage in
echo "M5:$TAG 头不通过 → 自动训练 WTA 回退头(约 3 小时)"
$PY -m ml.pstate set m5 branch=wta
train_one ml/configs/wta.json
dagger_one wta
m5_one wta || { echo "M5:两种头都未通过,把 ml/runs/m5_gate_*.json 发我"; exit 3; }
elif [ "${M5_STRICT:-1}" = 0 ]; then echo "M5:不通过,M5_STRICT=0(冒烟)→ 照常继续"; echo ml/runs/$TAG/best.pt > $SEL
else echo "M5:不通过,把 ml/runs/m5_gate_*.json 发我"; exit 3; fi ;;
apg) ck=$(ckpt); res=""; [ -f ml/runs/apg/last.pt ] && { res="--resume ml/runs/apg/last.pt"; echo "发现 ml/runs/apg/last.pt → 续跑"; }
run $PY -m ml.apg.apg_finetune --init $ck --samples ml/data/samples --out ml/runs/apg ${APG_FIRST_STEPS:+--steps $APG_FIRST_STEPS} $res; cp ml/runs/apg/best.pt ml/runs/current.pt ;;
run $PY -m ml.apg.apg_finetune --init $ck --samples ml/data/samples $(ls -d ml/data/samples_dag_* 2>/dev/null | tr '\n' ' ') --out ml/runs/apg ${APG_FIRST_STEPS:+--steps $APG_FIRST_STEPS} $res; cp ml/runs/apg/best.pt ml/runs/current.pt ;;
mine) run bash ml/mining/loop.sh $ROUNDS $APG_STEPS $MINE_N ;;
monitor) run $PY -m ml.monitor ${MONITOR_ARGS:-} ;;
selftest) run bash ml/selftest.sh ;;