First-Spike Laplacian Attention / verify_module.py
Mechanism confirmed, baseline not beaten
1import json
2import numpy as np
3import torch
4from laplacian_attention import FirstSpikeLaplacianAttention
5
6
7def main():
8 torch.manual_seed(7)
9 dtype = torch.float64
10 b, h, nq, nk, c, d = 2, 3, 5, 7, 4, 6
11 q = torch.rand(b, h, nq, c, dtype=dtype, requires_grad=True)
12 k = torch.rand(b, h, nk, c, dtype=dtype, requires_grad=True)
13 v = torch.rand(b, h, nk, d, dtype=dtype, requires_grad=True)
14 mod = FirstSpikeLaplacianAttention(h, init_sigma=.7).to(dtype)
15 out, a, _ = mod(q, k, v, return_attention=True)
16 out.square().mean().backward()
17
18 # 13 independent valid cases: near distance 0, far distance delta >= 0.
19 # The expected probability is the exact two-key normalization after L1.
20 delta = torch.linspace(0, 3, 13, dtype=dtype)
21 q2 = torch.zeros(13, 1, 1, 1, dtype=dtype)
22 k2 = torch.stack([torch.zeros_like(delta), delta], dim=-1).reshape(13, 1, 2, 1)
23 v2 = torch.eye(2, dtype=dtype).reshape(1, 1, 2, 2).expand(13, -1, -1, -1)
24 sigma = .7
25 mod2 = FirstSpikeLaplacianAttention(1, init_sigma=sigma).to(dtype)
26 _, a2, _ = mod2(q2, k2, v2, return_attention=True)
27 observed_prob = a2[:, 0, 0, 0].detach().numpy()
28 expected_prob = (1 / (1 + torch.exp(-delta / sigma))).numpy()
29
30 q3 = torch.zeros(1, 1, 1, 1, dtype=dtype)
31 k3 = torch.tensor([[[[.8], [2.4]]]], dtype=dtype)
32 _, a3, _ = mod2(q3, k3, torch.ones(1,1,2,1,dtype=dtype), return_attention=True)
33 observed_log_ratio = float(torch.log(a3[0,0,0,0] / a3[0,0,0,1]))
34 predicted_log_ratio = (2.4-.8)/sigma
35 result = {
36 'shape': list(out.shape),
37 'row_sum_error': float((a.sum(-1)-1).abs().max()),
38 'nonnegative': bool((a >= 0).all()),
39 'positive_bandwidths': mod.bandwidth().detach().tolist(),
40 'gradient_finite': bool(all(x.grad is not None and torch.isfinite(x.grad).all() for x in [q,k,v,mod.theta])),
41 'two_key_max_error': float(np.max(np.abs(observed_prob-expected_prob))),
42 'two_key_crossing_delta': float(delta[np.argmin(np.abs(observed_prob-.5))]),
43 'log_ratio_observed': observed_log_ratio,
44 'log_ratio_predicted': predicted_log_ratio,
45 'log_ratio_error': abs(observed_log_ratio-predicted_log_ratio),
46 }
47 print(json.dumps(result, indent=2))
48
49if __name__ == '__main__': main()