mirror of
https://github.com/wassname/evil_MoE.git
synced 2026-08-01 12:30:07 +08:00
feat: knob-ON eval (route arms) for like-for-like train-vs-deploy + teacher-off marker
The 2x2 train row used per-step hack_s (noisy n=28 train batch, knob-on) vs the deploy row's smooth n=64 eval (knob-off) -- different estimators, confounded. Now at each eval step route arms ALSO run the SAME n=64 eval with the quarantine ACTIVE (knob-on = training policy), logged as hk_on/slv_on. vanilla/erase reuse deploy (no quarantine -> knob-on==knob-off). plot_dynamics prefers hk_on for the train series so the 2x2 differs ONLY in knob state. Also: plot parses --teacher-off-step from argv and shades the teacher-ON region [0,toff] + a dashed cut line in the 2x2. The stashed long-run route2 jobs (92 KL, 94 teacher-off) inherit the knob-on eval automatically at runtime. Smoke (route2 hk_on present + logged, both plot parse paths) green. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
@@ -145,6 +145,11 @@ class StepLogger:
|
||||
]
|
||||
if arm in ("routing", "routing2"):
|
||||
cols += [
|
||||
# Knob-ON eval: SAME eval set/n/T as hk_dep but quarantine ACTIVE
|
||||
# (training-time policy). Like-for-like train series vs the knob-off
|
||||
# hk_dep, for the train-vs-deploy 2x2. nan between eval steps.
|
||||
_Col("hack_kon", 7, "hk_on", "+.2f", "knob-ON eval hack (quarantine active = training policy); same eval set as hk_dep"),
|
||||
_Col("solve_kon", 7, "slv_on", "+.2f", "knob-ON eval solve (same eval set as slv_dep)"),
|
||||
_Col("q_egy", 6, "qE", ".2f", "grad energy into quarantine ||g_quar||/(||g_keep||+||g_quar||); ~0.5+ rising = learning dumped into the thrown-away knob"),
|
||||
_Col("hack_abl", 6, "hk_abl", "frac", "FREE per-step deploy proxy: hack rate on the ablated (deploy-mode) rollout slice; train prompts, noisier than hk_dep"),
|
||||
_Col("solve_abl", 6, "slv_abl", "frac", "free per-step deploy proxy: solve rate on the ablated rollout slice"),
|
||||
|
||||
@@ -1375,21 +1375,36 @@ def main(cfg: Config) -> int:
|
||||
# route shows a deploy eval while others show training rollouts -> different
|
||||
# n/cadence, route looks artificially smoother). NaN on non-eval steps.
|
||||
hack_deploy = solve_deploy = float("nan")
|
||||
hack_kon = solve_kon = float("nan") # knob-ON eval (route only); see below
|
||||
if cfg.eval_ablate_every > 0 and (step % cfg.eval_ablate_every == 0 or step == steps - 1):
|
||||
_was_training = model.training
|
||||
model.eval()
|
||||
is_route = cfg.intervention in ("route", "route2")
|
||||
with (ablate_quarantine(wrappers) if is_route else nullcontext()):
|
||||
ev = eval_hack_solve(model, tok, problems, eval_idxs, gen_cfg_eval, device, max_new)
|
||||
hack_deploy, solve_deploy = ev["hack"], ev["solve"]
|
||||
# Like-for-like knob-ON eval: re-run the SAME n eval prompts with the
|
||||
# quarantine ACTIVE (the training-time policy). The per-step hack_s is a
|
||||
# noisy n=28 train batch -> spiky, looks like a different estimator than
|
||||
# the smooth n=64 deploy curve. This gives a train series measured the
|
||||
# IDENTICAL way as deploy (same prompts/n/T), differing only in knob state,
|
||||
# for the train-vs-deploy 2x2. Route only: vanilla/erase have no quarantine
|
||||
# (knob-on == knob-off), so reuse the deploy number.
|
||||
if is_route:
|
||||
ev_on = eval_hack_solve(model, tok, problems, eval_idxs, gen_cfg_eval, device, max_new)
|
||||
hack_kon, solve_kon = ev_on["hack"], ev_on["solve"]
|
||||
else:
|
||||
hack_kon, solve_kon = hack_deploy, solve_deploy
|
||||
if _was_training:
|
||||
model.train()
|
||||
hack_deploy, solve_deploy = ev["hack"], ev["solve"]
|
||||
tag = "quarantine knob OFF = deployed model" if is_route else "deployed = trained model (no quarantine)"
|
||||
should = ("deploy hack < this step's training hack_s (knob is holding the cheat); "
|
||||
should = ("deploy hack < knob-ON eval hack (knob is holding the cheat); "
|
||||
"ELSE routing isn't capturing it") if is_route else "deploy ~= training hack_s (same model)"
|
||||
logger.info(
|
||||
f"step {step} DEPLOY-eval ({tag}): "
|
||||
f"hack={hack_deploy:.3f} solve={solve_deploy:.3f} n={ev['n']}. SHOULD: {should}")
|
||||
f"hack={hack_deploy:.3f} solve={solve_deploy:.3f} n={ev['n']}"
|
||||
+ (f" | knob-ON same-eval: hack={hack_kon:.3f} solve={solve_kon:.3f}" if is_route else "")
|
||||
+ f". SHOULD: {should}")
|
||||
|
||||
rewards_t = torch.tensor(agg_rew, dtype=torch.float32) if agg_rew else torch.zeros(1)
|
||||
rew_mean = rewards_t.mean().item()
|
||||
@@ -1522,6 +1537,11 @@ def main(cfg: Config) -> int:
|
||||
# are unaffected. plot_dynamics reads it by name.
|
||||
"hack_deploy": hack_deploy,
|
||||
"solve_deploy": solve_deploy,
|
||||
# Knob-ON eval: SAME n eval prompts as deploy, quarantine active = the
|
||||
# training-time policy. Like-for-like train series for the train-vs-deploy
|
||||
# 2x2 (vs the noisy per-step hack_s batch). route only; else == deploy.
|
||||
"hack_kon": hack_kon,
|
||||
"solve_kon": solve_kon,
|
||||
# Free per-step deploy proxy from the ablated rollout slice (above).
|
||||
"hack_abl": (hack_abl_n, n_abl_step) if n_abl_step else (0, 0),
|
||||
"solve_abl": (gt_abl_n, n_abl_step) if n_abl_step else (0, 0),
|
||||
|
||||
Reference in New Issue
Block a user