65 lines
5.1 KiB
Python
65 lines
5.1 KiB
Python
"""Report Phase 4S gates without selecting new parameters or checkpoints."""
|
||
from pathlib import Path
|
||
import json
|
||
import sys
|
||
import numpy as np
|
||
import pandas as pd
|
||
|
||
root=Path('/data/digital-drosophila/experiments/phase4s-timing-credit')
|
||
r=json.loads((root/'audit/results.json').read_text())
|
||
report={'status':r['status'],'timing':r['calibration'],'heldout':r['heldout'],'formal':r['formal'],
|
||
'isolated_endpoint':r['isolated']['endpoint'] if r['isolated'] else None,
|
||
'isolated_pass':r['isolated']['gate_pass'] if r['isolated'] else None,
|
||
'whole':r['whole'],'timing_gate_pass':r['timing_candidate'],'credit_gate_pass':r['credit_candidate'],
|
||
'regression_pass':r['regression_pass'],'performance':json.loads((root/'performance/summary.json').read_text()),
|
||
'scope':'Open-loop credit accumulation and replay; no learned weights fed back into trial generation; no associative memory claim.'}
|
||
if (root/'formal/group-trajectory.parquet').exists():
|
||
f=pd.read_parquet(root/'formal/group-trajectory.parquet')
|
||
endpoint=f[f.pairing==100].groupby(['arm','group'],as_index=False).agg(
|
||
mean_updated_edges=('updated_edges','mean'),mean_delta_E=('mean_delta_E','mean'),
|
||
mean_total_abs_delta_E=('total_abs_delta_E','mean'),mean_weighted_delta_mv=('total_weighted_delta_mv','mean'))
|
||
report['group_endpoints']=endpoint.to_dict('records')
|
||
c=pd.read_parquet(root/'formal/B-contamination.parquet')
|
||
report['B_contamination_unique_edges']=c.groupby('arm').edge_id.nunique().to_dict() if len(c) else {}
|
||
trajectory=pd.DataFrame(r['isolated']['trajectory']).groupby('pairing',as_index=False).agg(
|
||
A_L1=('A','mean'),B_L1=('B','mean'),random_A_L1=('random_A','mean'),
|
||
A_specific_seeds=('A_specific','sum'),random_specific_seeds=('random_specific','sum'))
|
||
report['isolated_trajectory']=trajectory.to_dict('records')
|
||
sys.path.insert(0,'/tmp/malecns-phase4r-plot-20260929/lib/python3.10/site-packages')
|
||
import matplotlib
|
||
matplotlib.use('Agg')
|
||
import matplotlib.pyplot as plt
|
||
fig,axes=plt.subplots(1,3,figsize=(15,4.5),layout='constrained')
|
||
for ax,group in zip(axes[:2],['A-specific','B-specific']):
|
||
for arm in ('v2_same_US','v2_90ms','v3_matched','v3_random'):
|
||
z=f[(f.group==group)&(f.arm==arm)].groupby('pairing').total_abs_delta_E.mean()
|
||
ax.plot(z.index,z.values,marker='.',label=arm)
|
||
ax.set(title=group+' credit',xlabel='Pairings',ylabel='Mean sum |delta E|');ax.legend(fontsize=8)
|
||
for name in ('A_L1','B_L1','random_A_L1'):
|
||
axes[2].plot(trajectory.pairing,trajectory[name],marker='.',label=name)
|
||
axes[2].set(title='Isolated MBON output change',xlabel='Pairings',ylabel='Mean spike-count L1');axes[2].legend(fontsize=8)
|
||
(root/'figures').mkdir(exist_ok=True);fig.savefig(root/'figures/credit-and-transfer.png',dpi=180);plt.close(fig)
|
||
(root/'audit/mechanism-summary.json').write_text(json.dumps(report,indent=2,sort_keys=True)+'\n')
|
||
lines=['# Phase 4S:时序修复与 credit 特异性验证','',f"状态:`{r['status']}`",'',
|
||
'本轮只改变外部 US 时序及预注册的局部 eligibility 窗口。全脑动力学、APL、嗅觉 encoder、学习幅度和 14,232 条 plastic mask 保持冻结。',
|
||
'', '比较采用同一批真实 KC 事件,累积实验性 E overlay;事件采集始终使用未学习的 base brain。结果不构成在线关联记忆声明。','']
|
||
if r['calibration']:
|
||
t=r['calibration'];lines+=[f"校准选择:US={t['US_ms']} ms,window={t['window_ms']} ms,tau={t['tau_ms']:.6f} ms。",'']
|
||
if r['heldout']:
|
||
lines+=['独立 seeds 验证:','', '| 气味 | matched/random credit 比值 | 达标 seeds |','|---|---:|---:|']
|
||
for x in r['heldout']['odors']:lines.append(f"| {x['label']} | {x['ratio']:.4f} | {x['qualifying_seeds']}/5 |")
|
||
lines+=['',f"独立 timing gate:{r['heldout']['pass']}。",'']
|
||
if r['formal']:
|
||
lines+=[f"正式 A/B credit gate:{r['formal']['gate_pass']}(预注册 100-pairing 终点)。",'']
|
||
else:
|
||
lines+=['独立 timing gate 未通过,正式累积权重实验、isolated replay 和 whole-brain 传递实验均未执行。未生成学习产物;不能据此判断这些未执行实验的结果。','']
|
||
if r['isolated']:
|
||
lines+=[f"Isolated gate:{r['isolated']['gate_pass']}。",'', '| Seed | A L1 | B L1 | random A L1 | random B L1 |','|---|---:|---:|---:|---:|']
|
||
for x in r['isolated']['endpoint']:lines.append(f"| {x['seed']} | {x['A']} | {x['B']} | {x['random_A']} | {x['random_B']} |")
|
||
lines+=['','','']
|
||
lines += [f"Whole-brain:{json.dumps(r['whole'],ensure_ascii=False)}",'',
|
||
f"冻结参考回归:{r['regression_pass']}。完整 frozen integrity 结果见 `frozen-integrity.json`。",'',
|
||
'限制:只有两个 calibration odors 和五个独立验证 seeds;credit 改善与刺激特异 MBON 功能变化分别判定。没有根据正式 A/B 或 heldout 结果重新挑参数,没有提前停止在最有利 checkpoint。']
|
||
(root/'audit/REPORT.md').write_text('\n'.join(lines)+'\n',encoding='utf-8')
|
||
print(json.dumps({k:v for k,v in report.items() if k not in ('group_endpoints','isolated_trajectory')},indent=2))
|