brandonmusic's picture
Add CPU-only paired quality analysis and metric explanations
66293d6 verified
Raw
History Blame Contribute Delete
4.93 kB
from pathlib import Path
import json, hashlib,itertools
import numpy as np
from scipy.special import xlogy
P=Path(__file__).resolve().parent
roots={'MX':Path('/media/brandonmusic/nvme1n1p3/trellismx-reference-kld-20260909'),'TR3':Path('/media/brandonmusic/nvme1n1p3/glm53-tr3-kld-20260909/attempt2')}
def sha(p):
with p.open('rb') as f:return hashlib.file_digest(f,'sha256').hexdigest()
def save(n,x):(P/n).write_text(json.dumps(x,indent=2)+'\n')
save('plan.json',{'status':'Exploratory post-hoc, already-opened CF32; no model execution','mask':'prediction rows 1..2046; equal 32 window means','metrics':['retained full teacher-to-student KL mean and token quantiles','top1 agreement, actual-token top1 hit rate','mean NLL and perplexity','actual-token probability absolute error','six student-pair top1 agreements','all ten teacher/student pairs: actual-next-token versus rest KL both directions and JS','student cache changes: teacher top1 retained/lost/gained'],'limits':'Two-bucket KL is a lower bound on full KL, not its estimate. One actual next token is not an answer correctness label. No independent repetitions, no new qualification, no multiplicity-adjusted claims.'})
D={};receipts=[];wins=None;inventory=[]
for model,root in roots.items():
ws=json.loads((root/'verified-inputs.json').read_text())['windows']
if wins is None:wins=ws
assert ws==wins
for cache in ['fp8','nvfp4']:
arr=[]
for w in ws:
p=root/cache/'scores'/f"{w['id']}.npz";r=json.loads(p.with_suffix('.json').read_text())
assert sha(p)==r['score_sha256'] and r['teacher_sha256']==w['teacher_sha256'] and r['token_sha256']==w['token_values_sha256'] and r['true_decode_rows']==2046
with np.load(p) as z:a={k:np.asarray(z[k][1:],dtype=np.float64 if z[k].dtype.kind=='f' else z[k].dtype) for k in z.files}
assert all(v.shape==(2046,) for v in a.values());arr.append(a)
receipts.append({'path':str(p),'sha256':r['score_sha256']})
D[model+'_'+cache]={k:np.stack([a[k] for a in arr]) for k in arr[0]}
inventory.extend({'path':str(p),'bytes':p.stat().st_size} for p in (root/cache).rglob('*') if p.is_file() and ('logit' in p.name or p.suffix in ['.f32','.npy']))
base=next(iter(D.values()))
for a in D.values():
for k in ['teacher_top1','teacher_top1_p','teacher_entropy','realized_token','teacher_logp_realized']:assert np.array_equal(a[k],base[k]),k
out={'rows':65472,'windows':32,'arms':{},'pairs':{},'cache_changes':{},'inputs':receipts,'raw_inventory':inventory,'script_sha256':sha(Path(__file__)),'plan_sha256':sha(P/'plan.json')}
probs={'BF16':np.exp(base['teacher_logp_realized'])}
def summary(v):return {'mean':float(v.mean()),'per_window':v.mean(axis=1).tolist()}
def kl(p,q):return xlogy(p,p)-xlogy(p,q)+xlogy(1-p,1-p)-xlogy(1-p,1-q)
# Verify binary KL implementation on known controls.
assert np.allclose(kl(np.array([.2,.5]),np.array([.2,.5])),0)
assert np.allclose(kl(np.array([.5]),np.array([.25])),.5*np.log(4/3))
for name,a in D.items():
p=np.exp(a['student_logp_realized']);assert np.all((p>0)&(p<1));probs[name]=p
agree=a['teacher_top1']==a['student_top1'];actual=a['student_top1']==a['realized_token']
out['arms'][name]={'full_teacher_KL':summary(a['kld']),'KL_token_quantiles':dict(zip(['p50','p90','p95','p99','max'],map(float,np.quantile(a['kld'],[.5,.9,.95,.99,1])))),'teacher_top1_agreement':summary(agree),'actual_token_top1_hit':summary(actual),'NLL':summary(-a['student_logp_realized']),'perplexity':float(np.exp(-a['student_logp_realized'].mean())),'actual_token_probability_MAE_vs_teacher':summary(abs(p-probs['BF16'])),'high_confidence_teacher_matches':int((agree & (a['teacher_top1_p']>=.9)).sum())}
for n,m in itertools.combinations(probs,2):
p,q=probs[n],probs[m];mid=(p+q)/2
v={'KL_A_to_B_two_bucket':summary(kl(p,q)),'KL_B_to_A_two_bucket':summary(kl(q,p)),'JS_two_bucket':summary((kl(p,mid)+kl(q,mid))/2),'actual_token_probability_MAE':summary(abs(p-q))}
if n in D and m in D:v['top1_agreement']=summary(D[n]['student_top1']==D[m]['student_top1'])
if n=='BF16':assert np.all(kl(p,q)<=D[m]['kld']+1e-6)
out['pairs'][n+' vs '+m]=v
for model in roots:
a,b=D[model+'_fp8'],D[model+'_nvfp4'];am=a['student_top1']==a['teacher_top1'];bm=b['student_top1']==b['teacher_top1']
out['cache_changes'][model]={'top1_flips':int((a['student_top1']!=b['student_top1']).sum()),'teacher_match_lost':int((am&~bm).sum()),'teacher_match_gained':int((~am&bm).sum()),'full_teacher_KL_increase':summary(b['kld']-a['kld'])}
out['teacher']={'actual_token_top1_hit':float((base['teacher_top1']==base['realized_token']).mean()),'perplexity':float(np.exp(-base['teacher_logp_realized'].mean()))}
save('results.json',out)
print(json.dumps({'arms':{k:{m:(v['mean'] if isinstance(v,dict) and 'mean' in v else v) for m,v in a.items()} for k,a in out['arms'].items()},'pairs':{k:{m:v['mean'] for m,v in a.items()} for k,a in out['pairs'].items()},'cache_changes':out['cache_changes'],'raw_inventory':inventory},indent=2))