PyTorch:动态计算图之间的关系 - 填充 - DataLoader

时间:2018-01-13 20:33:00

标签: nlp deep-learning padding pytorch

据我了解,PyTorch的强度应该是它与动态计算图一起使用。在NLP的上下文中,这意味着具有可变长度的序列不一定需要填充到相同的长度。但是,如果我想使用PyTorch DataLoader,我需要填充我的序列,因为DataLoader只需要张量 - 假设我作为一个初学者不想构建一些自定义的collat​​e_fn。

现在这让我想知道 - 在这种背景下,这不会消除动态计算图的整体优势吗? 另外,如果我将我的序列填充到DataLoader作为张量,并且在末尾有很多零作为填充标记(在单词ID的情况下),它会对我的训练产生任何负面影响,因为PyTorch可能没有针对使用填充序列进行计算(因为整个前提是它可以在动态图中使用可变序列长度),还是只是没有任何区别?

我也会在PyTorch论坛上发布这个问题......

谢谢!

1 个答案:

答案 0 :(得分:4)

  

在NLP的上下文中,这意味着具有可变长度的序列不一定需要填充到相同的长度。

这意味着您不需要填充序列,除非您正在进行数据批处理,这是目前在PyTorch中添加并行性的唯一方法。 DyNet有一个名为autobatching的方法(详细描述in this paper),它对图操作而不是数据进行批处理,因此这可能是您想要查看的内容。

  

但是,如果我想使用PyTorch DataLoader,我需要填充我的序列,因为DataLoader只需要张量 - 假设我作为一个初学者不想构建一些自定义的collat​​e_fn。

如果您编写自己的DataLoader课程,并且使用Dataset,则可以使用batch_size=1。扭曲是为你的可变长度序列使用numpy数组(否则default_collate会给你带来困难):

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

class FooDataset(Dataset):
    def __init__(self, data, target):
        assert len(data) == len(target)
        self.data = data
        self.target = target
    def __getitem__(self, index):
        return self.data[index], self.target[index]
    def __len__(self):
        return len(self.data)

data = [[1,2,3], [4,5,6,7,8]]
data = [np.array(n) for n in data]
targets = ['a', 'b']

ds = FooDataset(data, targets)
dl = DataLoader(ds, batch_size=1)

print(list(enumerate(dl)))
# [(0, [
#  1  2  3
# [torch.LongTensor of size 1x3]
# , ('a',)]), (1, [
#  4  5  6  7  8
# [torch.LongTensor of size 1x5]
# , ('b',)])]
  

现在这让我想知道 - 在这种情况下,这不会消除动态计算图的整体优势吗?

公平点,但动态计算图的主要优势(至少目前)主要是使用像pdb这样的调试工具的可能性,这会迅速缩短开发时间。使用静态计算图表进行调试会更加困难。 PyTorch也没有理由不在未来实施进一步的即时优化或类似于DyNet自动批处理的概念。

  

另外,如果我将我的序列填充到DataLoader作为张量,并且在末尾有很多零作为填充标记,它会对我的训练产生负面影响吗? / p>

是的,无论是在运行时还是在渐变中。 RNN将像普通数据一样遍历填充,这意味着您必须以某种方式处理它。 PyTorch为您提供处理填充序列和RNN的工具,即pad_packed_sequencepack_padded_sequence。这些将允许您在RNN执行期间忽略填充元素,但要注意:这不适用于您自己实现的RNN(或者至少如果您不手动添加对它的支持)。