Pytorch Dataloader 如何处理可变大小的数据?
How does Pytorch Dataloader handle variable size data?
我有一个如下所示的数据集。那就是第一项是用户 ID,然后是用户单击的项目集。
0 24104 27359 6684
0 24104 27359
1 16742 31529 31485
1 16742 31529
2 6579 19316 13091 7181 6579 19316 13091
2 6579 19316 13091 7181 6579 19316
2 6579 19316 13091 7181 6579 19316 13091 6579
2 6579 19316 13091 7181 6579
4 19577 21608
4 19577 21608
4 19577 21608 18373
5 3541 9529
5 3541 9529
6 6832 19218 14144
6 6832 19218
7 9751 23424 25067 12606 26245 23083 12606
我定义了一个自定义数据集来处理我的点击日志数据。
import torch.utils.data as data
class ClickLogDataset(data.Dataset):
def __init__(self, data_path):
self.data_path = data_path
self.uids = []
self.streams = []
with open(self.data_path, 'r') as fdata:
for row in fdata:
row = row.strip('\n').split('\t')
self.uids.append(int(row[0]))
self.streams.append(list(map(int, row[1:])))
def __len__(self):
return len(self.uids)
def __getitem__(self, idx):
uid, stream = self.uids[idx], self.streams[idx]
return uid, stream
然后我使用 DataLoader 从数据中检索小批量进行训练。
from torch.utils.data.dataloader import DataLoader
clicklog_dataset = ClickLogDataset(data_path)
clicklog_data_loader = DataLoader(dataset=clicklog_dataset, batch_size=16)
for uid_batch, stream_batch in stream_data_loader:
print(uid_batch)
print(stream_batch)
上面的代码 returns 与我的预期不同,我希望 stream_batch
是长度为 16
的整数类型的二维张量。然而,我得到的是一个长度为 16 的一维张量列表,并且该列表只有一个元素,如下所示。这是为什么?
#stream_batch
[tensor([24104, 24104, 16742, 16742, 6579, 6579, 6579, 6579, 19577, 19577,
19577, 3541, 3541, 6832, 6832, 9751])]
那么您如何处理样本长度不同的事实? torch.utils.data.DataLoader
has a collate_fn
parameter which is used to transform a list of samples into a batch. By default it does this 列出。您可以编写自己的 collate_fn
,例如 0
-填充输入,将其截断为某个预定义的长度或应用您选择的任何其他操作。
正如@Jatentaki 所建议的,我编写了我的自定义整理函数并且它运行良好。
def get_max_length(x):
return len(max(x, key=len))
def pad_sequence(seq):
def _pad(_it, _max_len):
return [0] * (_max_len - len(_it)) + _it
return [_pad(it, get_max_length(seq)) for it in seq]
def custom_collate(batch):
transposed = zip(*batch)
lst = []
for samples in transposed:
if isinstance(samples[0], int):
lst.append(torch.LongTensor(samples))
elif isinstance(samples[0], float):
lst.append(torch.DoubleTensor(samples))
elif isinstance(samples[0], collections.Sequence):
lst.append(torch.LongTensor(pad_sequence(samples)))
return lst
stream_dataset = StreamDataset(data_path)
stream_data_loader = torch.utils.data.dataloader.DataLoader(dataset=stream_dataset,
batch_size=batch_size,
collate_fn=custom_collate,
shuffle=False)
我是这样做的:
def collate_fn_padd(batch):
'''
Padds batch of variable length
note: it converts things ToTensor manually here since the ToTensor transform
assume it takes in images rather than arbitrary tensors.
'''
## get sequence lengths
lengths = torch.tensor([ t.shape[0] for t in batch ]).to(device)
## padd
batch = [ torch.Tensor(t).to(device) for t in batch ]
batch = torch.nn.utils.rnn.pad_sequence(batch)
## compute mask
mask = (batch != 0).to(device)
return batch, lengths, mask
然后我将其作为 collate_fn
.
传递给数据加载器 class
pytorch 论坛中似乎有大量不同的帖子。让我 link 给他们所有人。他们都有自己的答案和讨论。在我看来似乎没有 "standard way to do it" 但如果有权威参考,请分享。
如果理想答案提到
就好了
- 效率,例如如果在 GPU 中使用 torch 在 collate 函数中进行处理 vs numpy
诸如此类。
列表:
- https://discuss.pytorch.org/t/how-to-create-batches-of-a-list-of-varying-dimension-tensors/50773
- https://discuss.pytorch.org/t/how-to-create-a-dataloader-with-variable-size-input/8278
- https://discuss.pytorch.org/t/using-variable-sized-input-is-padding-required/18131
- https://discuss.pytorch.org/t/dataloader-for-various-length-of-data/6418
- https://discuss.pytorch.org/t/how-to-do-padding-based-on-lengths/24442
分桶:
- https://discuss.pytorch.org/t/tensorflow-esque-bucket-by-sequence-length/41284
我有一个如下所示的数据集。那就是第一项是用户 ID,然后是用户单击的项目集。
0 24104 27359 6684
0 24104 27359
1 16742 31529 31485
1 16742 31529
2 6579 19316 13091 7181 6579 19316 13091
2 6579 19316 13091 7181 6579 19316
2 6579 19316 13091 7181 6579 19316 13091 6579
2 6579 19316 13091 7181 6579
4 19577 21608
4 19577 21608
4 19577 21608 18373
5 3541 9529
5 3541 9529
6 6832 19218 14144
6 6832 19218
7 9751 23424 25067 12606 26245 23083 12606
我定义了一个自定义数据集来处理我的点击日志数据。
import torch.utils.data as data
class ClickLogDataset(data.Dataset):
def __init__(self, data_path):
self.data_path = data_path
self.uids = []
self.streams = []
with open(self.data_path, 'r') as fdata:
for row in fdata:
row = row.strip('\n').split('\t')
self.uids.append(int(row[0]))
self.streams.append(list(map(int, row[1:])))
def __len__(self):
return len(self.uids)
def __getitem__(self, idx):
uid, stream = self.uids[idx], self.streams[idx]
return uid, stream
然后我使用 DataLoader 从数据中检索小批量进行训练。
from torch.utils.data.dataloader import DataLoader
clicklog_dataset = ClickLogDataset(data_path)
clicklog_data_loader = DataLoader(dataset=clicklog_dataset, batch_size=16)
for uid_batch, stream_batch in stream_data_loader:
print(uid_batch)
print(stream_batch)
上面的代码 returns 与我的预期不同,我希望 stream_batch
是长度为 16
的整数类型的二维张量。然而,我得到的是一个长度为 16 的一维张量列表,并且该列表只有一个元素,如下所示。这是为什么?
#stream_batch
[tensor([24104, 24104, 16742, 16742, 6579, 6579, 6579, 6579, 19577, 19577,
19577, 3541, 3541, 6832, 6832, 9751])]
那么您如何处理样本长度不同的事实? torch.utils.data.DataLoader
has a collate_fn
parameter which is used to transform a list of samples into a batch. By default it does this 列出。您可以编写自己的 collate_fn
,例如 0
-填充输入,将其截断为某个预定义的长度或应用您选择的任何其他操作。
正如@Jatentaki 所建议的,我编写了我的自定义整理函数并且它运行良好。
def get_max_length(x):
return len(max(x, key=len))
def pad_sequence(seq):
def _pad(_it, _max_len):
return [0] * (_max_len - len(_it)) + _it
return [_pad(it, get_max_length(seq)) for it in seq]
def custom_collate(batch):
transposed = zip(*batch)
lst = []
for samples in transposed:
if isinstance(samples[0], int):
lst.append(torch.LongTensor(samples))
elif isinstance(samples[0], float):
lst.append(torch.DoubleTensor(samples))
elif isinstance(samples[0], collections.Sequence):
lst.append(torch.LongTensor(pad_sequence(samples)))
return lst
stream_dataset = StreamDataset(data_path)
stream_data_loader = torch.utils.data.dataloader.DataLoader(dataset=stream_dataset,
batch_size=batch_size,
collate_fn=custom_collate,
shuffle=False)
我是这样做的:
def collate_fn_padd(batch):
'''
Padds batch of variable length
note: it converts things ToTensor manually here since the ToTensor transform
assume it takes in images rather than arbitrary tensors.
'''
## get sequence lengths
lengths = torch.tensor([ t.shape[0] for t in batch ]).to(device)
## padd
batch = [ torch.Tensor(t).to(device) for t in batch ]
batch = torch.nn.utils.rnn.pad_sequence(batch)
## compute mask
mask = (batch != 0).to(device)
return batch, lengths, mask
然后我将其作为 collate_fn
.
pytorch 论坛中似乎有大量不同的帖子。让我 link 给他们所有人。他们都有自己的答案和讨论。在我看来似乎没有 "standard way to do it" 但如果有权威参考,请分享。
如果理想答案提到
就好了- 效率,例如如果在 GPU 中使用 torch 在 collate 函数中进行处理 vs numpy
诸如此类。
列表:
- https://discuss.pytorch.org/t/how-to-create-batches-of-a-list-of-varying-dimension-tensors/50773
- https://discuss.pytorch.org/t/how-to-create-a-dataloader-with-variable-size-input/8278
- https://discuss.pytorch.org/t/using-variable-sized-input-is-padding-required/18131
- https://discuss.pytorch.org/t/dataloader-for-various-length-of-data/6418
- https://discuss.pytorch.org/t/how-to-do-padding-based-on-lengths/24442
分桶: - https://discuss.pytorch.org/t/tensorflow-esque-bucket-by-sequence-length/41284