pytorch中的分布式顺序窗口数据



在我训练的每个epoch,我需要将我的数据集分成t个连续样本的n个批次。例如,如果我的数据是[1,2,3,4,5,6,7,8,9,10],n = 2t = 3,那么有效批次将是

[1-2-3, 4-5-6] and [7-8-9, 10-1-2]
[2-3-4, 8-9-10] and [5-6-7, 1-2-3]

我的旧版本如下,但它采样数据中的每个点,这意味着我将每个epoch解析整个数据集t次。

train_dataset = list(range(n))
train_sampler = None
if distributed:
train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)
train_loader = torch.utils.data.DataLoader(
train_dataset, batch_size=bsize, shuffle=(train_sampler is None),
pin_memory=True, sampler=train_sampler)
for epoch in range(epochs):
if distributed: 
train_sampler.set_epoch(epoch)
for starting_i in train_loader:
batch = np.array([np.mod(np.arange(i, i + t), n) for i in starting_i])

我现在已经实现了我自己的抽样函数,将数据分成随机批次,每个样本都远离最接近的两个确切的t。在非分布式场景中,我可以执行

for epoch in range(epochs):
pad = np.random.randint(n)
train_loader = np.mod(np.arange(pad, n + pad, t), n)
np.random.shuffle(train_loader)
train_loader = np.array_split(train_loader,
np.ceil(len(train_loader) / bsize))
for starting_i in train_loader:
batch = np.array([np.mod(np.arange(i, i + t), n) for i in starting_i])

如何发布这个版本?我需要自定义torch.nn.parallel.DistributedDataParalleltorch.utils.data.DataLoader吗?

我已经检查了DistributedSampler类我的猜测是,我必须重写__iter__方法。我说的对吗?
DistributedSampler如何分割数据集?它是顺序在num_replicas?比如num_replicas = 2。我的数据集是否会在两个工人之间分割为[1,2,3,4,5][6,7,8,9,10]?还是随机的?像[1,4,7,3,10][2,9,5,8,6]一样?第一种情况对我来说是可以的,因为保持样本顺序,但第二种情况就不行了。

我最终制作了自己的Dataset,其中数据是[t, t + window, ... t + n * window]。每次调用它时,它都会随机化窗口的起始索引。然后采样器像往常一样进行洗牌。为了重现性,它具有类似于采样器set_epochset_seed方法。

class SequentialWindowedDataset(Dataset):
def __init__(self, size, window):
self.size = size
self.window = window
self.seed = 0
self.data = np.arange(0, self.size, self.window)
def __getitem__(self, index):
rng = np.random.default_rng(self.seed)
pad = rng.integers(0, self.size)
data = (self.data + pad) % self.size
return data[index]
def __len__(self):
return len(self.data)
def set_seed(self, seed):
self.seed = seed

下面的版本在调用之外随机化数据,它要快得多。

class SequentialWindowedDataset(Dataset):
def __init__(self, size, window):
self.size = size
self.window = window
self.data = np.arange(0, self.size, self.window)
def __getitem__(self, index):
return self.data[index]
def __len__(self):
return len(self.data)
def randomize(self, seed):
rng = np.random.default_rng(seed)
pad = rng.integers(0, self.size)
self.data = (self.data + pad) % self.size

最新更新