Skip to content

Commit 1662147

Browse files
kmbandyclaude
andcommitted
feat(mad281): E.5 rung-A gptq arm in smoke harness (wiring only)
Adds the 'gptq' arm: trains frozen Axis A to convergence, then ONE post-loop full-H GPTQ index re-solve (collect_target_hessians + gptq_reassign_targets) against the tuned centroids, re-measures holdout KL. Per-step reassign now guarded to mse/pv only. Syntax/import/wiring verified on CPU; GPU run is the supervised gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent dd1304f commit 1662147

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

scripts/calibration/smoke_fp8_qat.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
from transformers import AutoTokenizer
3030
from act_replay import (load_hf_model, _LMWrap, _attach_one, _install_one,
3131
map_gguf_to_hf, assistant_delimiters, batch_response_mask,
32-
reassign_targets, lr_warmup_cosine)
32+
reassign_targets, lr_warmup_cosine,
33+
collect_target_hessians, gptq_reassign_targets)
3334
from act_replay_student import select_targets
3435
from gguf_state import open_ml8_gguf, list_ml8_names
3536
from kl_loss import topk_teacher, kl_topk
@@ -58,7 +59,8 @@ def main():
5859
import argparse
5960
ap = argparse.ArgumentParser()
6061
ap.add_argument("--arms", default="frozen,mse,pv",
61-
help="comma list of arms: frozen,mse,pv (pv expands over --pv-fracs)")
62+
help="comma list of arms: frozen,mse,pv,gptq "
63+
"(pv expands over --pv-fracs; gptq = Axis B v2 full-H re-solve)")
6264
ap.add_argument("--pv-fracs", default="0.1",
6365
help="comma list of pv trust-region fractions (one pv arm each)")
6466
ap.add_argument("--eval-interval", type=int, default=1,
@@ -164,7 +166,9 @@ def run_arm(label, reassign_mode, reassign_frac, eval_interval, max_steps):
164166
opt.param_groups[1]["lr"] = base[1] * mult
165167
opt.step(); opt.zero_grad(); step += 1
166168
flips = 0
167-
if reassign_mode != "none" and step % REASSIGN_INTERVAL == 0:
169+
# mse/pv reassign in-loop; gptq (Axis B v2) is a single post-Axis-A
170+
# re-solve done after the loop, so it trains frozen here.
171+
if reassign_mode in ("mse", "pv") and step % REASSIGN_INTERVAL == 0:
168172
flips = reassign_targets(tlist, reassign_mode, frac=reassign_frac)
169173
# Eval cadence: reassign_interval is a multiple of eval_interval in
170174
# practice, so every reassign step also reports its post-flip KL.
@@ -176,6 +180,15 @@ def run_arm(label, reassign_mode, reassign_frac, eval_interval, max_steps):
176180
break
177181
sps = max_steps / (time.time() - t0)
178182
print(f"[arm {label}] start {k0:.4f} -> final {kf:.4f} ({sps:.3f} steps/s)", flush=True)
183+
# Axis B rung A: ONE full-H GPTQ index re-solve against the now-tuned centroids.
184+
# Collect the rotated activation Hessian fresh for THIS arm's tuned state, then
185+
# re-solve indices (sequential, H^-1-compensated — cannot diverge like pv).
186+
if reassign_mode == "gptq":
187+
print(f"[arm {label}] collecting rotated Hessians ({len(targets)} targets)...", flush=True)
188+
H_by_name = collect_target_hessians(targets, train_w, model, dev)
189+
nflip = gptq_reassign_targets(targets, H_by_name, percdamp=0.05, act_order=True)
190+
kf = holdout_kl()
191+
print(f"[arm {label}] post-GPTQ-reassign KL {kf:.4f} ({nflip} indices changed)", flush=True)
179192
return k0, kf
180193

181194
# Build arm specs from CLI: frozen/mse once, pv once per requested frac.
@@ -188,6 +201,8 @@ def run_arm(label, reassign_mode, reassign_frac, eval_interval, max_steps):
188201
elif a == "pv":
189202
for fr in PV_FRACS:
190203
arm_specs.append((f"pv_f{fr:g}", "pv", fr))
204+
elif a == "gptq":
205+
arm_specs.append(("gptq", "gptq", 0.0))
191206
results = {}
192207
for label, mode, fr in arm_specs:
193208
results[label] = run_arm(label, mode, fr, EVAL_INTERVAL, STEPS)

0 commit comments

Comments
 (0)