Pytorch中DataLoader输出类型问题--“ RuntimeError: Input type (double) and bias type (float) should be the“

引言

Pytorch中DataLoader输出精度问题–“ RuntimeError: Input type (double) and bias type (float) should be the same"和“RuntimeError: expected scalar type Double but found Float”来源很简单,在使用DataLoader进行数据集读取后,得到的Batch数据通过神经网络报错RuntimeError: expected scalar type Double but found Float,经查看是因为Pytorch中神经网络的参数默认精度是torch.float32,而送入的测试数据精度是torch.float64导致报错。但实际上笔者并没有显式对输入数据的精度进行调整,只是在Dataset构造时从本地读取了文件,再以此构建了DataLoader类,因此进行了一番排错。经实验发现,这算是Pytoch DataLoader的考虑不周。

代码环境复现

 首先我们本地存特征和标签:

from torch import nn
import numpy as np
from torch.utils.data import DataLoader,Dataset

X=np.random.rand(10,3,8,8)
import os
os.makedirs('./test')
np.save(X,'./test/feature.npy')
y=np.random.randint(2,size=(8,))
np.save('./test/label.npy',y)

然后构建相应的DataLoader:

class CustomData(Dataset):
    def __init__(self, data_path, label_path, transform=None):
        super(CustomData,self).__init__()
        self.feature = np.load(data_path)
        self.label = np.load(label_path)
        self.transform = transform
    def __len__(self):
        return self.feature.shape[0]
    def __getitem__(self, item):
        X = self.feature[item]
        y = self.label[item]
        if self.transform:
            X = self.transform(X)
        return X, y
cusData=CustomData('./test/feature.npy','./test/label.npy')
cusDataLoader=DataLoader(cusData)

再抽取一个batch送入模型验证:

model=nn.Conv2d(3,6,3,1,1)
sample=next(iter(cusDataLoader))
res=model(sample[0])

可以看到这时候就会报错:
RuntimeError: Input type (double) and bias type (float) should be the same
如果使用的不是conv2d函数而是直接初始化了Paramter和输入进行相乘,则会发生类似的报错:
“RuntimeError: expected scalar type Double but found Float”

原因

 实际上这是因为在DataLoader的输出过程中会自动的对Dataset的item值进行张量转换,把数据的格式由np.array转为torch.Tensor,但这一过程存在着缺陷–即它保持了原有的数据精度不变。如果原来np.array的精度为了float64,转换完成后还是float64,也就与神经网络的默认精度不兼容了。输出前述案例的数据dtype如下:

print(sample[0].dtype)
torch.float64
print(X.dtype)
float64
print(model.weight.dtype)
torch.float32

解决方案如下:

1. Dataset 处理

 由于这一Tensor的准换或者说排查过程是在DataLoader类构造时出现的,那么我们在Dataset构造时提前解决精度问题即可。手动对输入数据进行张量化:torch.Tensor(X)默认返回float32精度数据;也可以直接调整np.array精度.
即在Dataset里修改:

class CustomData(Dataset):
    def __init__(self, data_path, label_path, transform=None):
        super(CustomData,self).__init__()
        self.feature = np.load(data_path)
        self.label = np.load(label_path)
        self.transform = transform
    def __len__(self):
        return self.feature.shape[0]
    def __getitem__(self, item):
        X = self.feature[item]
        y = self.label[item]
        if self.transform:
            X = self.transform(X)
        return torch.Tensor(X), y

2. DataLoader处理

 也可以在读取batch的时候进行修改,添加额外的处理函数来对数据格式进行检查和转换:

    def _prepare_batch(batch, device=None, non_blocking=False):
        """
        对dataloader每个batch的输出进行进一步的处理
        :param batch: dataloader输出
        :param device:
        :param non_blocking:
        :return:
        """
        device = "cuda:" + str(device)
        x,y = batch
        x=x.float()
        y=y.float().view(-1,1)
        return x,y
        
 x,y=_prepare_batch((sample[0],sample[1]))
 res=model(x)

参考文献

DataLoader does not consider default floating point type

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值