这个版本的PyTorch似乎PackedSequence
为递归神经网络提供了可变长度的输入.但是,我发现正确使用它有点困难.
使用pad_packed_sequence
以恢复其通过喂食RNN层的输出pack_padded_sequence
,我们得到了一个T x B x N
张量outputs
,其中T
为最大的时间步长,B
是批量大小和N
是隐藏的尺寸.我发现对于批处理中的短序列,后续输出将全为零.
这是我的问题.
outputs[-1]
将给出错误的结果,因为该张量包含许多短序列的零.需要按序列长度构建索引以获取所有序列的单个最后输出.有更简单的方法吗?N x O
并将批量输出重新整形T x B x O
为TB x O
并使用真实目标TB
(通常是语言模型中的整数)计算交叉熵损失.在这种情况下,批量输出中的这些零值是否重要?问题1 - 最后一个时间步
这是我用来获取最后一个时间步的输出的代码.我不知道是否有更简单的解决方案.如果是的话,我想知道.我按照这个讨论,抓住了我的last_timestep
方法的相关代码片段.这是我的前锋.
class BaselineRNN(nn.Module):
def __init__(self, **kwargs):
...
def last_timestep(self, unpacked, lengths):
# Index of the last output for each sequence.
idx = (lengths - 1).view(-1, 1).expand(unpacked.size(0),
unpacked.size(2)).unsqueeze(1)
return unpacked.gather(1, idx).squeeze()
def forward(self, x, lengths):
embs = self.embedding(x)
# pack the batch
packed = pack_padded_sequence(embs, list(lengths.data),
batch_first=True)
out_packed, (h, c) = self.rnn(packed)
out_unpacked, _ = pad_packed_sequence(out_packed, batch_first=True)
# get the outputs from the last *non-masked* timestep for each sentence
last_outputs = self.last_timestep(out_unpacked, lengths)
# project to the classes using a linear layer
logits = self.linear(last_outputs)
return logits
Run Code Online (Sandbox Code Playgroud)
问题2 - 蒙面交叉熵损失
是的,默认情况下,零填充时间步长(目标)很重要.但是,它很容易掩盖它们.您有两种选择,具体取决于您使用的PyTorch版本.
PyTorch 0.2.0:现在pytorch支持直接在屏蔽CrossEntropyLoss,与ignore_index
说法.例如,在语言建模或seq2seq中,我添加零填充,我掩盖零填充的单词(目标),就像这样:
loss_function = nn.CrossEntropyLoss(ignore_index = 0)
PyTorch 0.1.12及更早版本:在较旧版本的PyTorch中,不支持屏蔽,因此您必须实现自己的解决方法.我使用的解决方案是jihunchoi的masked_cross_entropy.py.您可能也对此讨论感兴趣.
归档时间: |
|
查看次数: |
6986 次 |
最近记录: |