是否有任何一般性建议可以在自定义数据集中有效地处理数据,以便它可以很好地与minibatch eval / train循环一起使用?为了更具体地说明我的意思,假设我定义了将x映射到x + 1的合成玩具数据集:
import torch.utils.data as data
class Dataset(data.Dataset):
def __init__(self):
super(Dataset, self).__init__()
# list of [x, y]
self.dataset = [
[1, 2],
[2, 3],
[3, 4],
[4, 5]
]
def __getitem__(self, index):
item = self.dataset[index]
return item[0], item[1]
def __len__(self):
return len(self.dataset)
实际上,这将被包装在DataLoader中并在eval / train循环中访问,如下所示:
dataset = Dataset()
data_loader = data.DataLoader(dataset=dataset, batch_size=2, shuffle=True)
epochs = 100
for i_epoch in range(epochs):
for i_minibatch, minibatch in enumerate(data_loader):
x, y = minibatch
# predict and train
数据集对象可能返回原始Python对象,如数字或列表,就像在我的示例实现中一样,但在最后一个代码片段的“预测和训练”部分,我们需要一些特定的数据类型来计算内容,比如火炬.FloatTensor(似乎数据加载器可以隐式地执行此操作),甚至可能包装为torch.autograd.Variable,并且可能还需要一些.cuda()调用。我的问题是关于何时进行这些数据转换和函数调用的一般建议。
例如,一个选项是将所有内容保存为数据集内的torch.FloatTensor,在data_loader循环中,我们可以添加Variable包装器并调用.cuda()。我们也可以通过在数据集构造函数或getitem方法中调用.cuda()来获取GPU上的全部或部分数据。我认为所有这些方法可能都有利有弊。如果我正在训练几个时代的模型,我不想在每个时期或小批量迭代中引入不必要的开销,这可以通过预先计算数据集中的内容来避免。可能有更多关于pytorch内部知识的人(可能与某些缓存或jit编译有关)可能会指出更具体的理由选择一种方法而不是另一种方法。
答案 0 :(得分:2)
通常,数据集以更易于存储在磁盘上的格式存储在文件中。加载数据集时,您希望数据类型对PyTorch更友好。这是通过Torchvision库的transformations interface完成的。例如,对于MNIST,以下是标准转换:
datasets.MNIST('../data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
此处ToTensor
将张量中的所有值除以255,这样,如果数据是RGB图像,则张量中的值将为0.0到1.0。
这里的关键是,磁盘上的数据理想情况下应该与您可能想要处理的内容(培训,可视化,计算统计信息等)无关,并且与所使用的框架无关。在加载与您正在做的事情有关的数据之后,您可以应用转换。
我想提到的另一件事是处理非常大的数据集,例如ImageNet。重要的事情很少:
K = C * total_epochs * batch_size
记录,其中C
是您选择的某个常数> =1。然后将K条记录随机排列在内存中,然后将它们分成几批。不幸的是,您现在必须手动执行此操作。答案 1 :(得分:1)
您是否阅读了一些官方示例,例如imagenet train?在这些示例中,它们首先获取数据。正如您所说,数据已被隐式转换为火炬张量。然后,如果你有GPU,将cpu张量转换为GPU张量。最后,将GPU上的普通张量转换为火炬Variable
以使autograd工作。
我认为这是做这些事情的规范和标准方式。至少,我到目前为止看到的所有pytorch代码都是这样做的。如果您想提高速度,可以考虑