PyTorch编写代码常见错误提示有哪些?怎样解决?
发布时间:2022-03-12 13:44:58 所属栏目:语言 来源:互联网
导读:PyTorch是一个开源的Python机器学习库,很多新手在PyTorch编写代码过程中,会遇到多种问题。对此下面小编就介绍一些常见的错误提示以及解方法,希望对大家学习PyTorch有帮助。 PyTorch编写代码遇到的问题 错误提示:no module named xxx xxx为自定义文件夹的
PyTorch是一个开源的Python机器学习库,很多新手在PyTorch编写代码过程中,会遇到多种问题。对此下面小编就介绍一些常见的错误提示以及解方法,希望对大家学习PyTorch有帮助。 PyTorch编写代码遇到的问题 错误提示:no module named xxx xxx为自定义文件夹的名字 因为搜索不到,所以将当前路径加入到包的搜索目录 解决方法: import sys sys.path.append('..') #将上层目录加入到搜索路径中 sys.path.append('/home/xxx') # 绝对路径 import os sys.path.append(os.getcwd()) # #将当前工作路径加入到搜索路径中 还可以在当前终端的命令行设置 export PYTHONPATH=$PYTHONPATH:./ 错误提示:AttributeError: ‘NoneType' object has no attribute ‘shape' height, width, channel = img.shape 在Linux系统下img.shape报错AttributeError: ‘NoneType' object has no attribute ‘shape' img=cv2.imread(),读取一张图片时,img.shape是包含三个量的元组,分别是: img.shape[0]:图像的高度 img.shape[1]:图像的宽度 img.shape[2]:图像的通道数 解决方法:读的文件出错 或者查看文件路径是否正确 错误提示 :TypeError: slice indices must be integers or None or have an index method cropped_im = img[ny1 : ny2, nx1 : nx2, :] 解决方法:需要将ny1 : ny2, nx1 : nx2转换成int类型 错误提示 :Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same 以下三小段分别是Data type CPU tensor GPU tensor 32-bit floating point torch.FloatTensor torch.cuda.FloatTensor 64-bit floating point torch.DoubleTensor torch.cuda.DoubleTensor 出错在类型转换 np.float更改为np.float32 import torchvision.transforms as transforms import numpy as np transform = transforms.ToTensor() def convert_image_to_tensor(image): """convert an image to pytorch tensor image: numpy array , h * w * c image_tensor: pytorch.FloatTensor, c * h * w """ image = image.astype(np.float32) return transform(image) 错误提示:RuntimeError: zero-dimensional tensor (at position 0) cannot be concatenated 版本问题 旧式写法 import torch x = torch.tensor(0.1) y = torch.tensor(0.2) z = torch.cat((x, y)) 改成新式写法 x = torch.tensor([0.1]) y = torch.tensor([0.2]) z = torch.cat((x, y)) print(z) 结果 tensor([0.1000, 0.2000]) 错误提示:TypeError: ‘float' object is not subscriptable 多了下标 a = x.tolist()[0] 去除下标 a = x.tolist() 错误提示:argument ‘input' (position 1) must be Tensor, not list 需要将list转换成tensor 假设a是list torch.tensor(a) GPU模型和CPU模型之间的转换 假设原来保存的是GPU模型,要转换为CPU模型 torch.save(model, os.path.join( "./complete.pth")) cpu_model = torch.load("./complete.pth", map_location=lambda storage, loc: storage) dummy_input = torch.randn(1, 3, 224, 224) 假设原来保存的是CPU模型,要转换为GPU模型 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") torch.save(model, os.path.join( "./complete.pth")) gpu_model = torch.load("./complete.pth", map_location=lambda storage, loc: storage.cuda) dummy_input = torch.randn(1, 3, 224, 224) dummy_input = dummy_input.to(device) 错误提示 RuntimeError: Subtraction, the - operator, with a bool tensor is not supported. If you are trying to invert a mask, use the ~ or logical_not() operator instead. 原代码 # Store only unsuppressed boxes for this class image_boxes.append(class_decoded_locs[1 - suppress]) image_labels.append(torch.LongTensor((1 - suppress).sum().item() * [c]).to(device)) image_scores.append(class_scores[1 - suppress]) 更改为 image_boxes.append(class_decoded_locs[~suppress]) image_labels.append(torch.LongTensor((~ suppress).sum().item() * [c]).to(device)) image_scores.append(class_scores[~suppress]) 错误提示 RuntimeError: Expected object of scalar type Byte but got scalar type Bool for argument #2 ‘other' in call to _th_max 原代码 suppress = torch.zeros((n_above_min_score), dtype=torch.uint8).to(device) 更改为 suppress = torch.zeros((n_above_min_score), dtype=torch.bool).to(device) UserWarning: volatile was removed and now has no effect. Use with torch.no_grad(): instead. #之前旧版本 ... x = Variable(torch.randn(1), volatile=True) return x #新版 with torch.no_grad(): ... x = torch.randn(1) return x 错误提示 RuntimeError: Attempting to deserialize object on CUDA device 1 but torch.cuda.device_count() is 1. Please use torch.load with map_location to map your storages to an existing device. 或者是 RuntimeError: expected device cuda:0 but got device cuda:1 错误原因之一 使用了CUDA 1显卡训练保存的模型文件,使用CUDA 0验证 代码中写了 device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”) 可以在命令行设置让哪些GPU可见 export CUDA_VISIBLE_DEVICES=1 #GPU编号 export CUDA_VISIBLE_DEVICES=0,1,2,3#4张显卡可见 也可以在代码里改成 checkpoint = torch.load(checkpoint,map_location=‘cuda:0') 错误提示 raise ConnectionError(e, request=request) requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8097): Max retries exceeded with url: /update (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f3111915e80>: Failed to establish a new connection: [Errno 111] Connection refused',)) Exception in user code: 解决方案 因为没有启动visdom可视化程序,所有报错 在终端执行命令 visdom之后就能看到如下信息 Checking for scripts. It's Alive! INFO:root:Application Started You can navigate to http://localhost:8097 nn.Module.cuda() 和 Tensor.cuda() 无论是对于模型还是数据,cuda() 都能实现从CPU到GPU的内存迁移,但是他们的作用效果有所不同。 Model: model = model.cuda() model.cuda() 上面两句能够达到一样的效果,即对model自身进行的内存迁移 Tensor: model = Model() tensor = torch.zeros([2, 3, 10, 10]) model.cuda() tensor.cuda() tensor_cuda = tensor.cuda() model(tensor) # 会报错 model(tensor_cuda) # 正常运行 和 nn.Module 不同,调用 tensor.cuda 只是返回这个 tensor 对象在 GPU 内存上的拷贝,而不会对自身进行改变。因此必须对 tensor 进行重新赋值,即 tensor = tensor.cuda() PyTorch 0.4 计算累积损失的不同 以广泛使用的模式 total_loss += loss.data[0] 为例。Python0.4.0 之前,loss 是一个封装了 (1,) 张量的 Variable,但 Python0.4.0 的 loss 现在是一个零维的标量。对标量进行 索引是没有意义的(似乎会报 invalid index to scalar variable 的错误)。使用 loss.item() 可以从标量中获取 Python 数字。所以改为: total_loss = total_loss + loss.item() 如果在累加损失时未将其转换为 Python 数字,则可能出现程序内存使用量增加的情况。这是因为上面表达式的右侧原本是一个 Python 浮点数,而它现在是一个零维张量。因此,总损失累加了张量和它们的梯度历史,这可能会产生很大的 autograd 图,耗费内存和计算资源。 自适应 CPU 和 GPU设备的 trick device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = Model().to(device) total_loss = 0 for input, target in train_loader: input, target = input.to(device), target.to(device) ... total_loss = total_loss + loss.item() with torch.no_grad(): for input, target in test_loader: ... torch.Tensor.detach的使用 官方说明:Returns a new Tensor, detached from the current graph,The result will never require gradient 假设有模型 A 和模型 B,我们需要将 A 的输出作为 B 的输入,但训练时我们只训练模型 B. 那么可以这样做: input_B = output_A.detach 它可以使两个计算图的梯度传递断开,从而实现我们所需的功能。 pytorch中loss函数的参数设置 以CrossEntropyLoss为例: CrossEntropyLoss(self, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean') 若 reduce = False,那么 size_average 参数失效,直接返回向量形式的 loss,即batch中每个元素对应的loss. 若 reduce = True,那么 loss 返回的是标量: 如果 size_average = True,返回 loss.mean. 如果 size_average = False,返回 loss.sum. weight : 输入一个1D的权值向量,为各个类别的loss加权,如下公式所示: ignore_index : 选择要忽视的目标值,使其对输入梯度不作贡献。如果 size_average = True,那么只计算不被忽视的目标的loss的均值。 reduction : 可选的参数有:‘none' | ‘elementwise_mean' | ‘sum', 正如参数的字面意思。 多GPU的处理机制 使用多GPU时,应该记住 PyTorch 的处理逻辑是: 在各个GPU上初始化模型。 前向传播时,把batch分配到各个GPU上进行计算。 得到的输出在主GPU上进行汇总,计算loss并反向传播,更新主GPU上的权值。 把主GPU上的模型复制到其它GPU上。 训练时损失出现nan的问题 训练模型时出现损失为 nan 的情况 可能导致梯度出现 nan 的三个原因: 梯度爆炸。也就是说梯度数值超出范围变成 nan. 通常可以调小学习率、加 BN 层或者做梯度裁剪来试试看有没有解决。 损失函数或者网络设计。比方说,出现了除 0,或者出现一些边界情况导致函数不可导,比方说log(0)、sqrt(0). 脏数据。可以事先对输入数据进行判断看看是否存在 nan. 补充一下nan数据的判断方法: 注意!像 nan 或者 inf 这样的数值不能使用 == 或者 is 来判断!为了安全起见统一使用 math.isnan 或者 numpy.isnan 吧。 import numpy as np if np.any(np.isnan(input.cpu().numpy())): print("Input data has NaN!") if(np.isnan(loss.item())): print("Loss value is NaN!") pytorch 内存泄漏 torch.as_tensor(data, dtype=None,device=None)->Tensor : 为data生成tensor。 如果data已经是tensor,且dtype和device与参数相同,则生成的tensor会和data共享内存。如果data是ndarray,且dtype对应,devices为cpu,则同样共享内存。其他情况则不共享内存。 import torch import numpy a = numpy.array([1, 2, 3]) t = torch.as_tensor(a) (编辑:安阳站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |