PyTorch 数据集应该返回什么?

rwa*_*ace 5 pytorch pytorch-dataloader

我正在尝试让 PyTorch 与 DataLoader 一起使用,据说这是处理小批量的最简单方法,在某些情况下这是获得最佳性能所必需的。

DataLoader 想要一个数据集作为输入。

大多数关于数据集的文档都假设您正在使用现成的标准数据集(例如 MNIST),或者至少使用图像,并且可以使用现有的机器作为黑匣子。我正在处理自己生成的非图像数据。我当前最好的尝试是,将有关如何执行此操作的文档提炼为最小的测试用例:

import torch
from torch import nn
from torch.utils.data import Dataset, DataLoader


class Dataset1(Dataset):
    def __init__(self):
        pass

    def __len__(self):
        return 80

    def __getitem__(self, i):
        # actual data is blank, just to test the mechanics of Dataset
        return [0.0, 0.0, 0.0], 1.0


train_dataloader = DataLoader(Dataset1(), batch_size=8)

for X, y in train_dataloader:
    print(f"X: {X}")
    print(f"y: {y.shape} {y.dtype} {y}")
    break


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(3, 10),
            nn.ReLU(),
            nn.Linear(10, 1),
            nn.Sigmoid(),
        )

    def forward(self, x):
        return self.layers(x)


device = torch.device("cpu")
model = Net().to(device)
criterion = nn.BCELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

for epoch in range(10):
    for X, y in train_dataloader:
        X, y = X.to(device), y.to(device)

        pred = model(X)
        loss = criterion(pred, y)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
Run Code Online (Sandbox Code Playgroud)

上述程序的输出是:

X: [tensor([0., 0., 0., 0., 0., 0., 0., 0.], dtype=torch.float64), tensor([0., 0., 0., 0., 0., 0., 0., 0.], dtype=torch.float64), tensor([0., 0., 0., 0., 0., 0., 0., 0.], dtype=torch.float64)]
y: torch.Size([8]) torch.float64 tensor([1., 1., 1., 1., 1., 1., 1., 1.], dtype=torch.float64)
Traceback (most recent call last):
  File "C:\ml\test_dataloader.py", line 47, in <module>
    X, y = X.to(device), y.to(device)
AttributeError: 'list' object has no attribute 'to'
Run Code Online (Sandbox Code Playgroud)

在我能找到的所有示例代码中,X, y = X.to(device), y.to(device)都成功了,因为X确实是一个张量(而它不在我的版本中)。现在我试图找出到底是什么转换X为张量,因为示例代码例如https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html不这样做,或者我无法理解如何以及它在哪里。

Dataset 本身是否将事物转换为张量?答案似乎是“有点”。

它已转换为张量,即批次中每个示例的值y的列。y这么多,是有道理的,尽管它使用了 float64 类型,而在机器学习中,我们通常更喜欢 float32。我习惯了Python总是以双精度表示标量的想法,因此从双精度到单精度的转换发生在形成张量时,并且可以通过指定参数来确保这一点dtype。但在这种情况下,数据集似乎隐式地形成了张量。有没有地方或方法可以指定dtype参数?

X不是张量,而是张量的列表。如果它是批次中示例的列表,那么它会具有直观意义,但不是一个包含 8 个元素(每个元素包含 3 个元素)的列表,而是相反。因此 Dataset 已经转置了输入数据,如果它正在形成一个张量来匹配 的形状y,那么这是有意义的,但它不是创建单个 2d 张量,而是创建了一个 1d 张量列表。(并且再次采用双精度。)为什么?有办法改变这种行为吗?

到目前为止发布的答案Does pytorch Dataset.__getitem__ has to return a dict? __getitem__可以返回任何东西。好的,但是如何将这些内容转换为训练程序所需的形式呢?

Iva*_*van 4

数据集实例仅负责返回数据集的单个元素,该元素可以采用多种形式: dict list int float 张量等......

但您看到的行为实际上是由 PyTorch 数据加载器处理的,而不是由底层数据集处理的。这种机制称为整理,其实现是由 完成的collate_fn。您实际上可以提供自己的参数作为data.DataLoader. PyTorch 提供了默认的整理功能default_collate,可以处理绝大多数情况。请查看其文档,因为它提供了有关它可以处理的可能用例的见解。

使用此默认整理,返回的批次将采用与数据集中返回的项目相同的类型。因此,您应该返回张量而不是像@dx2-66所解释的列表。