75 lines
4.2 KiB
Python
75 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Targeted GPU replays of the two Phase 4N/4M eligibility discrepancies."""
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
import torch
|
|
|
|
from phase4n import load_config
|
|
from phase4i import Validator
|
|
from phase4j import apply_v2
|
|
from phase4l import OdorSimulator,pn_drive
|
|
from phase4m import load_odor_inputs
|
|
from phase4o_a import EXP,ROOT,save
|
|
|
|
|
|
def main():
|
|
ncfg,mcfg,cfg,cfgpath=load_config(ROOT/'models/male-cns-lif/credit-assignment-v1/phase4n.yaml')
|
|
history=pd.read_parquet(Path(mcfg['experiment_root'])/'efficacy-overlay/update-history.parquet')
|
|
by={(int(s),int(p)):g for (s,p),g in history.groupby(['train_seed','pairing'])}
|
|
v=Validator(cfg,cfgpath,EXP);sim=OdorSimulator(v,cfg,EXP)
|
|
panel,vectors,selection,mapping=load_odor_inputs(cfg)
|
|
oid=selection['ODOR_A']['odor_id']
|
|
pn=pn_drive(oid,vectors[oid],mapping,selection['glomeruli_order'],str(mcfg['protocol']['input_mode']),float(np.median(panel.mapped_response_sum)),cfg)[:2]
|
|
target=str(mcfg['protocol']['target_compartment_verbatim'])
|
|
dan=v.dan_targets(str(mcfg['protocol']['matched_dan_type']),target)
|
|
lookup=np.full(v.n,-1,np.int32);lookup[v.kc]=np.arange(len(v.kc),dtype=np.int32)
|
|
loc=lookup[v.cand.source_neuron_idx.to_numpy(np.int32)]
|
|
eid_to_local=pd.Series(np.arange(len(v.edge_ids),dtype=np.int32),index=v.edge_ids.astype(np.int64))
|
|
rows=[]
|
|
for seed,pairing in [(51202,40),(51203,39)]:
|
|
delta=np.zeros(len(v.edge_ids),np.float32)
|
|
for p in range(1,pairing):
|
|
rec=by[(seed,p)]
|
|
local=eid_to_local.loc[rec.edge_id.to_numpy(np.int64)].to_numpy(np.int32)
|
|
frozen_trace=np.zeros(len(v.kc),np.float32)
|
|
frozen_trace[loc[local]]=rec.eligibility.to_numpy(np.float32)
|
|
delta,_=apply_v2(v,frozen_trace,target,1.,delta,cfg)
|
|
rec=by[(seed,pairing)]
|
|
local=eid_to_local.loc[rec.edge_id.to_numpy(np.int64)].to_numpy(np.int32)
|
|
old_trace=rec.eligibility.to_numpy(np.float32)
|
|
for repeat in range(15):
|
|
run=sim.run_rates(*pn,seed+pairing,float(mcfg['protocol']['duration_ms']),delta=delta,dan_targets=dan,
|
|
dan_pulses=[float(mcfg['protocol']['dan_time_ms'])],collect_kc_spikes=True)
|
|
observed=run['kc_trace_at_dan'][loc[local]]
|
|
diff=np.abs(observed-old_trace)
|
|
j=int(np.argmax(diff)) if len(diff) else None
|
|
events=run['kc_spikes'][['step','neuron_idx']].to_numpy(np.int32)
|
|
row={'seed':seed,'pairing':pairing,'repeat':repeat,'event_count':len(events),
|
|
'event_sha256':hashlib.sha256(events.tobytes()).hexdigest(),
|
|
'trace_sha256':hashlib.sha256(observed.tobytes()).hexdigest(),
|
|
'max_abs_error_vs_frozen':float(diff.max()) if len(diff) else 0.,
|
|
'exact_to_frozen':bool(len(diff)==0 or float(diff.max())<=2e-5),
|
|
'first_largest_error_edge_id':int(rec.edge_id.iloc[j]) if j is not None else None,
|
|
'first_largest_error_KC_neuron_idx':int(v.cand.source_neuron_idx.iloc[local[j]]) if j is not None else None,
|
|
'observed_eligibility':float(observed[j]) if j is not None else None,
|
|
'frozen_eligibility':float(old_trace[j]) if j is not None else None,
|
|
'wall_seconds':run['wall_seconds']}
|
|
rows.append(row)
|
|
print(json.dumps({'seed':seed,'pairing':pairing,'repeat':repeat,'exact':row['exact_to_frozen'],
|
|
'event_sha256':row['event_sha256'][:12]}),flush=True)
|
|
save(EXP/'eligibility-replay/targeted-gpu-repeats.json',rows)
|
|
save(EXP/'eligibility-replay/targeted-summary.json',{'rows':len(rows),
|
|
'exact_count':sum(r['exact_to_frozen'] for r in rows),
|
|
'distinct_event_hashes_by_trial':{f'{s}/{p}':len({r['event_sha256'] for r in rows if r['seed']==s and r['pairing']==p}) for s,p in [(51202,40),(51203,39)]},
|
|
'same_seed_config_and_sealed_additive_prefix':True,
|
|
'note':'This is an isolated 15-repeat targeted diagnostic of the two formerly discrepant trials, not a 5x500 complete brain rerun.'})
|
|
|
|
|
|
if __name__=='__main__':main()
|