[LAB 13 · 看图生成一句话:训练、解码与消融](/course/notebooks/3da47f3ee3554ee0a36e0bb6a2fdc61f.html) # 5. 读真实图、真实曲线与失败边界 · 实现代码 [独立阅读](/course/notebook-blocks/1a6a0f13eab24338b41badd5b17c9678.html) 按问题继续 真实CNN–GRU条件训练与greedy/beam生成、遮图/错图消融 展开完整实现代码 ``` fig,axes=plt.subplots(2,3,figsize=(10,6)) chosen=[0,3,7,10,14,17] for ax,i in zip(axes.flat,chosen): ax.imshow(Xtest[i].permute(1,2,0)); ax.axis('off') ax.set_title('truth: '+test_text[i]+'\ngreedy: '+pred[i]+'\nbeam: '+beam_pred[i],fontsize=9) fig.suptitle('LAB13: held-out images; model-generated captions',fontsize=13); fig.tight_layout() fig.savefig(OUT/'lab13-caption-predictions.png',dpi=160); plt.show(); plt.close(fig) fig,axes=plt.subplots(1,2,figsize=(10,3.4)) axes[0].plot([r['epoch'] for r in curve],[r['train_token_ce'] for r in curve],label='train'); axes[0].plot([r['epoch'] for r in curve],[r['heldout_teacher_forced_ce'] for r in curve],label='held-out'); axes[0].set(xlabel='epoch',ylabel='mean non-pad token CE');axes[0].legend() labels=['greedy','beam 3','zero image','shuffled image'];values=[metrics[k] for k in ['greedy_exact_match','beam3_exact_match','zero_pixels_exact_match','shuffled_pixels_exact_match']] axes[1].bar(labels,values,color=['#356b91','#40868e','#a9adb0','#a9adb0']);axes[1].set(ylim=(0,1.12),ylabel='exact caption accuracy (180 images)') for i,v in enumerate(values):axes[1].text(i,v+.025,f'{v:.1%}',ha='center') fig.tight_layout();fig.savefig(OUT/'lab13-caption-controls.png',dpi=160);plt.show();plt.close(fig) fig,axes=plt.subplots(1,3,figsize=(9,3)) for ax,x,row in zip(axes,control_pixels,controls): ax.imshow(x.permute(1,2,0));ax.axis('off');ax.set_title('prefix: a\n'+row['generated'],fontsize=10) fig.tight_layout();fig.savefig(OUT/'lab13-same-prefix.png',dpi=160);plt.show();plt.close(fig) result={'notebook_id':'3da47f3ee3554ee0a36e0bb6a2fdc61f','execution':'local CPU, fresh process; not a Deepnote cloud run','created_utc':datetime.now(timezone.utc).isoformat(),'elapsed_seconds':time.perf_counter()-START,'environment':{'python':sys.version,'torch':torch.__version__,'numpy':np.__version__,'platform':platform.platform()},'split':{'train_seed':13031,'test_seed':13033,'train_images':720,'test_images':180,'description':'independent noisy renders; same 18 semantic combinations on both sides; no compositional/general-photo claim'},'metrics':metrics,'curve':curve,'same_prefix_controls':controls,'predictions':[{'truth':t,'greedy':p,'beam3':b,'zero':z,'shuffled':s} for t,p,b,z,s in zip(test_text,pred,beam_pred,zero_pred,shuffle_pred)],'weight_sha256':hashlib.sha256((OUT/'lab13-caption-weights.pt').read_bytes()).hexdigest(),'data_sha256':hashlib.sha256((OUT/'lab13-data.npz').read_bytes()).hexdigest()} (OUT/'lab13-results.json').write_text(json.dumps(result,indent=2)) print('saved',OUT,'seconds',round(result['elapsed_seconds'],2)) ```