我从https://github.com/fadel/pytorch_ema下载并使用torch_ema这个库,在调用ExponentialMovingAverage(EMA,指数滑动平均)时遇到了问题。以下是我的详细代码:
from torch_ema import ExponentialMovingAverage
model = ...
for name, para in model.named_parameters():
if "blocks" in name or "head" in name:
para.requires_grad_(True)
else:
para.requires_grad_(False)
# pg are the parameters to be trained in the model(I freeze some of the parameters of the model during training)
pg = [p for p in model.parameters() if p.requires_grad]
optimizer = optim.SGD(pg, lr=0.01, momentum=0.9, weight_decay=5e-5)
scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=20, eta_min=0)
ema_model = ExponentialMovingAverage(parameters=pg, decay=0.9999)
best_MAE=10
save_path=...
for epoch in range(args.epochs):# train
print('epoch:',epoch,'Current learning rate:', optimizer.param_groups[0]['lr'])
train_loss, train_MAE, tb_writer = train_one_epoch(model=model,
optimizer=optimizer,
data_loader=train_loader,
device=device,
epoch=epoch,
scheduler=scheduler,
csv_filename=args.csv_filename,
tb_writer=tb_writer)
scheduler.step()
ema_model.update()
# validate
with ema_model.average_parameters():
val_loss, val_MAE = evaluate(model=model,data_loader=val_loader,device=device,epoch=epoch)
if val_MAE < best_MAE:
best_MAE=val_MAE
torch.save(ema_model.state_dict(), save_path)
其中,evaluate函数如下所示:
@torch.no_grad()
def evaluate(model, data_loader, device, epoch):
softceloss_function = SoftCrossEntropy()
model.eval()
data_loader = tqdm(data_loader)
for step, data in enumerate(data_loader):
images, names, labels = data
pred = model(images.to(device))
softlabel = softlabel_function(labels) # a function to convert labels to softlabel
loss = softceloss_function(pred, softlabel.to(device))
val_loss,val_MAE = ... # calculate loss and MAE
return val_loss, val_MAE
在训练过程中的每个epoch结束时,我都会在验证集上执行evaluate函数。如果 val_MAE < best_MAE,我会保存模型的checkpoint。经过 20 个 epoch 的训练后,我会选择在验证集上性能最好的模型,去在测试集上进行测试。
结果如下:
如果我不使用 pytorch_ema 软件包,即在不使用 ema_model.average_parameters() 这句代码时执行evaluate函数,epoch 1、2、3 的 val_MAE 分别为 6.185、5.779 和 5.529。
如果我使用上面提供的代码,即
ema_model = ExponentialMovingAverage(parameters=pg,decay=0.9999)
,其中decay设置为 0.9999,则epoch 1、2、3 的值 val_MAE 分别为 6.269、5.878 和 5.548。这证明了 ema 模式的有效性。当我尝试将decay设置为其他值,如 0.999(或任何其他值),即
ema_model = ExponentialMovingAverage(parameters=pg, decay=0.999)
,并重新开始训练时,我发现每轮的验证结果完全一样,epoch 1、2、3 的 val_MAE 还是分别为 6.269、5.878 和 5.548。
总的来说,我有三个问题:
1.我想知道为什么设置不同的 decay 进行训练时,验证结果完全相同。
2.由于 ema_model.state_dict() 与 model.state_dict() 不同,如何保存 ema_model 的 checkpoint 并将其应用于测试集?
3.是否有其他更方便的、兼容torch的,使用EMA功能的方法,如有麻烦提供链接或例程,非常感谢!