summaryrefslogtreecommitdiff
path: root/artifacts/spectral_frontier_probe/diag10.py
diff options
context:
space:
mode:
Diffstat (limited to 'artifacts/spectral_frontier_probe/diag10.py')
-rw-r--r--artifacts/spectral_frontier_probe/diag10.py41
1 files changed, 41 insertions, 0 deletions
diff --git a/artifacts/spectral_frontier_probe/diag10.py b/artifacts/spectral_frontier_probe/diag10.py
new file mode 100644
index 0000000..752612c
--- /dev/null
+++ b/artifacts/spectral_frontier_probe/diag10.py
@@ -0,0 +1,41 @@
+import numpy as np, torch
+from collections import defaultdict
+def standardise(M):
+ M=np.asarray(M,dtype=np.float64); mask=~np.eye(len(M),dtype=bool); v=M[mask]
+ out=(M-v.mean())/v.std(); np.fill_diagonal(out,0.0); return out
+d=torch.load('/home/yurenh2/emm/artifacts/synth_v1/omit_size.pt',map_location='cpu')
+V0=d['visual_field'].double().numpy(); T0=d['text_field'].double().numpy()
+T=standardise(T0); V=standardise(V0); N=len(T)
+# exact automorphism-by-identical-rows of T (blind: uses T only)
+key={}; cls=defaultdict(list)
+Toff=T.copy(); np.fill_diagonal(Toff,0.0)
+# group scenes whose T rows agree after removing the two swapped coords
+groups=[]; used=np.zeros(N,bool)
+for i in range(N):
+ if used[i]: continue
+ g=[i]; used[i]=True
+ for j in range(i+1,N):
+ if used[j]: continue
+ a=np.delete(Toff[i],[i,j]); b=np.delete(Toff[j],[i,j])
+ if np.abs(a-b).max()<1e-9 and abs(Toff[i,j]-max(Toff[i,i],0))<1e6:
+ g.append(j); used[j]=True
+ groups.append(g)
+sizes=np.array([len(g) for g in groups])
+print("T exact-twin classes: total",len(groups),"; size histogram",np.bincount(sizes)[1:])
+excess=int((sizes-1).sum())
+print("scenes in non-trivial classes:",int(sizes[sizes>1].sum()),"; log|Aut| classes:",int((sizes>1).sum()))
+ceil=(N-int(sizes[sizes>1].sum())+int((sizes>1).sum()))/N
+print(f"blind accuracy ceiling if class is identified but member picked at random: {ceil:.3f}")
+# check the objective really is invariant: swap two members of a class
+import itertools
+p=np.arange(N)
+E0=(( (T*T).sum()+(V*V).sum() )-2*(T[np.ix_(p,p)]*V).sum())/(N*(N-1))
+bad=0; tested=0
+for g in groups:
+ if len(g)>1:
+ i,j=g[0],g[1]; q=p.copy(); q[[i,j]]=q[[j,i]]
+ E1=(((T*T).sum()+(V*V).sum())-2*(T[np.ix_(q,q)]*V).sum())/(N*(N-1))
+ tested+=1
+ if abs(E1-E0)>1e-9: bad+=1
+print(f"swapping twins changes E in {bad}/{tested} classes (0 means exact symmetry of the objective)")
+print(f"E(truth) = {E0:.10f}")