| """Claim-5 matched-learning-rate control. |
| |
| The paper's own model-selection rule (pick the learning rate with the best |
| zero-shot Humanities accuracy) happened to select very different step sizes for |
| the two arms in our runs -- 1e-5 for all-attention (Q/K/V) but 3e-4 for |
| value-matrix-only (V). The two fine-tuned models therefore sit at very |
| different distances from the base model, which confounds any comparison of how |
| much in-context ability each one retained. |
| |
| This control removes that confound: it trains BOTH arms at the SAME learning |
| rate (1e-4, the middle of the paper's grid, where both arms score well on the |
| zero-shot objective) with the same seeds, and re-measures 0-shot and 7-shot |
| accuracy on all four categories. |
| |
| Emits results/claim5_matched.json. |
| """ |
| import argparse, json, os, torch |
| import mmlu_data as MD |
| import claim5_mmlu_qwen_finetune as C |
|
|
|
|
| def main(): |
| ap = argparse.ArgumentParser() |
| ap.add_argument("--out", default="/work/results") |
| ap.add_argument("--lr", type=float, default=1e-4) |
| ap.add_argument("--seeds", type=int, default=2) |
| ap.add_argument("--bsz", type=int, default=32) |
| a = ap.parse_args() |
| os.makedirs(a.out, exist_ok=True) |
|
|
| C.log("building MMLU data ...") |
| data = MD.build() |
| tok = C.load_tok() |
| out = {"model": C.MODEL_ID, "matched_lr": a.lr, "lora_r": C.LORA_R, |
| "epochs": C.EPOCHS, "n_eval_per_cat": MD.N_EVAL_PER_CAT, |
| "n_shot": MD.N_SHOT, "arms": {}} |
| path = os.path.join(a.out, "claim5_matched.json") |
|
|
| def dump(): |
| json.dump(out, open(path, "w"), indent=2) |
|
|
| C.log("=== BASE MODEL (re-measured for a self-contained control) ===") |
| base = C.load_base() |
| out["base"], out["base_hits"] = C.eval_all(base, tok, data, batch_size=a.bsz) |
| del base; torch.cuda.empty_cache() |
| dump() |
|
|
| for tgt in ("qkv", "v"): |
| out["arms"][tgt] = {"lr": a.lr, "seeds": []} |
| for s in range(a.seeds): |
| C.log(f"=== MATCHED target={tgt} lr={a.lr:g} seed={s} ===") |
| m, meta = C.train_lora(tok, data, tgt, a.lr, seed=s) |
| acc, hits = C.eval_all(m, tok, data, batch_size=a.bsz) |
| out["arms"][tgt]["seeds"].append( |
| {"seed": s, "acc": acc, "hits": hits, **meta}) |
| del m; torch.cuda.empty_cache() |
| dump() |
| C.log("MATCHED CONTROL DONE") |
| dump() |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|