【问题标题】:How to load a list of numpy arrays to pytorch dataset loader?如何将 numpy 数组列表加载到 pytorch 数据集加载器?
【发布时间】:2017-11-09 18:48:43
【问题描述】:

我有一个庞大的 numpy 数组列表,其中每个数组代表一个图像,我想使用 torch.utils.data.Dataloader 对象加载它。但是 torch.utils.data.Dataloader 的文档提到它直接从文件夹加载数据。我如何为我的原因修改它?我是 pytorch 的新手,任何帮助将不胜感激。 我的单个图像的 numpy 数组看起来像这样。图片为RBG图片。

[[[ 70  82  94]
  [ 67  81  93]
  [ 66  82  94]
  ..., 
  [182 182 188]
  [183 183 189]
  [188 186 192]]

 [[ 66  80  92]
  [ 62  78  91]
  [ 64  79  95]
  ..., 
  [176 176 182]
  [178 178 184]
  [180 180 186]]

 [[ 62  82  93]
  [ 62  81  96]
  [ 65  80  99]
  ..., 
  [169 172 177]
  [173 173 179]
  [172 172 178]]

 ..., 

【问题讨论】:

    标签: python numpy pytorch


    【解决方案1】:

    我认为 DataLoader 实际需要的是子类Dataset 的输入。您可以编写自己的数据集类来继承 Dataset 或使用 TensorDataset,如下所示:

    import torch
    import numpy as np
    from torch.utils.data import TensorDataset, DataLoader
    
    my_x = [np.array([[1.0,2],[3,4]]),np.array([[5.,6],[7,8]])] # a list of numpy arrays
    my_y = [np.array([4.]), np.array([2.])] # another list of numpy arrays (targets)
    
    tensor_x = torch.Tensor(my_x) # transform to torch tensor
    tensor_y = torch.Tensor(my_y)
    
    my_dataset = TensorDataset(tensor_x,tensor_y) # create your datset
    my_dataloader = DataLoader(my_dataset) # create your dataloader
    

    为我工作。希望对你有帮助。

    【讨论】:

    • 如果有内存限制,有没有办法复制这个?我发现自己在 torch.stack 步骤中的内存不足。
    • @Indrajit,当然,不要使用 TensorDataset,只需定义您自己的 Dataset 类,该类从文件加载一个 numpy 数组。
    • 您不需要将toch.stack 与列表理解一起使用。相反,您可以直接使用torch.Tensor(my_x)torch.Tensor(my_y)
    • @mbpaulus 我可以批量加载numpy数组吗?这对内存问题有很大帮助。
    【解决方案2】:

    由于您有图像,您可能希望对它们执行转换。所以TensorDataset 不是这里的最佳选择。相反,您可以创建自己的Dataset。像这样的:

    import torch
    from torchvision import transforms
    from torch.utils.data import Dataset, DataLoader
    import numpy as np
    from PIL import Image
    
    
    class MyDataset(Dataset):
        def __init__(self, data, targets, transform=None):
            self.data = data
            self.targets = torch.LongTensor(targets)
            self.transform = transform
            
        def __getitem__(self, index):
            x = self.data[index]
            y = self.targets[index]
            
            if self.transform:
                x = Image.fromarray(self.data[index].astype(np.uint8).transpose(1,2,0))
                x = self.transform(x)
            
            return x, y
        
        def __len__(self):
            return len(self.data)
    
    # Let's create 10 RGB images of size 128x128 and 10 labels {0, 1}
    data = list(np.random.randint(0, 255, size=(10, 3, 128, 128)))
    targets = list(np.random.randint(2, size=(10)))
    
    transform = transforms.Compose([transforms.Resize(64), transforms.ToTensor()])
    dataset = MyDataset(data, targets, transform=transform)
    dataloader = DataLoader(dataset, batch_size=5)
    

    【讨论】:

    • transformstransform = transforms.Compose(...) 行中来自哪里?
    • @AdamMurphy 它来自torchvisionpytorch.org/vision/stable/transforms.html 我通过在导入它的代码中添加一行来修复答案。
    • 在转换之前必须将 numpy 数组转换为 PIL 图像,这有点令人难过。
    【解决方案3】:

    PyTorch DataLoader 需要 DataSet,因为您可以查看 docs。正确的做法是使用:

    torch.utils.data.TensorDataset(*tensors)
    

    这是一个用于包装张量的数据集,其中每个样本将通过沿第一维索引张量来检索。 参数*tensors 表示与第一维大小相同的张量。

    另一个class torch.utils.data.Dataset是一个抽象类。

    下面是如何将 numpy 数组转换为张量:

    import torch
    import numpy as np
    n = np.arange(10)
    print(n) #[0 1 2 3 4 5 6 7 8 9]
    t1 = torch.Tensor(n)  # as torch.float32
    print(t1) #tensor([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
    t2 = torch.from_numpy(n)  # as torch.int32
    print(t2) #tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=torch.int32)
    

    接受的答案使用torch.Tensor 构造。 如果你有一个像素为 0-255 的图像,你可以使用这个:

    timg = torch.from_numpy(img).float()
    

    或 torchvision to_tensor 方法,将 PIL 图像或 numpy.ndarray 转换为张量。


    但是这里有一个小技巧,你可以直接放置你的 numpy 数组。

    x1 = np.array([1,2,3])
    d1 = DataLoader( x1, batch_size=3)
    

    这也有效,但如果你打印 d1.dataset 类型:

    print(type(d1.dataset)) # <class 'numpy.ndarray'>
    

    虽然我们实际上需要张量来使用 CUDA,所以最好使用张量来提供 DataLoader

    【讨论】:

    • 您好,DataLoader 的输入,np.arraytensor 有什么区别?我发现如果输入x1 如果np.arrayDataLoader 仍然会输出tensor,所以我认为使用np.array 数据来馈送DataLoader 与使用tensor 数据相同。
    • 效果是一样的。唯一的区别是我们有一个转换,以防我们提供 numpy 数组。
    猜你喜欢
    • 2021-03-27
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 2020-10-09
    • 1970-01-01
    • 2020-12-14
    相关资源
    最近更新 更多