之前训练网络时,会先编写学习率随训练epoch的增加而逐渐减低的函数,然后选取一个相对较大的学习率(一般从e-2量级开始),选取一个epoch能够接受的batchsize,如果loss稳定下降较快,则开始训练.从未体验过学习率和batchsize搭配之难.
最近新看了一篇论文ABCNN(有空再细讲),采用开源的tensorflow工程训练一下,效果很好,因工程需要,开始将其移植到pytorch框架下,移植完毕后,关于loss函数遇到不少问题,在此记录.
1.学习率随epoch降低的函数
def adjust_learning_rate(learning_rate, learning_rate_decay, optimizer, epoch):
"""Sets the learning rate to the initial LR multiplied by learning_rate_decay(set 0.98, usually) every epoch"""
learning_rate = learning_rate * (learning_rate_decay ** epoch)
for param_group in optimizer.param_groups:
param_group['lr'] = learning_rate
return learning_rate
2.loss变nan
- 现象:loss进行一次反传后,loss变nan;
- 排查顺序:
- 训练数据(包括label)中有无异常值(nan, inf等);
- 网络中有无除法,确保分母不会出现0, 分母可以加一个eps=1e-8;
- 网络中有无开根号(torch.sqrt), 保证根号下>=0, 我的程序即是由此引起的(未保证不出现0或者极小正值的情况),解决也是加一个eps=1e-8.
3.loss不收敛
此处包含两种情况,一种是loss一直在震荡,一种是loss下降一点后不再下降到理想水平,而验证集上的表现保持不变.
1.保持需要的batchsize不变;
2.查看是否有梯度回传,查看代码如下:
for name, parms in model.named_parameters():
print('-->name:', name, '-->grad_requirs:', parms.requires_grad, '--weight', torch.mean(parms.data), ' -->grad_value:', torch.mean(parms.grad))
3.查看数据是否有问题,如标签错乱等现象;
4.调节学习率,从大向小调,建议每次除以5;我的项目即是因为学习率过大过小都不收敛引起的;
5.如果学习率调好后,需要调节batchsize大小,如batchsize调大2倍,则将学习率对应调大(项目测试调大2~3倍OK),反之,学习率对应调小