【ERROR】关于训练时以及开发集上loss丝毫不变的原因

记录一次马虎导致的BUG

 

事情起因:

最新在跑项目的代码,一切都好好的,直到我突发奇想加了个新model之后,一切诡异了起来。。。

代码逻辑是每训练一轮会在开发集上测三次,然后log打印每次测出的loss以及PRF指标,在改了model之后,在每一次打印的log中所有的数值都丝毫没有变化。。。

 

出现问题:

训练时以及开发集上loss丝毫不变

这说明了虽然模型每一轮都在训练,但是模型中待学习的参数却丝毫没有得到更新。

 

调试过程:

            print(probs.grad)
            print(targets.grad)
            print("probs:{}".format(probs.requires_grad))
            print("targets:{}".format(targets.requires_grad))
            
            loss = criterion(probs, targets) 
            print("loss:{}".format(loss.requires_grad))

训练时:

None
None
probs:True
targets:False
loss:True

测试时:

None
None
probs:False
targets:False
loss:False

一切正常,其中.grad只有在loss.backward()之后才会计算自己的梯度,并在此后累计梯度,所以默认输出None是正常的

因此可以排除问题出在模型内部的可能性

 

现在来排查函数之外,首先怀疑优化器函数写的不对,几次尝试后,发现问题依然不在这里。。。

 

突然发现一处代码,之前由于模型较大出现out of memory,所以曾经把参数放到CPU去优化,定义获取参数代码如下:

    if args.optimize_on_cpu:
        param_optimizer = [(n, param.clone().detach().to('cpu').requires_grad_()) for n, param in net.named_parameters()]
    else:
        param_optimizer = net.named_parameters()

这样的话在使用优化器更新参数,即optimizer.step(),时,要进行以下三个步骤:

1)对于模型的每一个参数,若该参数有梯度,则把该参数的梯度的值(para_model.grad.data)copy给对应的优化器的参数(若对应的优化器参数的梯度为None则为其赋予梯度);若模型某一参数的梯度为None,则给对应的优化器的参数的grad也复制为None;

2)梯度回传后,进行模型参数的更新;

3)将优化后的优化器的各个参数值copy到模型的各个参数上。

if args.optimize_on_cpu:
    is_nan = set_optimizer_params_grad(param_optimizer, net.named_parameters(), test_nan=True)
    optimizer.step()
    copy_optimizer_params_to_model(net.named_parameters(), param_optimizer)
else:
    optimizer.step()

 

你可能感兴趣的:(ERROR)