item 31 pre-registered (Nils's design): synthetic memory tokens — burst states → per-band-layer KV prefix via KVMemoryAdapter (in-place attention wrap, bit-exact disarmed, gated silent init); composed with frozen item-29 arm-1; +29 tf+fr in-flight note (30.5, FR term hurts)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -950,3 +950,35 @@ Nils's morning decision: clamp test vs pivot to the hybrid/A2 line
|
|||||||
matched accuracy; oracle meaningfully above 57.4 (early-stop
|
matched accuracy; oracle meaningfully above 57.4 (early-stop
|
||||||
rescues drift cases). Arm 2 (later): line-correctness /
|
rescues drift cases). Arm 2 (later): line-correctness /
|
||||||
deferral head gating re-expansion. Job: scripts/jobs/zzz_w_metacog.sh.
|
deferral head gating re-expansion. Job: scripts/jobs/zzz_w_metacog.sh.
|
||||||
|
|
||||||
|
31. **Synthetic memory tokens: per-layer KV prefix (pre-registered
|
||||||
|
2026-07-17 ~15:50, before running; Nils's design: "the one read
|
||||||
|
mechanism a frozen transformer natively possesses is attention over
|
||||||
|
the KV cache... adapter maps L30 state -> KV entries at band
|
||||||
|
layers"; injection variant chosen by Nils: per-layer KV prefix).**
|
||||||
|
The read-side attack, composed with item 29: warm-start the arm-1
|
||||||
|
adapter (its burst COMPUTES — trajectory-trained, ltf 0.085 — but
|
||||||
|
is provably unread: ablation 8-8 p=1.0) and FREEZE it; train only
|
||||||
|
a KVMemoryAdapter (6.3M params: shared code-512 trunk + per-band-
|
||||||
|
layer k/v heads with per-layer geometry — gemma-4 mixes 256-d
|
||||||
|
sliding and 512-d global heads) mapping the 10 burst iterates to
|
||||||
|
post-RoPE (k,v) columns appended to every band layer's attention
|
||||||
|
during the answer scan and at generation. Engineering, validated
|
||||||
|
in smokes: the registered attention implementation is wrapped IN
|
||||||
|
PLACE (config name untouched -> mask construction identical;
|
||||||
|
disarmed = bit-exact, diff 0.0); zero-init value heads + learnable
|
||||||
|
per-layer gate bias (init -10) make the memory silent at init
|
||||||
|
(step-0 loss 0.108 = the arm-1 endpoint exactly); memory stays
|
||||||
|
armed through backward (checkpoint recompute). Output CE only,
|
||||||
|
200 steps, lr 1e-3. Eval: 0:0 sanity + 2:0 matched (burst +
|
||||||
|
memory); the ablation is item 29's matched cell BY CONSTRUCTION
|
||||||
|
(same frozen adapter and burst, memory absent) = 39.1. Decision:
|
||||||
|
>44.1 (>=+5 over 39.1) = the consumption wall was a READ-PATH
|
||||||
|
problem and native attention over state-derived KV breaches it;
|
||||||
|
within +-5 = even natively readable computed states go unused ->
|
||||||
|
the wall is not about the read mechanism either, and the hybrid/
|
||||||
|
metacog lines carry the program. In-flight note on item 29 arm 2
|
||||||
|
(tf+fr): matched 30.5 — the free-running term HURT (vs 39.1
|
||||||
|
tf-only), reinforcing the training-signal attribution: clean TF
|
||||||
|
transition gradients are the active ingredient.
|
||||||
|
Job: scripts/jobs/zzz_x_kvmem.sh.
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ def carry_logits(looper, adapter, input_ids, attention_mask, prompt_lens,
|
|||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
def generate_carry_c(looper, adapter, tok, input_ids, attention_mask,
|
def generate_carry_c(looper, adapter, tok, input_ids, attention_mask,
|
||||||
k, p, max_new_tokens=10, feedforward=False,
|
k, p, max_new_tokens=10, feedforward=False,
|
||||||
inner_iters=0):
|
inner_iters=0, kvmem=None):
|
||||||
"""Greedy design-C generation (left-padded batch, uniform positions).
|
"""Greedy design-C generation (left-padded batch, uniform positions).
|
||||||
|
|
||||||
Appends p pause tokens, prefill-loops the prompt, carries through the
|
Appends p pause tokens, prefill-loops the prompt, carries through the
|
||||||
@@ -167,7 +167,12 @@ def generate_carry_c(looper, adapter, tok, input_ids, attention_mask,
|
|||||||
# p=0: iterate at the last prompt position, before any
|
# p=0: iterate at the last prompt position, before any
|
||||||
# visible token — no pause tokens involved
|
# visible token — no pause tokens involved
|
||||||
updates = (inner + updates) if p == 0 else (updates + inner)
|
updates = (inner + updates) if p == 0 else (updates + inner)
|
||||||
S, X = carry_steps(looper, adapter, e, calls, S, X, updates)
|
itst = [] if (kvmem is not None and inner_iters) else None
|
||||||
|
S, X = carry_steps(looper, adapter, e, calls, S, X, updates,
|
||||||
|
iter_states=itst)
|
||||||
|
if kvmem is not None and itst:
|
||||||
|
from kv_memory import arm_memory
|
||||||
|
arm_memory(kvmem(torch.stack(itst, 1)))
|
||||||
else:
|
else:
|
||||||
X = torch.cat([X_store, e[:, X_store.shape[1]:]], 1)
|
X = torch.cat([X_store, e[:, X_store.shape[1]:]], 1)
|
||||||
rows = torch.arange(B, device=dev)
|
rows = torch.arange(B, device=dev)
|
||||||
|
|||||||
@@ -40,11 +40,25 @@ def main():
|
|||||||
help="load a lora_*_e*.pt loop-only band-LoRA checkpoint")
|
help="load a lora_*_e*.pt loop-only band-LoRA checkpoint")
|
||||||
ap.add_argument("--inner-iters", type=int, default=0, metavar="M",
|
ap.add_argument("--inner-iters", type=int, default=0, metavar="M",
|
||||||
help="M in-place band iterations at the last pause")
|
help="M in-place band iterations at the last pause")
|
||||||
|
ap.add_argument("--kvmem", default=None, metavar="KVMEM_PT",
|
||||||
|
help="KVMemoryAdapter checkpoint: burst states become "
|
||||||
|
"band-layer KV prefix entries at generation")
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
|
|
||||||
model, tok = load_model(dtype=torch.bfloat16)
|
model, tok = load_model(dtype=torch.bfloat16)
|
||||||
tok.padding_side = "left"
|
tok.padding_side = "left"
|
||||||
looper = BandLooper(model)
|
looper = BandLooper(model)
|
||||||
|
kvmem = None
|
||||||
|
if args.kvmem:
|
||||||
|
from kv_memory import install, KVMemoryAdapter
|
||||||
|
from loop_common import BAND
|
||||||
|
install(model)
|
||||||
|
sd = torch.load(args.kvmem, map_location="cuda")
|
||||||
|
code = sd["trunk.1.weight"].shape[0]
|
||||||
|
kvmem = KVMemoryAdapter(model, band=BAND, code=code).cuda()
|
||||||
|
kvmem.load_state_dict(sd)
|
||||||
|
kvmem.eval()
|
||||||
|
print(f"kv-memory loaded: {args.kvmem} (code={code})", flush=True)
|
||||||
if args.bandlora:
|
if args.bandlora:
|
||||||
from lora_band import inject_band_lora
|
from lora_band import inject_band_lora
|
||||||
ck = torch.load(args.bandlora, map_location="cuda")
|
ck = torch.load(args.bandlora, map_location="cuda")
|
||||||
@@ -86,7 +100,11 @@ def main():
|
|||||||
enc["attention_mask"], k, p,
|
enc["attention_mask"], k, p,
|
||||||
max_new_tokens=args.max_new,
|
max_new_tokens=args.max_new,
|
||||||
feedforward=args.feedforward,
|
feedforward=args.feedforward,
|
||||||
inner_iters=args.inner_iters)
|
inner_iters=args.inner_iters,
|
||||||
|
kvmem=kvmem)
|
||||||
|
if kvmem is not None:
|
||||||
|
from kv_memory import arm_memory
|
||||||
|
arm_memory(None)
|
||||||
for j, it in enumerate(chunk):
|
for j, it in enumerate(chunk):
|
||||||
txt = tok.decode(gen[j, enc["input_ids"].shape[1]:],
|
txt = tok.decode(gen[j, enc["input_ids"].shape[1]:],
|
||||||
skip_special_tokens=True)
|
skip_special_tokens=True)
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# gpuq-in: results-loop/star_data.json results-loop/gsm_cot_data.json results-loop/adapter_carrycot_b1_ii10_tjs50_00_p0_e200.pt
|
||||||
|
# gpuq-out: results-loop/eval_gsm_carrycot_b1_kvm*.json results-loop/train_carrycot_b1_ii10_kvm512_fm_p0_log.json results-loop/kvmem_carrycot_b1_ii10_kvm512_fm_p0_e200.pt
|
||||||
|
git pull origin main -q 2>/dev/null
|
||||||
|
P=/home/nils/jspace/.venv/bin/python
|
||||||
|
export JLENS_MODEL=google/gemma-4-E2B-it LOOP_OUT=/home/nils/jspace/results-loop
|
||||||
|
cd /home/nils/jspace/scripts
|
||||||
|
A=$LOOP_OUT/adapter_carrycot_b1_ii10_tjs50_00_p0_e200.pt
|
||||||
|
$P train_carry_cot.py --drop-steps 1 --pause-per-step 0 --base-pauses 0 \
|
||||||
|
--inner-iters 10 --kvmem 512 --freeze-merge \
|
||||||
|
--warm-start $A --steps 200 --lr 1e-3
|
||||||
|
$P eval_carry_cot.py --adapter $A \
|
||||||
|
--kvmem $LOOP_OUT/kvmem_carrycot_b1_ii10_kvm512_fm_p0_e200.pt \
|
||||||
|
--tag gsm_carrycot_b1_kvm512 --grid 0:0,2:0 --n 256 --inner-iters 10
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
"""Item 31: synthetic memory tokens — per-layer KV prefix (Nils's design).
|
||||||
|
|
||||||
|
"The one read mechanism a frozen transformer natively possesses is
|
||||||
|
attention over the KV cache." A KVMemoryAdapter maps carried L30 states
|
||||||
|
to (k, v) entries appended to every band layer's attention — frozen
|
||||||
|
heads consume the state through their existing machinery. Keys live in
|
||||||
|
post-RoPE space (prefix-tuning convention: learned keys place themselves
|
||||||
|
where frozen queries already point).
|
||||||
|
|
||||||
|
Activation is global-flag-scoped like lora_band.LoopLoRA: a custom
|
||||||
|
attention interface "kvmem" wraps the stock eager path; when _MEM is
|
||||||
|
armed and the module is a band layer, memory kv columns are appended
|
||||||
|
(mask columns visible to every query).
|
||||||
|
"""
|
||||||
|
import torch
|
||||||
|
import torch.nn as nn
|
||||||
|
|
||||||
|
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
|
||||||
|
from transformers.models.gemma4.modeling_gemma4 import (
|
||||||
|
eager_attention_forward)
|
||||||
|
|
||||||
|
_MEM = {"on": False, "kv": None, "band": (14, 30), "base": None}
|
||||||
|
|
||||||
|
|
||||||
|
def arm_memory(kv):
|
||||||
|
"""kv: dict layer_idx -> (k, v), each (B, kv_heads, M, head_dim)."""
|
||||||
|
_MEM["kv"] = kv
|
||||||
|
_MEM["on"] = kv is not None
|
||||||
|
|
||||||
|
|
||||||
|
def kvmem_attention(module, query, key, value, attention_mask, **kwargs):
|
||||||
|
if (_MEM["on"] and _MEM["kv"] is not None
|
||||||
|
and getattr(module, "layer_idx", -1) in _MEM["kv"]):
|
||||||
|
mk, mv, gate = _MEM["kv"][module.layer_idx]
|
||||||
|
m = mk.shape[2]
|
||||||
|
key = torch.cat([key, mk.to(dtype=key.dtype, device=key.device)], 2)
|
||||||
|
value = torch.cat([value, mv.to(dtype=value.dtype,
|
||||||
|
device=value.device)], 2)
|
||||||
|
if attention_mask is not None:
|
||||||
|
pad = torch.zeros(*attention_mask.shape[:-1], m,
|
||||||
|
dtype=attention_mask.dtype,
|
||||||
|
device=attention_mask.device) + gate.to(
|
||||||
|
attention_mask.dtype)
|
||||||
|
attention_mask = torch.cat([attention_mask, pad], -1)
|
||||||
|
base = _MEM["base"] or eager_attention_forward
|
||||||
|
return base(module, query, key, value, attention_mask, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def install(model):
|
||||||
|
"""Wrap the registered implementation IN PLACE — the config name is
|
||||||
|
untouched, so mask construction and every other branch stays
|
||||||
|
bit-identical; only the (q,k,v,mask) seam gains the memory append."""
|
||||||
|
if _MEM.get("installed"):
|
||||||
|
return
|
||||||
|
impl = model.config._attn_implementation
|
||||||
|
_MEM["base"] = ALL_ATTENTION_FUNCTIONS.get_interface(
|
||||||
|
impl, eager_attention_forward)
|
||||||
|
try:
|
||||||
|
ALL_ATTENTION_FUNCTIONS[impl] = kvmem_attention
|
||||||
|
except TypeError:
|
||||||
|
ALL_ATTENTION_FUNCTIONS.register(impl, kvmem_attention)
|
||||||
|
_MEM["installed"] = True
|
||||||
|
|
||||||
|
|
||||||
|
class KVMemoryAdapter(nn.Module):
|
||||||
|
"""Carried states (B, M, d) -> per-band-layer post-RoPE (k, v).
|
||||||
|
Per-layer geometry (head_dim, kv heads) read off the live modules —
|
||||||
|
gemma-4 mixes sliding (256) and global (512) head dims in the band."""
|
||||||
|
|
||||||
|
def __init__(self, model, band=(14, 30), code=512):
|
||||||
|
super().__init__()
|
||||||
|
self.band = band
|
||||||
|
tm = model.model.language_model
|
||||||
|
d = model.config.get_text_config().hidden_size
|
||||||
|
self.trunk = nn.Sequential(nn.LayerNorm(d), nn.Linear(d, code),
|
||||||
|
nn.GELU())
|
||||||
|
self.geom = {}
|
||||||
|
self.k_heads = nn.ModuleDict()
|
||||||
|
self.v_heads = nn.ModuleDict()
|
||||||
|
tc = model.config.get_text_config()
|
||||||
|
for l in range(band[0], band[1] + 1):
|
||||||
|
att = tm.layers[l].self_attn
|
||||||
|
hd = att.head_dim
|
||||||
|
kvh = (tc.num_global_key_value_heads
|
||||||
|
if getattr(att, "use_alternative_attention", False)
|
||||||
|
else tc.num_key_value_heads)
|
||||||
|
self.geom[l] = (kvh, hd)
|
||||||
|
self.k_heads[str(l)] = nn.Linear(code, kvh * hd)
|
||||||
|
self.v_heads[str(l)] = nn.Linear(code, kvh * hd)
|
||||||
|
nn.init.zeros_(self.v_heads[str(l)].weight)
|
||||||
|
nn.init.zeros_(self.v_heads[str(l)].bias)
|
||||||
|
# learnable per-layer attention gate on the memory columns:
|
||||||
|
# init -10 -> memory is invisible until training opens it
|
||||||
|
self.gate = nn.ParameterDict(
|
||||||
|
{str(l): nn.Parameter(torch.tensor(-10.0))
|
||||||
|
for l in range(band[0], band[1] + 1)})
|
||||||
|
|
||||||
|
def forward(self, states):
|
||||||
|
B, M, _ = states.shape
|
||||||
|
c = self.trunk(states.float())
|
||||||
|
kv = {}
|
||||||
|
for l in range(self.band[0], self.band[1] + 1):
|
||||||
|
kvh, hd = self.geom[l]
|
||||||
|
k = self.k_heads[str(l)](c).view(B, M, kvh, hd).transpose(1, 2)
|
||||||
|
v = self.v_heads[str(l)](c).view(B, M, kvh, hd).transpose(1, 2)
|
||||||
|
kv[l] = (k, v, self.gate[str(l)])
|
||||||
|
return kv
|
||||||
@@ -89,6 +89,13 @@ ap.add_argument("--traj-fr", type=float, default=0.0, metavar="LAMBDA",
|
|||||||
ap.add_argument("--traj-span", choices=("step", "full"), default="step",
|
ap.add_argument("--traj-span", choices=("step", "full"), default="step",
|
||||||
help="waypoints sampled evenly across the deleted step "
|
help="waypoints sampled evenly across the deleted step "
|
||||||
"(job 1, d=1) or the full CoT (job 2, answer-only)")
|
"(job 1, d=1) or the full CoT (job 2, answer-only)")
|
||||||
|
ap.add_argument("--kvmem", type=int, default=0, metavar="CODE",
|
||||||
|
help="item 31: KVMemoryAdapter (code width) — burst states "
|
||||||
|
"become per-band-layer KV prefix entries readable by "
|
||||||
|
"frozen attention during the answer scan")
|
||||||
|
ap.add_argument("--freeze-merge", action="store_true",
|
||||||
|
help="freeze the (warm-started) merge adapter; train only "
|
||||||
|
"the kvmem adapter")
|
||||||
ap.add_argument("--teachstate", type=float, default=0.0, metavar="LAMBDA",
|
ap.add_argument("--teachstate", type=float, default=0.0, metavar="LAMBDA",
|
||||||
help="item 28 (Nils's variant): teacher-state distillation "
|
help="item 28 (Nils's variant): teacher-state distillation "
|
||||||
"— frozen warm-start adapter runs the FULL cot (step "
|
"— frozen warm-start adapter runs the FULL cot (step "
|
||||||
@@ -109,6 +116,8 @@ TAG = ("carrycot_ff" if ARGS.feedforward else "carrycot") + (
|
|||||||
f"_tj{ARGS.traj_span[0]}{str(ARGS.traj_tf).replace('.', '')}"
|
f"_tj{ARGS.traj_span[0]}{str(ARGS.traj_tf).replace('.', '')}"
|
||||||
f"_{str(ARGS.traj_fr).replace('.', '')}"
|
f"_{str(ARGS.traj_fr).replace('.', '')}"
|
||||||
if (ARGS.traj_tf or ARGS.traj_fr) else "") + (
|
if (ARGS.traj_tf or ARGS.traj_fr) else "") + (
|
||||||
|
f"_kvm{ARGS.kvmem}" if ARGS.kvmem else "") + (
|
||||||
|
"_fm" if ARGS.freeze_merge else "") + (
|
||||||
f"_p{ARGS.base_pauses}" if ARGS.base_pauses >= 0 else "") + (
|
f"_p{ARGS.base_pauses}" if ARGS.base_pauses >= 0 else "") + (
|
||||||
f"_ln{ARGS.lensnoise.replace(',', '_')}" if ARGS.lensnoise else "") + (
|
f"_ln{ARGS.lensnoise.replace(',', '_')}" if ARGS.lensnoise else "") + (
|
||||||
f"_s{ARGS.seed}" if ARGS.seed else "") + ARGS.tag_suffix
|
f"_s{ARGS.seed}" if ARGS.seed else "") + ARGS.tag_suffix
|
||||||
@@ -188,7 +197,8 @@ def gen_staging_targets(tok, cot):
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def traj_burst_forward(looper, adapter, ids, msk, plens, m, T, tf_on, k):
|
def traj_burst_forward(looper, adapter, ids, msk, plens, m, T, tf_on, k,
|
||||||
|
mem_adapter=None):
|
||||||
"""Item 29 forward: optional teacher-forced transition predictions,
|
"""Item 29 forward: optional teacher-forced transition predictions,
|
||||||
then the free-running burst (whose final state seeds the answer scan,
|
then the free-running burst (whose final state seeds the answer scan,
|
||||||
matching inference), then the visible-token carry. Returns
|
matching inference), then the visible-token carry. Returns
|
||||||
@@ -224,11 +234,17 @@ def traj_burst_forward(looper, adapter, ids, msk, plens, m, T, tf_on, k):
|
|||||||
seed = s0 if i == 0 else fr_states[-1]
|
seed = s0 if i == 0 else fr_states[-1]
|
||||||
S, X = upd(S, X, seed)
|
S, X = upd(S, X, seed)
|
||||||
fr_states.append(S[rows, anchor])
|
fr_states.append(S[rows, anchor])
|
||||||
|
if mem_adapter is not None:
|
||||||
|
from kv_memory import arm_memory
|
||||||
|
arm_memory(mem_adapter(torch.stack(fr_states, 1)))
|
||||||
total = msk.sum(-1)
|
total = msk.sum(-1)
|
||||||
updates = build_step_updates(plens.to(dev), total.to(dev), dev)
|
updates = build_step_updates(plens.to(dev), total.to(dev), dev)
|
||||||
S, X = carry_steps(looper, adapter, e, calls, S, X, updates,
|
S, X = carry_steps(looper, adapter, e, calls, S, X, updates,
|
||||||
use_checkpoint=True)
|
use_checkpoint=True)
|
||||||
return looper.suffix_logits(S, calls), tf_preds, fr_states
|
out = looper.suffix_logits(S, calls)
|
||||||
|
# NOTE: memory stays armed through backward (checkpoint recompute
|
||||||
|
# must see the same graph); the caller disarms after opt.step().
|
||||||
|
return out, tf_preds, fr_states
|
||||||
|
|
||||||
|
|
||||||
def lr_at(step):
|
def lr_at(step):
|
||||||
@@ -339,6 +355,20 @@ def main():
|
|||||||
f"{sum(p.numel() for p in lora_params)/1e6:.1f}M params, "
|
f"{sum(p.numel() for p in lora_params)/1e6:.1f}M params, "
|
||||||
f"layers {lora_band_layers[0]}-{lora_band_layers[-1]}, "
|
f"layers {lora_band_layers[0]}-{lora_band_layers[-1]}, "
|
||||||
f"lr={ARGS.lora_lr}", flush=True)
|
f"lr={ARGS.lora_lr}", flush=True)
|
||||||
|
mem_adapter = None
|
||||||
|
if ARGS.kvmem:
|
||||||
|
from kv_memory import install, KVMemoryAdapter
|
||||||
|
from loop_common import BAND
|
||||||
|
install(model)
|
||||||
|
mem_adapter = KVMemoryAdapter(model, band=BAND,
|
||||||
|
code=ARGS.kvmem).cuda()
|
||||||
|
print(f"kv-memory adapter: code={ARGS.kvmem}, "
|
||||||
|
f"{sum(p.numel() for p in mem_adapter.parameters())/1e6:.1f}M "
|
||||||
|
f"params, band {BAND}", flush=True)
|
||||||
|
if ARGS.freeze_merge:
|
||||||
|
for p_ in adapter.parameters():
|
||||||
|
p_.requires_grad_(False)
|
||||||
|
print("merge adapter FROZEN", flush=True)
|
||||||
lens_teach = None
|
lens_teach = None
|
||||||
if ARGS.lensteach or ARGS.lensteach_gen:
|
if ARGS.lensteach or ARGS.lensteach_gen:
|
||||||
from loop_common import BAND
|
from loop_common import BAND
|
||||||
@@ -431,7 +461,12 @@ def main():
|
|||||||
print(f"teacher states: {len(todo)} captured ({time.time()-t0_:.0f}s;"
|
print(f"teacher states: {len(todo)} captured ({time.time()-t0_:.0f}s;"
|
||||||
f" frozen warm-start adapter, full cot, band-exit at the "
|
f" frozen warm-start adapter, full cot, band-exit at the "
|
||||||
f"deleted step's last token)", flush=True)
|
f"deleted step's last token)", flush=True)
|
||||||
groups = [{"params": list(adapter.parameters()), "lr": LR, "base": LR}]
|
groups = ([] if ARGS.freeze_merge else
|
||||||
|
[{"params": list(adapter.parameters()), "lr": LR,
|
||||||
|
"base": LR}])
|
||||||
|
if mem_adapter is not None:
|
||||||
|
groups.append({"params": list(mem_adapter.parameters()), "lr": LR,
|
||||||
|
"base": LR})
|
||||||
if lora_params:
|
if lora_params:
|
||||||
groups.append({"params": lora_params, "lr": ARGS.lora_lr,
|
groups.append({"params": lora_params, "lr": ARGS.lora_lr,
|
||||||
"base": ARGS.lora_lr})
|
"base": ARGS.lora_lr})
|
||||||
@@ -463,12 +498,13 @@ def main():
|
|||||||
for g in opt.param_groups:
|
for g in opt.param_groups:
|
||||||
g["lr"] = g["base"] * lr_at(step) / LR
|
g["lr"] = g["base"] * lr_at(step) / LR
|
||||||
ckw, itstates, tfp, frs = {}, None, None, None
|
ckw, itstates, tfp, frs = {}, None, None, None
|
||||||
if ARGS.traj_tf or ARGS.traj_fr:
|
if ARGS.traj_tf or ARGS.traj_fr or ARGS.kvmem:
|
||||||
T = torch.stack([torch.as_tensor(b_["traj_states"])
|
T = (torch.stack([torch.as_tensor(b_["traj_states"])
|
||||||
for b_ in batch]).cuda()
|
for b_ in batch]).cuda()
|
||||||
|
if (ARGS.traj_tf or ARGS.traj_fr) else None)
|
||||||
logits, tfp, frs = traj_burst_forward(
|
logits, tfp, frs = traj_burst_forward(
|
||||||
looper, adapter, ids, msk, plens, ARGS.inner_iters, T,
|
looper, adapter, ids, msk, plens, ARGS.inner_iters, T,
|
||||||
bool(ARGS.traj_tf), K_PREFILL)
|
bool(ARGS.traj_tf), K_PREFILL, mem_adapter=mem_adapter)
|
||||||
else:
|
else:
|
||||||
if ARGS.inner_iters:
|
if ARGS.inner_iters:
|
||||||
extras = torch.tensor([b_.get("extra_pauses", 0)
|
extras = torch.tensor([b_.get("extra_pauses", 0)
|
||||||
@@ -569,8 +605,14 @@ def main():
|
|||||||
opt.zero_grad(set_to_none=True)
|
opt.zero_grad(set_to_none=True)
|
||||||
loss.backward()
|
loss.backward()
|
||||||
torch.nn.utils.clip_grad_norm_(
|
torch.nn.utils.clip_grad_norm_(
|
||||||
list(adapter.parameters()) + lora_params, 1.0)
|
[p_ for p_ in adapter.parameters() if p_.requires_grad]
|
||||||
|
+ lora_params
|
||||||
|
+ (list(mem_adapter.parameters()) if mem_adapter is not None
|
||||||
|
else []), 1.0)
|
||||||
opt.step()
|
opt.step()
|
||||||
|
if ARGS.kvmem:
|
||||||
|
from kv_memory import arm_memory
|
||||||
|
arm_memory(None)
|
||||||
log.append({"step": step, "loss": loss.item(), "lce": lce_val,
|
log.append({"step": step, "loss": loss.item(), "lce": lce_val,
|
||||||
"lgen": lgen_val, "lts": lts_val, "ltf": ltf_val,
|
"lgen": lgen_val, "lts": lts_val, "ltf": ltf_val,
|
||||||
"lfr": lfr_val})
|
"lfr": lfr_val})
|
||||||
@@ -593,6 +635,9 @@ def main():
|
|||||||
adapter.noise_on = True
|
adapter.noise_on = True
|
||||||
sd = (adapter.base if ARGS.lensnoise else adapter).state_dict()
|
sd = (adapter.base if ARGS.lensnoise else adapter).state_dict()
|
||||||
torch.save(sd, OUT / f"adapter_{TAG}_e{step+1}.pt")
|
torch.save(sd, OUT / f"adapter_{TAG}_e{step+1}.pt")
|
||||||
|
if mem_adapter is not None:
|
||||||
|
torch.save(mem_adapter.state_dict(),
|
||||||
|
OUT / f"kvmem_{TAG}_e{step+1}.pt")
|
||||||
if lora_params:
|
if lora_params:
|
||||||
torch.save({"rank": ARGS.bandlora, "band": lora_band_layers,
|
torch.save({"rank": ARGS.bandlora, "band": lora_band_layers,
|
||||||
"tensors": [p.detach().cpu()
|
"tensors": [p.detach().cpu()
|
||||||
|
|||||||
Reference in New Issue
Block a user