kdirgul commited on
Commit
4623d23
·
verified ·
1 Parent(s): 5d47d62

faz9_recur: --sweep (k zorluk taramasi, GAP-vs-k trendi = asil GO/NO-GO kaniti)

Browse files
Files changed (1) hide show
  1. code/kod/faz9_recur.py +44 -14
code/kod/faz9_recur.py CHANGED
@@ -171,17 +171,15 @@ class FixedDepthLM(nn.Module):
171
  return self.lm_head(rms_norm(h, self.norm_f))
172
 
173
 
174
- def compare(device="cpu", n_keys=12, k=4, steps=2000, batch=64, d_model=128, lr=1e-3, fast=False):
 
175
  P, C = 1, 1
176
  cfg = tiny_cfg(d_model=d_model, vocab_size=n_keys + 1)
177
  rec = RecurrentDepthLM(cfg, n_prelude=P, n_coda=C, core_attn=True, prenorm_core=False, block_attn=fast).to(device)
178
  fix = FixedDepthLM(cfg, n_layers=P + 1 + C, all_attn=fast).to(device)
179
- print(f"[compare] görev: {k}-hop / {n_keys} anahtar | device={device} | steps={steps} | fast={fast}")
180
- print(f" param: recurrent {_params(rec)/1e6:.3f}M | fixed {_params(fix)/1e6:.3f}M (eşit olmalı)")
181
 
182
  def train(model, recurrent):
183
- opt = torch.optim.AdamW(model.parameters(), lr=lr)
184
- model.train()
185
  for s in range(steps):
186
  ids, tgt = gen_khop(batch, n_keys, k, device)
187
  R = int(torch.randint(2, 13, (1,))) if recurrent else 1
@@ -189,8 +187,8 @@ def compare(device="cpu", n_keys=12, k=4, steps=2000, batch=64, d_model=128, lr=
189
  loss = F.cross_entropy(last, tgt)
190
  opt.zero_grad(); loss.backward()
191
  torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0); opt.step()
192
- if s % max(1, steps // 5) == 0:
193
- print(f" {'REC' if recurrent else 'FIX'} step {s:>4} loss {loss.item():.3f}")
194
 
195
  @torch.no_grad()
196
  def acc(model, recurrent, R=8, n=1000):
@@ -198,17 +196,44 @@ def compare(device="cpu", n_keys=12, k=4, steps=2000, batch=64, d_model=128, lr=
198
  last = (model(ids, R=R) if recurrent else model(ids))[:, -1]
199
  return (last.argmax(-1) == tgt).float().mean().item()
200
 
201
- print(" --- FIXED eğitiliyor ---"); train(fix, False)
202
- print(" --- RECURRENT eğitiliyor ---"); train(rec, True)
 
 
 
 
 
 
203
  rnd = 1.0 / n_keys
204
- print(f"\n[SONUÇ] (random={rnd:.3f})")
205
- print(f" FIXED (depth {P+1+C}) acc = {acc(fix, False):.3f}")
206
  print(f" RECURRENT test-zamanı R ölçekleme:")
207
- for R in (1, 2, 4, 8, 16):
208
- print(f" R={R:>2} → acc {acc(rec, True, R=R):.3f}")
 
209
  print(" GO sinyali: recurrent fixed'i geçer VE R↑ ile acc↑ (özellikle R≥k).")
210
 
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  def main():
213
  ap = argparse.ArgumentParser()
214
  ap.add_argument("--smoke", action="store_true", help="CPU mekanik smoke (Faz A)")
@@ -219,13 +244,18 @@ def main():
219
  ap.add_argument("--steps", type=int, default=2000)
220
  ap.add_argument("--d_model", type=int, default=128)
221
  ap.add_argument("--fast", action="store_true", help="tüm bloklar attention (Mamba token-loop yok → ~30× hızlı; k-hop için uygun)")
 
 
222
  args = ap.parse_args()
223
  if args.smoke:
224
  smoke()
 
 
 
225
  elif args.compare:
226
  compare(device=args.device, n_keys=args.n_keys, k=args.k, steps=args.steps, d_model=args.d_model, fast=args.fast)
227
  else:
228
- print("kullanım: python faz9_recur.py --smoke | --compare [--device cuda --k 4 --n_keys 12 --steps 2000]")
229
 
230
 
231
  if __name__ == "__main__":
 
171
  return self.lm_head(rms_norm(h, self.norm_f))
172
 
173
 
174
+ def _train_eval(device, n_keys, k, steps, batch, d_model, lr, fast, verbose=True):
175
+ """Tek k için param-eşit fixed+recurrent eğit → (fix_acc, {R:rec_acc}, n_param)."""
176
  P, C = 1, 1
177
  cfg = tiny_cfg(d_model=d_model, vocab_size=n_keys + 1)
178
  rec = RecurrentDepthLM(cfg, n_prelude=P, n_coda=C, core_attn=True, prenorm_core=False, block_attn=fast).to(device)
179
  fix = FixedDepthLM(cfg, n_layers=P + 1 + C, all_attn=fast).to(device)
 
 
180
 
181
  def train(model, recurrent):
182
+ opt = torch.optim.AdamW(model.parameters(), lr=lr); model.train()
 
183
  for s in range(steps):
184
  ids, tgt = gen_khop(batch, n_keys, k, device)
185
  R = int(torch.randint(2, 13, (1,))) if recurrent else 1
 
187
  loss = F.cross_entropy(last, tgt)
188
  opt.zero_grad(); loss.backward()
189
  torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0); opt.step()
190
+ if verbose and s % max(1, steps // 4) == 0:
191
+ print(f" {'REC' if recurrent else 'FIX'} k={k} step {s:>4} loss {loss.item():.3f}")
192
 
193
  @torch.no_grad()
194
  def acc(model, recurrent, R=8, n=1000):
 
196
  last = (model(ids, R=R) if recurrent else model(ids))[:, -1]
197
  return (last.argmax(-1) == tgt).float().mean().item()
198
 
199
+ train(fix, False); train(rec, True)
200
+ rec_by_R = {R: acc(rec, True, R=R) for R in (1, 2, 4, 8, 16)}
201
+ return acc(fix, False), rec_by_R, _params(rec)
202
+
203
+
204
+ def compare(device="cpu", n_keys=12, k=4, steps=2000, batch=64, d_model=128, lr=1e-3, fast=False):
205
+ print(f"[compare] görev: {k}-hop / {n_keys} anahtar | device={device} | steps={steps} | fast={fast}")
206
+ fa, rec, npar = _train_eval(device, n_keys, k, steps, batch, d_model, lr, fast)
207
  rnd = 1.0 / n_keys
208
+ print(f"\n[SONUÇ] param ~{npar/1e6:.3f}M (eşit) | random={rnd:.3f}")
209
+ print(f" FIXED (depth 3) acc = {fa:.3f}")
210
  print(f" RECURRENT test-zamanı R ölçekleme:")
211
+ for R, a in rec.items():
212
+ print(f" R={R:>2} → acc {a:.3f}")
213
+ print(f" GAP (rec_best − fixed) = {max(rec.values()) - fa:+.3f}")
214
  print(" GO sinyali: recurrent fixed'i geçer VE R↑ ile acc↑ (özellikle R≥k).")
215
 
216
 
217
+ def sweep(device="cpu", n_keys=12, ks=(2, 4, 6), steps=2000, batch=64, d_model=128, lr=1e-3, fast=True):
218
+ """ZORLUK TARAMASI: GAP (rec−fixed) k ile büyüyor mu = recursion derinlikle değer kazanıyor mu."""
219
+ rnd = 1.0 / n_keys
220
+ print(f"[sweep] k={list(ks)} / {n_keys} anahtar | device={device} | steps={steps} | fast={fast} | random={rnd:.3f}\n")
221
+ rows = []
222
+ for k in ks:
223
+ fa, rec, npar = _train_eval(device, n_keys, k, steps, batch, d_model, lr, fast, verbose=False)
224
+ bR = max(rec, key=rec.get); gap = rec[bR] - fa
225
+ rows.append((k, fa, rec, bR, gap))
226
+ print(f" k={k}: FIX {fa:.3f} | REC R1={rec[1]:.2f} R4={rec[4]:.2f} R8={rec[8]:.2f} R16={rec[16]:.2f} "
227
+ f"| best@R{bR}={rec[bR]:.3f} | GAP {gap:+.3f}")
228
+ print(f"\n[ÖZET] GAP (rec_best − fixed) — k arttıkça büyümeli (random={rnd:.3f}):")
229
+ for k, fa, rec, bR, gap in rows:
230
+ print(f" k={k}: GAP {gap:+.3f} {'#' * max(0, int(gap * 60))}")
231
+ gaps = [r[4] for r in rows]
232
+ grow = all(gaps[i] <= gaps[i + 1] + 1e-9 for i in range(len(gaps) - 1)) and gaps[-1] > 0.05
233
+ print(f"\n → GAP k ile {'✅ ARTIYOR = GO (recursion derinlikle değer kazanıyor)' if grow else '⚠️ ARTMIYOR/karışık = zayıf sinyal'}")
234
+ print(" → Ayrıca zor k'da REC acc ~R≥k civarında sıçramalı (daha çok düşünme = daha çok hop).")
235
+
236
+
237
  def main():
238
  ap = argparse.ArgumentParser()
239
  ap.add_argument("--smoke", action="store_true", help="CPU mekanik smoke (Faz A)")
 
244
  ap.add_argument("--steps", type=int, default=2000)
245
  ap.add_argument("--d_model", type=int, default=128)
246
  ap.add_argument("--fast", action="store_true", help="tüm bloklar attention (Mamba token-loop yok → ~30× hızlı; k-hop için uygun)")
247
+ ap.add_argument("--sweep", action="store_true", help="Faz B zorluk taraması: k=2/4/6 GAP trendi (asıl GO/NO-GO)")
248
+ ap.add_argument("--ks", default="2,4,6", help="sweep k değerleri (virgülle, örn. 2,4,6)")
249
  args = ap.parse_args()
250
  if args.smoke:
251
  smoke()
252
+ elif args.sweep:
253
+ ks = tuple(int(x) for x in args.ks.split(","))
254
+ sweep(device=args.device, n_keys=args.n_keys, ks=ks, steps=args.steps, d_model=args.d_model, fast=args.fast)
255
  elif args.compare:
256
  compare(device=args.device, n_keys=args.n_keys, k=args.k, steps=args.steps, d_model=args.d_model, fast=args.fast)
257
  else:
258
+ print("kullanım: python faz9_recur.py --smoke | --compare | --sweep [--device cuda --n_keys 12 --steps 3000 --fast]")
259
 
260
 
261
  if __name__ == "__main__":