AbstractPhil commited on
Commit
b7f274b
·
verified ·
1 Parent(s): 7c373f7

splat_attention v2: CausalSplatHUB (the AR-validated causal form), dtype-aware clamps (fp16 landmine defused), header carries the full causal record — binding surface, corrected supply law, optimizer + precision guidance, the open problem stated plainly

Browse files
Files changed (1) hide show
  1. splat_attention.py +92 -2
splat_attention.py CHANGED
@@ -74,6 +74,38 @@
74
  # Frozen-everything remains fine for INFERENCE-style play and the
75
  # static properties above.
76
  #
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  # Status: research prototype. Trained-at-scale results pending; treat
78
  # every number above as what it is — a measurement on the stated probe.
79
  # =========================================================================
@@ -179,7 +211,11 @@ class SplatAttention(nn.Module):
179
  centers = frac * (L - 1)
180
  g = torch.exp(-0.5 * ((pos.unsqueeze(0) - centers.unsqueeze(1))
181
  / sig) ** 2)
182
- g = g / g.sum(dim=0, keepdim=True).clamp(min=1e-9)
 
 
 
 
183
  n_glob = int(round(self.M * self.global_frac))
184
  if n_glob > 0:
185
  g[:n_glob] = 1.0
@@ -229,10 +265,64 @@ class SplatAttention(nn.Module):
229
  c0, Mc)
230
  out = out.add_(part)
231
  den = den.add_(dpart)
232
- out = out / den.unsqueeze(-1).clamp_min(1e-9)
 
 
 
 
233
  return self.drop(self.w_o(out))
234
 
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  def _demo():
237
  torch.manual_seed(0)
238
  dev = "cuda" if torch.cuda.is_available() else "cpu"
 
74
  # Frozen-everything remains fine for INFERENCE-style play and the
75
  # static properties above.
76
  #
77
+ # CAUSAL / AR RECORD (2026-08-09/10, rank-controlled recall battery,
78
+ # clean protocol — see trainers/ for full replication):
79
+ # CausalSplatHUB (included below) is the causal prefix-sum form of the
80
+ # aleph read, measured against matched softmax attention on in-context
81
+ # key-value binding with dial-able demand (key rank R):
82
+ # low demand (R=4): near parity (.92 vs .96, shared data ceiling)
83
+ # moderate demand (R=16): .90 vs .99 — army extrapolates toward parity
84
+ # high demand (R=64): .84 vs .99 — army-SATURATED below parity.
85
+ # THE OPEN PROBLEM, stated plainly: at high binding demand the linear
86
+ # aleph read saturates below softmax parity and count does not close it.
87
+ # Something else is needed there — address dimensionality, per-depth
88
+ # allocation, and optimizer geometry are the live suspects.
89
+ # SUPPLY LAW (corrected): the army-size knee tracks the task's
90
+ # addressing DEMAND, but the constant is demand-dependent (4R at low
91
+ # demand, >=16R at moderate, saturating at high). Provision generously
92
+ # and measure CONSUMED address erank PER LAYER — late layers
93
+ # under-consume badly (uniform per-layer K wastes most of its supply).
94
+ # OPTIMIZER (measured, decisive): momentum-geometric optimizers
95
+ # (Muon-style orthogonalized momentum, plain SGD-momentum) beat Adam by
96
+ # ~.09 on this mechanism, and the mechanism is ~20x more
97
+ # optimizer-sensitive than softmax attention. Treat the optimizer as
98
+ # part of the architecture.
99
+ # PRECISION: train in fp32 or bf16 (bf16 measured >= fp32); do NOT
100
+ # train through fp8 (fails); fp8 e4m3 INFERENCE of trained weights is
101
+ # viable (~5% cost). All normalizer clamps in this file are dtype-aware
102
+ # because 1e-9-class constants flush to ZERO in fp16 (measured NaN at
103
+ # ~5% of sharp reads before the fix).
104
+ # REPLICATOR'S WARNING: evaluation-protocol faults can fake
105
+ # architecture plateaus (a window-truncation ceiling masqueraded as a
106
+ # softmax plateau at .936 for two days of this record). The trainers
107
+ # directory ships the corrected harness; use its clean gauges.
108
+ #
109
  # Status: research prototype. Trained-at-scale results pending; treat
110
  # every number above as what it is — a measurement on the stated probe.
111
  # =========================================================================
 
211
  centers = frac * (L - 1)
212
  g = torch.exp(-0.5 * ((pos.unsqueeze(0) - centers.unsqueeze(1))
213
  / sig) ** 2)
214
+ if g.dtype in (torch.float32, torch.float64):
215
+ _cl = 1e-9
216
+ else: # half dtypes: 1e-9 flushes to 0 (landmine)
217
+ _cl = float(torch.finfo(g.dtype).tiny) * 8
218
+ g = g / g.sum(dim=0, keepdim=True).clamp(min=_cl)
219
  n_glob = int(round(self.M * self.global_frac))
220
  if n_glob > 0:
221
  g[:n_glob] = 1.0
 
265
  c0, Mc)
266
  out = out.add_(part)
267
  den = den.add_(dpart)
268
+ if den.dtype in (torch.float32, torch.float64):
269
+ _cl = 1e-9
270
+ else: # half dtypes: 1e-9 flushes to 0 (landmine)
271
+ _cl = float(torch.finfo(den.dtype).tiny) * 8
272
+ out = out / den.unsqueeze(-1).clamp_min(_cl)
273
  return self.drop(self.w_o(out))
274
 
275
 
276
+
277
+ class CausalSplatHUB(nn.Module):
278
+ """Causal (autoregressive) aleph linear attention — the AR-validated
279
+ form from the rank-controlled recall battery. Prefix-sum memories over
280
+ the 2K oriented halves of the address; no selection event; O(L*K*d).
281
+
282
+ Guidance from the measured record (see header): D should match the
283
+ content's intrinsic dimensionality; K should be provisioned to the
284
+ task's addressing demand (knee tracks demand, constant is
285
+ demand-dependent — measure consumed address erank per layer); train
286
+ with momentum-geometric optimizers; fp32/bf16 only."""
287
+
288
+ def __init__(self, d_model, K=64, D=16, tau=0.1):
289
+ super().__init__()
290
+ self.K, self.D, self.tau = K, D, tau
291
+ self.codebook = nn.Parameter(F.normalize(torch.randn(K, D), dim=-1))
292
+ self.q = nn.Linear(d_model, D, bias=False)
293
+ self.k = nn.Linear(d_model, D, bias=False)
294
+ self.v = nn.Linear(d_model, d_model, bias=False)
295
+ self.o = nn.Linear(d_model, d_model, bias=False)
296
+ for m in (self.q, self.k, self.v, self.o):
297
+ nn.init.orthogonal_(m.weight)
298
+
299
+ def _oriented(self, x):
300
+ A = F.normalize(self.codebook, dim=-1)
301
+ u = (F.normalize(x, dim=-1) @ A.T) / self.tau
302
+ m = u.abs().amax(dim=-1, keepdim=True)
303
+ ep, en = torch.exp(u - m), torch.exp(-u - m)
304
+ Z = (ep + en).sum(dim=-1, keepdim=True)
305
+ return ep / Z, en / Z
306
+
307
+ def forward(self, x):
308
+ qp, qn = self._oriented(self.q(x))
309
+ kp, kn = self._oriented(self.k(x))
310
+ v = self.v(x)
311
+ Sp = torch.cumsum(torch.einsum("blk,bld->blkd", kp, v), dim=1)
312
+ Sn = torch.cumsum(torch.einsum("blk,bld->blkd", kn, v), dim=1)
313
+ zp = torch.cumsum(kp, dim=1)
314
+ zn = torch.cumsum(kn, dim=1)
315
+ num = (torch.einsum("blk,blkd->bld", qp, Sp)
316
+ + torch.einsum("blk,blkd->bld", qn, Sn))
317
+ den = ((qp * zp).sum(-1, keepdim=True)
318
+ + (qn * zn).sum(-1, keepdim=True))
319
+ if den.dtype in (torch.float32, torch.float64):
320
+ cl = 1e-12
321
+ else: # half dtypes: small constants flush to 0
322
+ cl = float(torch.finfo(den.dtype).tiny) * 8
323
+ return self.o(num / den.clamp_min(cl))
324
+
325
+
326
  def _demo():
327
  torch.manual_seed(0)
328
  dev = "cuda" if torch.cuda.is_available() else "cpu"