【问题标题】:Using a generator with pickled data in a Dataloader for PyTorch在 PyTorch 的 Dataloader 中使用带有腌制数据的生成器
【发布时间】:2019-07-04 09:49:48
【问题描述】:

我之前做过一些预处理和特征选择,并且我有一个包含列表列表的泡菜训练输入数据,例如(但腌制)

[[1,5,45,13], [23,256,4,2], [1,12,88,78], [-1]]
[[12,45,77,325], [23,257,5,28], [3,7,48,178], [12,77,89,99]]
[[13,22,78,89], [12,33,97], [-1], [-1]]

[-1] 是一个填充标记,但我认为这并不重要。

因为文件有很多千兆字节,我希望节省内存并使用生成器逐行读取泡菜(逐个列表)。我已经找到了this answer 这可能会有所帮助。如下所示:

def yield_from_pickle(pfin):
    with open(pfin, 'rb') as fhin:
        while True:
            try:
                yield pickle.load(fhin)
            except EOFError:
                break

接下来,我希望在 PyTorch (1.0.1) Dataloader 中使用这些数据。从我在其他答案中找到的内容来看,我必须为它提供一个Dataset,您可以对其进行子集化,但它必须包含__len____getitem__。它可能是这样的:

class TextDataset(Dataset):
    def __init__(self, pfin):
        self.pfin = pfin

    def __len__(self):
        # memory-lenient way but exhaust generator?
        return sum(1 for _ in self.yield_from_pickle())

    def __getitem__(self, index):
        # ???
        pass

    def yield_from_pickle(self):
        with open(self.pfin, 'rb') as fhin:
            while True:
                try:
                    yield pickle.load(fhin)
                except EOFError:
                    break

但我完全不确定这是否可能。如何以合理的方式实现__len____getitem__?我不认为我对 __len__ 所做的事情是一个好主意,因为这会耗尽生成器,而且我完全不知道如何在保留生成器的同时安全地实现 __getitem__

有没有更好的方法?总而言之,我想构建一个可以馈送到 PyTorch 的 Dataloader 的数据集(因为它的多处理能力),但以一种内存高效的方式,我不必将整个文件读入内存。

【问题讨论】:

    标签: python dataset generator pickle pytorch


    【解决方案1】:

    请参阅my other answer 了解您的选择。

    简而言之,您需要将每个样本预处理成单独的文件,或者使用不需要完全加载到内存中进行读取的数据格式。

    【讨论】:

      猜你喜欢
      • 2019-04-27
      • 2021-07-09
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      • 2020-08-26
      • 2020-07-05
      • 1970-01-01
      • 2014-11-18
      相关资源
      最近更新 更多