DynaTTT / scripts /run_widowx_memory_ablation.py
DanTim05's picture
Upload Zeva source and project assets
68eed61 verified
Raw History Blame Contribute Delete
5.05 kB
"""Matched external-bank on/off evaluation, without changing training state."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import subprocess
import sys
import time
def summarize(root, checkpoint):
path=root/'eval'/f'{checkpoint.stem}.json'
report=json.loads(path.read_text())
episodes=report['episodes']
traces=[]
for ep in episodes:
traces.extend(json.loads((root/'eval/traces'/checkpoint.stem/f'episode_{ep["seed"]:02d}.json').read_text()))
return dict(report=str(path),episodes=len(episodes),
successes=sum(bool(ep['success']) for ep in episodes),
success_rate=report['success_rate'],
progress={key:sum(bool(ep['progress'].get(key)) for ep in episodes)
for key in ('moved_correct_obj','moved_wrong_obj','is_src_obj_grasped','src_on_target')},
control_steps=len(traces),
gripper_closed_fraction=sum(x['command'][6]<0 for x in traces)/max(1,len(traces)))
def main():
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--checkpoint',type=Path,required=True)
p.add_argument('--output',type=Path,required=True)
p.add_argument('--episodes',type=int,default=20)
p.add_argument('--port',type=int,default=18825)
p.add_argument('--seed-start',type=int,default=0)
p.add_argument('--exec-horizon',type=int,choices=range(1,33),default=4)
p.add_argument('--after',type=Path,help='wait for a preceding matched comparison to finish')
args=p.parse_args()
if args.episodes<1 or args.seed_start<0: p.error('invalid episode count or seed')
if args.after:
print(f'MEMORY_ABLATION_WAITING_FOR {args.after}',flush=True)
while not args.after.is_file():
time.sleep(15)
previous=json.loads(args.after.read_text())
if previous.get('status')!='complete': raise ValueError('Preceding comparison is not complete')
checkpoint=args.checkpoint.resolve(strict=True)
root=args.output.resolve();root.mkdir(parents=True,exist_ok=True)
with checkpoint.open('rb') as stream:
digest=hashlib.file_digest(stream,'sha256').hexdigest()
protocol=dict(checkpoint=str(checkpoint),checkpoint_sha256=digest,
episodes=args.episodes,seed_start=args.seed_start,max_steps=150,
num_steps=30,exec_horizon=args.exec_horizon,guidance=3.0,
modes=['bank_off','on'],policy_gpu=os.environ.get('WIDOWX_EVAL_GPU'),
render_gpu=os.environ.get('WIDOWX_RENDER_GPU'),
intervention='bank_off skips external bank/head loading; global=zeros; CTE/BIT and policy weights unchanged')
manifest=root/'protocol.json'
if manifest.exists() and json.loads(manifest.read_text())!=protocol:
raise ValueError('Existing ablation protocol differs; choose a new output directory')
manifest.write_text(json.dumps(protocol,indent=2))
watcher=Path(__file__).with_name('watch_widowx_eval.py')
summary={}
for mode in protocol['modes']:
run=root/mode
report=run/'eval'/f'{checkpoint.stem}.json'
if not report.exists():
env=os.environ.copy();env['WIDOWX_RUN_DIR']=str(run)
print(f'MEMORY_ABLATION_START mode={mode}',flush=True)
subprocess.run([sys.executable,str(watcher),'--once','--checkpoint',str(checkpoint),
'--episodes',str(args.episodes),'--seed-start',str(args.seed_start),
'--port',str(args.port),'--record-traces','--max-steps','150',
'--num-steps','30','--exec-horizon',str(args.exec_horizon),'--guidance','3',
'--memory-mode',mode],env=env,check=True)
payload=json.loads(report.read_text())
if payload.get('status')!='complete' or payload.get('memory_mode')!=mode or len(payload['episodes'])!=args.episodes:
raise ValueError(f'Incomplete/wrong-mode report: {report}')
for field,expected in [('checkpoint',str(checkpoint)),('max_steps',150),('inference_num_steps',30),
('exec_horizon',args.exec_horizon),('guidance',3.0),('seed_start',args.seed_start)]:
if payload.get(field)!=expected: raise ValueError(f'Protocol mismatch: {field}')
if [ep['seed'] for ep in payload['episodes']]!=list(range(args.seed_start,args.seed_start+args.episodes)):
raise ValueError('Seed sequence differs')
summary[mode]=summarize(run,checkpoint)
print(f'MEMORY_ABLATION_RESULT {mode} '+json.dumps(summary[mode]),flush=True)
result=dict(status='complete',protocol=protocol,results=summary,
caveat='Inference-only ablation on a model trained with bank context; not equivalent to training without it.')
temp=root/'comparison.tmp';temp.write_text(json.dumps(result,indent=2));temp.replace(root/'comparison.json')
print('MEMORY_ABLATION_COMPLETE '+str(root/'comparison.json'),flush=True)
if __name__=='__main__': main()