training note + addr_proj: the converging configuration (rotary+addr_proj+train_codebooks), measured; frozen-all collapses in training
Browse files- splat_attention.py +24 -9
splat_attention.py
CHANGED
|
@@ -61,12 +61,21 @@
|
|
| 61 |
# y = attn(x, key_padding_mask=kpm) # kpm: (B, L) True = pad
|
| 62 |
# python splat_attention.py # runs the demo + a small speed bench
|
| 63 |
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
# Status: research prototype. Trained-at-scale results pending; treat
|
| 65 |
# every number above as what it is — a measurement on the stated probe.
|
| 66 |
-
#
|
| 67 |
-
# License: MIT
|
| 68 |
-
# Author: AbstractPhil + Claude
|
| 69 |
-
# Home: https://huggingface.co/AbstractPhil/aleph-splat-0/
|
| 70 |
# =========================================================================
|
| 71 |
|
| 72 |
import math
|
|
@@ -115,7 +124,7 @@ class SplatAttention(nn.Module):
|
|
| 115 |
def __init__(self, d_model, M=64, K=8, tau=0.1, dropout=0.0,
|
| 116 |
rotary=True, global_frac=0.0, overlap=1.5,
|
| 117 |
sigma_floor=0.0, head_gates=False, train_centers=False,
|
| 118 |
-
train_codebooks=False, mchunk=16,
|
| 119 |
checkpoint_chunks=False):
|
| 120 |
super().__init__()
|
| 121 |
self.M, self.K, self.tau = M, K, tau
|
|
@@ -131,6 +140,13 @@ class SplatAttention(nn.Module):
|
|
| 131 |
self.register_buffer("codebook", book)
|
| 132 |
self.w_v = nn.Linear(d_model, d_model)
|
| 133 |
self.w_o = nn.Linear(d_model, d_model)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
self.drop = nn.Dropout(dropout)
|
| 135 |
if train_centers:
|
| 136 |
self.center_off = nn.Parameter(torch.zeros(M))
|
|
@@ -187,7 +203,8 @@ class SplatAttention(nn.Module):
|
|
| 187 |
|
| 188 |
def forward(self, x, key_padding_mask=None):
|
| 189 |
B, L, d = x.shape
|
| 190 |
-
|
|
|
|
| 191 |
if self.rotary:
|
| 192 |
pos = torch.arange(L, device=x.device, dtype=torch.float32)
|
| 193 |
xn = F.normalize(rope_rotate(xn.float(), pos),
|
|
@@ -216,7 +233,6 @@ class SplatAttention(nn.Module):
|
|
| 216 |
return self.drop(self.w_o(out))
|
| 217 |
|
| 218 |
|
| 219 |
-
|
| 220 |
def _demo():
|
| 221 |
torch.manual_seed(0)
|
| 222 |
dev = "cuda" if torch.cuda.is_available() else "cpu"
|
|
@@ -232,7 +248,7 @@ def _demo():
|
|
| 232 |
if dev == "cuda":
|
| 233 |
import time
|
| 234 |
mha = nn.MultiheadAttention(256, 8, batch_first=True).to(dev)
|
| 235 |
-
for L, B in [(128,
|
| 236 |
xx = torch.randn(B, L, 256, device=dev, requires_grad=True)
|
| 237 |
def t(fn, n=10):
|
| 238 |
for _ in range(3):
|
|
@@ -251,6 +267,5 @@ def _demo():
|
|
| 251 |
"head_gates=True for learnable attenuation)")
|
| 252 |
|
| 253 |
|
| 254 |
-
|
| 255 |
if __name__ == "__main__":
|
| 256 |
_demo()
|
|
|
|
| 61 |
# y = attn(x, key_padding_mask=kpm) # kpm: (B, L) True = pad
|
| 62 |
# python splat_attention.py # runs the demo + a small speed bench
|
| 63 |
#
|
| 64 |
+
# TRAINING NOTE (measured 2026-08-06/07, 500k-caption encoder screens):
|
| 65 |
+
# the all-frozen configuration COLLAPSES when trained inside a trunk
|
| 66 |
+
# (representation erank ~5) — parameter-free routing deforms token
|
| 67 |
+
# states into address basins. The configuration that CONVERGES:
|
| 68 |
+
# SplatAttention(..., rotary=True, addr_proj=True,
|
| 69 |
+
# train_codebooks=True)
|
| 70 |
+
# (routing-owned parameters: a learned address frame + living
|
| 71 |
+
# codebooks). It reaches ~90% of a standard block's training-gauge
|
| 72 |
+
# performance at matched small budget and was still climbing at
|
| 73 |
+
# cutoff — functional, slower to organize, endpoint parity unproven.
|
| 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 |
# =========================================================================
|
| 80 |
|
| 81 |
import math
|
|
|
|
| 124 |
def __init__(self, d_model, M=64, K=8, tau=0.1, dropout=0.0,
|
| 125 |
rotary=True, global_frac=0.0, overlap=1.5,
|
| 126 |
sigma_floor=0.0, head_gates=False, train_centers=False,
|
| 127 |
+
train_codebooks=False, addr_proj=False, mchunk=16,
|
| 128 |
checkpoint_chunks=False):
|
| 129 |
super().__init__()
|
| 130 |
self.M, self.K, self.tau = M, K, tau
|
|
|
|
| 140 |
self.register_buffer("codebook", book)
|
| 141 |
self.w_v = nn.Linear(d_model, d_model)
|
| 142 |
self.w_o = nn.Linear(d_model, d_model)
|
| 143 |
+
if addr_proj:
|
| 144 |
+
# learned address frame, born at identity — routing-owned
|
| 145 |
+
# parameters (see TRAINING note in the module docstring)
|
| 146 |
+
self.w_a = nn.Linear(d_model, d_model, bias=False)
|
| 147 |
+
nn.init.eye_(self.w_a.weight)
|
| 148 |
+
else:
|
| 149 |
+
self.w_a = None
|
| 150 |
self.drop = nn.Dropout(dropout)
|
| 151 |
if train_centers:
|
| 152 |
self.center_off = nn.Parameter(torch.zeros(M))
|
|
|
|
| 203 |
|
| 204 |
def forward(self, x, key_padding_mask=None):
|
| 205 |
B, L, d = x.shape
|
| 206 |
+
xa = self.w_a(x) if self.w_a is not None else x
|
| 207 |
+
xn = F.normalize(xa, dim=-1)
|
| 208 |
if self.rotary:
|
| 209 |
pos = torch.arange(L, device=x.device, dtype=torch.float32)
|
| 210 |
xn = F.normalize(rope_rotate(xn.float(), pos),
|
|
|
|
| 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"
|
|
|
|
| 248 |
if dev == "cuda":
|
| 249 |
import time
|
| 250 |
mha = nn.MultiheadAttention(256, 8, batch_first=True).to(dev)
|
| 251 |
+
for L, B in [(128, 32), (2048, 2)]:
|
| 252 |
xx = torch.randn(B, L, 256, device=dev, requires_grad=True)
|
| 253 |
def t(fn, n=10):
|
| 254 |
for _ in range(3):
|
|
|
|
| 267 |
"head_gates=True for learnable attenuation)")
|
| 268 |
|
| 269 |
|
|
|
|
| 270 |
if __name__ == "__main__":
|
| 271 |
_demo()
|