Lecture 03 学习讲义
正文
工具
按问题查找
Lecture 033. 运行比较:用验证集选每组的停点 · 实现代码

3. 运行比较:用验证集选每组的停点 · 实现代码

独立阅读

按问题继续

同源参数的冻结/局部/全量/scratch与BN模式辨析

展开完整实现代码
@torch.no_grad()
def evaluate_binary(model,xx,yy):
    model.eval();scores=model(xx)
    return {'ce':float(F.cross_entropy(scores,yy)), 'accuracy':float((scores.argmax(1)==yy).float().mean())}
torch.use_deterministic_algorithms(True)
generator=torch.Generator().manual_seed(SEED+2)
orders=[torch.randperm(len(train_y),generator=generator) for _ in range(EPOCHS)]
models={};records={}
for mode in MODES:
    model=make_target_model(mode)
    frozen_before={n:p.detach().clone() for n,p in model.named_parameters() if not p.requires_grad}
    optimizer=torch.optim.Adam([p for p in model.parameters() if p.requires_grad],lr=LEARNING_RATE)
    best_ce=float('inf');history=[];start=time.perf_counter()
    for epoch,order in enumerate(orders,1):
        model.train()
        for ids in order.split(BATCH_SIZE):
            optimizer.zero_grad();loss=F.cross_entropy(model(train_x[ids]),train_y[ids]);loss.backward();optimizer.step()
        tr=evaluate_binary(model,train_x,train_y);va=evaluate_binary(model,val_x,val_y)
        history.append({'epoch':epoch,'train_ce':tr['ce'],'val_ce':va['ce'],'val_accuracy':va['accuracy']})
        if va['ce']<best_ce:
            best_ce=va['ce'];best_state=copy.deepcopy(model.state_dict());selected=epoch
    elapsed=time.perf_counter()-start
    model.load_state_dict(best_state)
    for name,param in model.named_parameters():
        if name in frozen_before: assert torch.equal(param.detach(),frozen_before[name]),name
    models[mode]=model
    records[mode]={'selected_epoch':selected,'train':evaluate_binary(model,train_x,train_y),
                   'validation':evaluate_binary(model,val_x,val_y),'seconds':elapsed,'history':history}
fig,axes=plt.subplots(1,2,figsize=(10,3.5),sharey=True)
for mode,r in records.items():
    axes[0].plot([v['epoch'] for v in r['history']],[v['train_ce'] for v in r['history']],label=mode)
    axes[1].plot([v['epoch'] for v in r['history']],[v['val_ce'] for v in r['history']],label=mode)
    chosen=next(v for v in r['history'] if v['epoch']==r['selected_epoch'])
    axes[1].scatter([chosen['epoch']],[chosen['val_ce']],facecolors='none',edgecolors=axes[1].lines[-1].get_color(),s=75,zorder=3)
ymax=max(v[key] for r in records.values() for v in r['history'] for key in ('train_ce','val_ce'))
axes[0].set_ylim(0,max(ymax*1.05,1e-8))
axes[0].set_ylabel('Cross-entropy (same scale)')
axes[0].set_title('training CE');axes[1].set_title('validation CE')
for ax in axes:ax.set_xlabel('epoch');ax.legend()
plt.tight_layout();plt.show()
print(json.dumps({m:{k:v for k,v in r.items() if k!='history'} for m,r in records.items()},indent=2))