音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

PyTorch 编写代码遇到的问题及解决方案
日期:2021-09-08 14:34:02   来源:脚本之家

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)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程