1. One of the differentiated Tensors appears to not have been used in the graph
出现原因:出现在使用autograd.grad(loss, x)手动求导时。出现原因一般是loss和x之间没有建立计算图关系,即loss不能由x经过计算得来,所以不能反向传播。
解决办法:检查loss的计算过程是不是用到了x。特别注意如果使用循环迭代计算loss,如Adversarial Training中的PGD,每次迭代的loss是不是用到了上次迭代的变量来计算,而如果你让loss只对此次迭代的中的变量求导就会报这个错。
2. RuntimeError: CUDA error: invalid configuration argument
出现原因:将空tensor传入模型前向传播也会报这个错。
如果在模型前向传播的时候报了这个错,网上有些地方说是因为对input的切片操作引起在gpu上内存不连续所致(如这篇),试图通过将model(x)改为model(x.contiguous())解决。虽然我也使用了对x切片的操作,但我这样搞并不能解决,后来发现是由于切片操作可能存在导致x为空tensor。将空tensor传入模型前向传播也会报这个错。
我的出错代码:
for c in range(self.num_classes): #calculate loss class-wisely
class_index = (y == torch.tensor(c)).nonzero().squeeze(1).cuda() #我的算法逻辑中,class_index可能为空tensor,一开始没想到
# if len(class_index)>0: 加上判断index是否为0就不报错了
worst_ce_loss_conditioned_on_y =F.cross_entropy(self.predict(transfered_x[class_index].contiguous()),
y[class_index].cuda().contiguous(),
reduction='mean')
#改正之前,这句话会报错RuntimeError: CUDA error: invalid configuration argument
ce_loss_conditioned_on_y = F.cross_entropy(self.predict(x[class_index].cuda().contiguous()),
y[class_index].cuda().contiguous(),
reduction='mean')
consis_loss = consis_loss + torch.abs(worst_ce_loss_conditioned_on_y - ce_loss_conditioned_on_y)
3. 多次forward计算而不backward导致显存爆炸
如果多次进行forward计算,而不进行backward,那么前向传播时产生的中间结果会一直积累在gpu中。如果你前向计算时并不希望进行反向传播,那么可以采用如下方式:
output_features=torch.utils.checkpoint.checkpoint(model,x.cuda())
4. 使用transfrom.scale或nn.functional.interpolate时报错ValueError: size shape must match input shape. Input is 2D, size is 4
这是由于transfrom.scale和nn.functional.interpolate在进行图片放缩时,默认要求input必须是[bsz, c, h, w]四维,**且输出的目标必须是[h, w]二维!**如果这样写就会报错:
x=torch.rand(2,5,3,3)
y=torch.nn.functional.interpolate(input=x, size=(2,5,10,10), mode='bilinear')
正确写法:
x=torch.rand(2,5,3,3)
y=torch.nn.functional.interpolate(input=x, size=(10,10), mode='bilinear')
scale函数同理。
5. loss.backward时报错RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
这说明在准备反向传播时发现并没有变量计算了梯度以供反传。
就三种可能:①模型参数设置了requires_grad=False ②假设你希望更新非网络模型参数外的变量(该变量参与计算loss,我们想通过一个optimizer来自动优化该变量),那么有可能该变量设置了requires_grad=False ③你以为的参与loss计算的变量实际上没参与计算
对于第一种情况,可以通过查看模型参数的requires_grad来排查:
for name, param in model.named_parameters():
print(f"{name} requires_grad: {param.requires_grad}")
另外,注意一下,设置model.eval()并不会导致requires_grad变为False。model.eval()只是将dropout设为0、不记录梯度等,并不会明确地将requires_grad变为False。同理,model.train()也并不会导致requires_grad变为True。
【关于这个bug有进一步讨论,见9】
6. RuntimeError: CUDA error: CUBLAS_STATUS_NOT_INITIALIZED when calling cublasCreate(handle)
可能是由于跑ipynb文件时由于前面的加载模型代码运行失败了(比如,一种常见的情况是:模型加载过一遍了,此时已经在gpu上了,但你又运行了一遍加载模型的代码,导致gpu爆炸,第二次加载模型失败),但是你直接跑了后面的用模型来前传的代码,就会报这个错。将notebook kernel restart一下,重新运行即可。
当然,也有可能是因为pytorch版本的问题,这个另说。
7. import pandas时:ImportError: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29’ not found
一个很奇怪的bug,触发条件是在import pandas前面先import了torch相关的库,比如:
import torch
from torch.nn import functional as F
from torch.utils.data import DataLoader
import pandas
将torch相关库改到pandas后面import就没问题了。
8. RuntimeError: CUDA error: device-side assert triggered
错误信息:
RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
原因: 越界
注意点: 有时报错不一定在越界的那一句!!!有可能是在越界的那句之后的某个语句报这个错。需要一点一点排查。
** 一种常见可能**:算cross_entropy loss时有label的id大于预测logit的类别数维度。
9. RuntimeError: element 0 of variables does not require grad and does not have a grad_fn
【关于这个bug的其他讨论,见5】
典型错误。说明计算loss时有个中间变量的requires_grad时False,大多是在反向传播时,即loss.backward()时出现。
可能的错误原因:
首先需要明确,只要前向计算时,**至少存在一个输入给网络的变量requires_grad为True(比如一个模型之外的想要被优化的权重矩阵),那么即使模型freeze了(模型参数requires_grad为False),此时loss也是可以backward的。**出现这个错误说明所有的输入以及网络参数都requires_grad=False了。
解决方案
逐条检查:
- 当网络参数被freeze时,假如一个输给网络的变量需要优化,那么它是不是requires_grad=True;
- 如果是在with torch.no_grad(): 环境下执行的,那么requires_grad自动为False。注意:with torch.no_grad(): 有可能会加在整个函数的定义开始处,作为一个装饰器出现,比较难以发现
- 【极其坑】torch.set_grad_enabled(False)这句话会导致全局自动设置requires_grad为False。在这种情况下,甚至会出现前一句你刚定义了一个w=tensor.randn(10, requires_grad=True),下一行打印w.requires_grad就是False,如果不知道这句话的话非常难debug。
10. ValueError: can’t optimize a non-leaf Tensor
non-leaf Tensor指计算的中间结果对应的变量,而非创建的tensor。如z=x*y,z就是non-leaf Tensor,而x和y时leaf-node。
如果确定z不是non-leaf node但还是报错,可能是由于使用了.to(device):
import torch
import torch.optim as optim
weights = torch.randn(10, requires_grad=True).to("cuda:0")
optimizer = optim.Adam([weights], lr=0.01) #报错
但如果改成
weights = torch.randn(10, requires_grad=True, device=device)
就不报错了。
11. RuntimeError: Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad().
**错误原因:**在一次loss.backward之后计算图已经被释放,如果没有重新前传计算就再次loss.backward,就会报错。
解决方案:
loss.backward(retain_graph=True)