当前位置: 首页 > 知识库问答 >
问题:

实现“无限循环”数据集

任小云
2023-03-14

我想实现一个无限循环数据集

class Infinite(Dataset):
    def __len__(self):
        return HPARAMS.batch_size
#         return 1<<30 # This causes huge memory usage.
    def __getitem__(self, idx):
        """Randomly generates one new example."""
        return sample_func_to_be_parallelized()

infinite_loader = DataLoader(
    dataset=Infinite(), 
    batch_size=HPARAMS.batch_size, 
    num_workers=16,
    worker_init_fn=lambda worker_id: np.random.seed(worker_id),  
)

while True:
    for idx, data in enumerate(infinite_loader):
        # forward + backward on "data"

如您所见,这里的主要挑战是\uu len()\uu方法。如果我在那里放一个足够大的数字,比如1

如果我在那里放一个小数字,比如1或BATCH_SIZE,训练循环中采样的“数据”将定期重复。这不是我想要的,因为我想产生新的数据

我猜过度使用内存的罪魁祸首是堆栈中的某个地方,缓存了一堆东西。随便看看Python的一面,我就不知道在哪里了。

有人能告诉我什么是实现我想要的最好的方法吗?(使用DataLoader的并行加载,同时确保加载的每个批都是全新的。)

共有3个答案

乜心思
2023-03-14

尝试使用itertools中的cycle。以下是简单数据集的示例:

代码

from itertools import cycle

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


# Create some dummy data.
data = torch.tensor([[0, 0],
                     [1, 1],
                     [2, 2],
                     [3, 3]])


class DataSet(Dataset):
    """Our dataset. Iterates over tensor data"""

    def __init__(self, data):
        self.data = data
        self.n = self.data.shape[0]

    def __len__(self):
        return self.n

    def __getitem__(self, idx):
        return self.data[idx]


bs = 1  # batch size
workers = 1  # number of workers

dataset = DataSet(data)
data_loader = DataLoader(dataset, batch_size=bs, shuffle=False, num_workers=workers)

# Infinite loop.
print(f'batch size: {bs} | number of workers: {workers}')
for i, data in cycle(enumerate(data_loader)):
    print(i, data)

输出:

batch size: 1 | number of workers: 1
0 tensor([[0, 0]])
1 tensor([[1, 1]])
2 tensor([[2, 2]])
3 tensor([[3, 3]])
0 tensor([[0, 0]])
1 tensor([[1, 1]])
2 tensor([[2, 2]])
3 tensor([[3, 3]])
...
batch size: 2 | number of workers: 2
0 tensor([[0, 0],
        [1, 1]])
1 tensor([[2, 2],
        [3, 3]])
0 tensor([[0, 0],
        [1, 1]])
1 tensor([[2, 2],
...
谢铭
2023-03-14

DataLoader在不替换数据集的情况下对数据集进行采样。为此,它生成一个介于0和len(数据集)之间的随机索引排列。我猜这种排列方式消耗了你大部分的记忆。我认为PyTorch API不支持无限集合,但您可以尝试在DataLoader中分叉代码,然后自己动手。您可以使用batch_sampler参数,并传入一个基于RandomSampler实现的自定义变量。这将允许您保留DataLoader的并行加载部分。

也就是说,基于\uu len\uu\uu getitem\uu的迭代协议不适合无限集合。您最好重新实现数据集__len_uu只返回您的数据集1__getitem__;始终返回一个新样本,而不管索引如何,然后从此数据集中使用替换项对n次进行采样。从技术上讲,它将为第0个样本询问n次,但由于您重写\uuu getitem\uuuu以返回不同的样本,这将有效地满足您的要求。

农英杰
2023-03-14

这似乎在不定期复制数据的情况下起作用:

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

BATCH_SIZE = 2

class Infinite(Dataset):

    def __len__(self):
        return BATCH_SIZE

    def __getitem__(self, idx):
        return torch.randint(0, 10, (3,))


data_loader = DataLoader(Infinite(), batch_size=BATCH_SIZE, num_workers=16)

batch_count = 0
while True:
    batch_count += 1
    print(f'Batch {batch_count}:')

    data = next(iter(data_loader))
    print(data)
    # forward + backward on "data"  

    if batch_count == 5:
        break

结果:

Batch 1:
tensor([[4, 7, 7],
        [0, 8, 0]])
Batch 2:
tensor([[6, 8, 6],
        [2, 6, 7]])
Batch 3:
tensor([[6, 6, 2],
        [8, 7, 0]])
Batch 4:
tensor([[9, 4, 8],
        [2, 4, 1]])
Batch 5:
tensor([[9, 6, 1],
        [2, 7, 5]])

所以我认为问题出在你的函数sample_func_to_be_parallelized()

编辑:If而不是火炬。randint(0,10,(3,)I使用np。随机的randint(10,size=3)\uuuuGetItem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu中(作为sample\u func\u to\u be\u parallellelized()的一个示例),那么每个批次的数据确实是重复的。看看这个问题。

因此,如果您在示例\u func\u to\u be\u parallelized()中的某个地方使用numpy的RGN,那么解决方法是使用

worker_init_fn=lambda worker_id: np.random.seed(np.random.get_state()[1][0] + worker_id) 

并通过np重置种子。随机的seed()在每次调用data=next(iter(数据加载器))之前。

 类似资料:
  • 问题内容: 我正在使用JDBC,需要不断检查数据库是否有更改值。 我目前拥有的是无限循环运行,内部循环迭代更改的值以及针对数据库的每次迭代。 我认为这不是最好的方法。 我在想的另一种方法是反向操作,以保持对数据库的迭代。 更新 感谢您提供有关计时器的反馈,但我认为它不能解决我的问题。一旦数据库中发生更改,我需要立即针对更改的值(示例代码中的“ el”)处理结果。 即使数据库没有更改,它仍然必须不断

  • 本文向大家介绍Android ViewPager实现无限循环的实例,包括了Android ViewPager实现无限循环的实例的使用技巧和注意事项,需要的朋友参考一下 Android ViewPager实现无限循环的实例 ViewPager自身并不支持左右无限循环的功能,这里就提供一种方案让Android ViewPager实现左右无限循环的功能,这里记录下: 用于显示的mViews,比数据源mL

  • 本文向大家介绍Android ViewPager实现无限循环效果,包括了Android ViewPager实现无限循环效果的使用技巧和注意事项,需要的朋友参考一下 最近项目里有用到ViewPager来做广告运营位展示,看到现在很多APP的广告运营位都是无限循环的,所以就研究了一下这个功能的实现。 先看看效果 从一个方向上一直滑动,么有滑到尽头的感觉,具体是怎么实现的呢?看下面的思路。 实现思路 此

  • 本文向大家介绍Objective-C实现无限循环轮播器,包括了Objective-C实现无限循环轮播器的使用技巧和注意事项,需要的朋友参考一下 先看看效果图: 具体实现代码: 1. 控制器     2. 显示内容界面设置 以上就是本文的全部内容,希望对大家的学习有所帮助。

  • 本文向大家介绍Android实现ViewPager无限循环效果(二),包括了Android实现ViewPager无限循环效果(二)的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android实现ViewPager无限循环效果的第二种方式,供大家参考,具体内容如下 原理:在Adapter中将getCount设置为无限大 代码: act_loopviewpager.xml 以上就是本文

  • 本文向大家介绍Android实现ViewPager无限循环效果(一),包括了Android实现ViewPager无限循环效果(一)的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android实现ViewPager无限循环的具体代码,供大家参考,具体内容如下 方式一: 实现原理: 假设有3张图片,分别是1,2,3,那么就创建5张图片,这5张图片的顺序为:3,1,2,3,1,其中1,2