Download paper/build_figures.py from nur-dev/unionmind-predictive-representations: direct link, hf CLI and curl.
- Browser
- Download file 9.13 kB
-
https://huggingface.co/nur-dev/unionmind-predictive-representations/resolve/main/paper/build_figures.py
- Command line
-
hf download hf://nur-dev/unionmind-predictive-representations/paper/build_figures.py
-
curl -L -o build_figures.py https://huggingface.co/nur-dev/unionmind-predictive-representations/resolve/main/paper/build_figures.py
9.13 kB
| """Generate every plotted value and table body from archived result records.""" | |
| from pathlib import Path | |
| import json,csv,statistics,shutil | |
| import matplotlib | |
| matplotlib.use('Agg') | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| R=Path(__file__).resolve().parents[1];A=R/'paper';F=A/'figures';T=A/'tables';F.mkdir(exist_ok=True);T.mkdir(exist_ok=True);(A/'metadata').mkdir(exist_ok=True) | |
| plt.rcParams.update({'font.family':'DejaVu Sans','font.size':11.5,'axes.spines.top':False,'axes.spines.right':False,'pdf.fonttype':42,'savefig.bbox':'tight'}) | |
| NAMES={'additive_full':'Additive Gaussian','additive_diag':'Diagonal Gaussian','factorized_neural':'Factorized forward MLP','joint_neural':'Joint-state forward MLP','factorized_nb':'Factorized Gaussian NB','factorized_lda':'Factorized Gaussian LDA','factorized_kernel':'Factorized kernel','factorized_ridge':'Factorized ridge','joint_gaussian':'Joint-state Gaussian','factorized_logistic':'Factorized logistic','factorized_classifier':'Direct factorized MLP'} | |
| METHODS={'query_joint':'Joint predictive clustering','posterior_clusters':'Posterior clustering','posterior_bins':'Posterior bins','future_marginal':'Observation clustering','raw_information':'Three features by mutual information','raw_entropy':'Three features by entropy','hash_code':'Fixed hash','identity':'Uncompressed mixture'} | |
| load=lambda p:json.loads((R/p).read_text()) | |
| control=load('results/controlled/decision.json');day=load('provenance/verification/independent_statistics.json');hydro=load('provenance/hydraulic/opened_hydraulic_summary.json');summary=load('provenance/temperature/summary.json') | |
| primary={r['method']:r for r in control['primary_metrics']} | |
| with (T/'controlled.tex').open('w') as f: | |
| for m in ['query_joint','raw_information','raw_entropy','posterior_clusters','posterior_bins','future_marginal','hash_code','identity']: | |
| r=primary[m];f.write(f"{METHODS[m]} & {r['utility']:.4f} & {r['representation_loss']:.4f} & {r['model_loss']:.4f} " + chr(92)*2 + chr(10)) | |
| front=list(csv.DictReader((R/'results/controlled/frontier.csv').open())) | |
| fig,ax=plt.subplots(1,2,figsize=(8,3.7)) | |
| for m,c in [('query_joint','#176b91'),('raw_information','#ba682e'),('posterior_clusters','#767676'),('identity','#277a50')]: | |
| xs=[64,256,1024,4096];ys=[] | |
| for n in xs: | |
| rows=[r for r in front if r['availability']=='full' and r['model']=='support_mixture' and r['method']==m and int(r['label_budget'])==n and int(r['query_budget'])>0] | |
| assert len(rows)==2,(m,n,len(rows));ys.append(statistics.mean(float(r['utility']) for r in rows)) | |
| ax[0].plot(xs,ys,'o-',color=c,label=METHODS[m]) | |
| ax[0].set_xscale('log',base=2);ax[0].set_xticks(xs,[str(x) for x in xs]);ax[0].set_xlabel('Estimation records');ax[0].set_ylabel('Expected utility');ax[0].set_title('(a) Sample dependence');ax[0].legend(fontsize=9,loc='lower right') | |
| fam=list(csv.DictReader((R/'results/controlled/primary_families.csv').open()));families=sorted(set(r['family'] for r in fam)) | |
| for m,dx,c in [('query_joint',-.24,'#176b91'),('raw_information',0,'#ba682e'),('posterior_clusters',.24,'#767676')]: | |
| ys=[float(next(r['utility'] for r in fam if r['family']==fa and r['method']==m)) for fa in families] | |
| ax[1].bar(np.arange(6)+dx,ys,.23,color=c,label=METHODS[m]) | |
| ax[1].set_xticks(np.arange(6),[x.replace('_','\n') for x in families],rotation=30,ha='right',fontsize=9);ax[1].set_ylabel('Expected utility');ax[1].set_title('(b) All six declared mechanism families');fig.tight_layout();fig.savefig(F/'controlled.pdf');plt.close(fig) | |
| # Matrix uses independent verification's equal-day scores, never the pooled-episode scores. | |
| def dscore(model,n):return next(r['top3_equal_day'] for r in day['summary'] if r['model']==model and r['samples']==n) | |
| def hscore(model,n): | |
| rows=[r for r in hydro['rows'] if r.get('model')==model and r.get('samples')==n] | |
| assert len(rows)==1,(model,n,rows);return rows[0]['top3'] | |
| with (T/'all_models.tex').open('w') as f: | |
| for m in NAMES: | |
| vals=[hscore(m,64),hscore(m,128),dscore(m,64),dscore(m,128)] | |
| f.write(NAMES[m]+' & '+' & '.join(f'{v*100:.2f}' for v in vals)+' '+chr(92)*2+chr(10)) | |
| fig,axes=plt.subplots(1,2,figsize=(8,5.2),sharey=True) | |
| for axis,n in zip(axes,[64,128]): | |
| y=np.arange(len(NAMES));axis.barh(y-.16,[100*hscore(m,n) for m in NAMES],.3,label='Hydraulic: opened development',color='#ba682e');axis.barh(y+.16,[100*dscore(m,n) for m in NAMES],.3,label='Gas array: four held days',color='#176b91');axis.set_yticks(y,list(NAMES.values()),fontsize=11);axis.set_ylim(len(NAMES)-.5,-.5);axis.set_xlim(0,105);axis.set_xlabel('Unseen-combination Top-3 (%)');axis.set_title(f'{n} total fitting examples');axis.grid(axis='x',alpha=.2) | |
| axes[1].legend(fontsize=9,loc='lower right');fig.tight_layout();fig.savefig(F/'models.pdf');plt.close(fig) | |
| fig,axes=plt.subplots(1,3,figsize=(8,3)) | |
| for axis,reference in zip(axes,['factorized_classifier','additive_full','factorized_lda']): | |
| a=next(r['per_day'] for r in day['summary'] if r['model']=='factorized_neural' and r['samples']==64);b=next(r['per_day'] for r in day['summary'] if r['model']==reference and r['samples']==64);g=100*(np.array(a)-np.array(b));axis.axhline(0,color='black',lw=.8);axis.scatter(range(1,5),g,color='#176b91',s=45);axis.set_xticks(range(1,5));axis.set_ylim(-20,50);axis.set_xlabel('Held day (ordered)');axis.set_title(NAMES[reference],fontsize=10);axis.grid(alpha=.15) | |
| axes[0].set_ylabel('Forward MLP gain (percentage points)');fig.tight_layout();fig.savefig(F/'days.pdf');plt.close(fig) | |
| with (T/'seen_models.tex').open('w') as f: | |
| for m in NAMES: | |
| vals=[] | |
| for n in [64,128]: | |
| rows=[r for r in summary['rows'] if r.get('model')==m and r.get('samples')==n and r.get('stratum')=='seen' and r.get('day') is not None] | |
| assert len(rows)==4;vals.append(statistics.mean(r['top3'] for r in rows)) | |
| f.write(NAMES[m]+' & '+' & '.join(f'{100*v:.2f}' for v in vals)+' '+chr(92)*2+chr(10)) | |
| proof={'controlled_gain':control['compact_comparisons'][3], 'temperature_scores':{m:dscore(m,64) for m in NAMES},'hydraulic_scores':{m:hscore(m,64) for m in NAMES},'figure_sources':['results/controlled/frontier.csv','results/controlled/primary_families.csv','provenance/verification/independent_statistics.json','provenance/hydraulic/opened_hydraulic_summary.json']} | |
| (A/'metadata/figure_values.json').write_text(json.dumps(proof,indent=2)+'\n') | |
| diagnostics=load('results/sensitivity_analysis/frozen_diagnostics.json') | |
| with (T/'sensitivity.tex').open('w') as f: | |
| for cohort,label in [('hydraulic','Hydraulic'),('temperature','Gas array')]: | |
| for n in [64,128]: | |
| rows={r['model']:r for r in diagnostics['sensor']['summary'] if r['cohort']==cohort and r['samples']==n} | |
| values=[label,str(n),str(rows['factorized_neural']['observed_combinations'])] | |
| values += [f"{100*rows[m]['macro_combination_top3']:.2f}" for m in ['factorized_neural','factorized_classifier','additive_full','factorized_lda']] | |
| f.write(' & '.join(values)+' '+chr(92)*2+chr(10)) | |
| print('Generated 3 vector figures and 5 table bodies') | |
| for filename,macro in [("controlled.tex","ControlledRows"),("all_models.tex","AllModelRows"),("seen_models.tex","SeenModelRows"),("sensitivity.tex","SensitivityRows")]: | |
| p=T/filename;p.write_text(chr(92)+"newcommand{"+chr(92)+macro+"}{%"+chr(10)+p.read_text()+"}%"+chr(10)) | |
| # The added control is descriptive on opened worlds, not a revised primary test. | |
| import gzip | |
| with gzip.open(R/'results/postconfirmation/controlled_frontiers.csv.gz','rt') as handle: | |
| additional=list(csv.DictReader(handle)) | |
| new_timing=load('results/postconfirmation/controlled_summary.json')['warm_batched_construction_medians'] | |
| order=[('identity','Uncompressed mixture'),('query_joint','Joint predictive clustering'), | |
| ('posterior_clusters','Posterior clustering'),('posterior_bins','Posterior bins'), | |
| ('future_marginal','Observation-only clustering'),('raw_information','Mutual-information selection'), | |
| ('raw_entropy','Entropy selection'),('hash_code','Fixed hash'), | |
| ('action_values','Action-value clustering (added)')] | |
| rows=[chr(92)+'newcommand{'+chr(92)+'ActionValueRows}{'] | |
| for method,label in order: | |
| values=[] | |
| for n in [64,256,1024,4096]: | |
| selected=[float(r['utility']) for r in additional if int(r['available'])==6 | |
| and r['estimator']=='support_mixture' and r['method']==method | |
| and int(r['labels'])==n and int(r['budget'])>0] | |
| assert len(selected)==6 | |
| values.append(statistics.mean(selected)) | |
| rows.append(label+' & '+' & '.join(f'{v:.4f}' for v in values) | |
| +f' & {1000*new_timing[method]:.2f}'+chr(92)*2) | |
| rows.extend(['}',chr(92)+'newcommand{'+chr(92)+'CrossedCovarianceRows}{']) | |
| cross=load('results/postconfirmation/sensor_diagnostics.json')['crossed_mean_covariance'] | |
| for m in [64,128]: | |
| for c in [64,128]: | |
| selected=[r for r in cross if r['mean_labels']==m and r['covariance_labels']==c] | |
| rows.append(f'{m} & {c} & {100*statistics.mean(r["top3"] for r in selected):.2f}' | |
| +f' & {statistics.mean(r["hypothesis_log_loss"] for r in selected):.2f}'+chr(92)*2) | |
| rows.append('}') | |
| (T/'postconfirmation.tex').write_text('\n'.join(rows)+'\n') | |