在 pytorch 中通过具有线性输出层的 RNN 发送的填充批次的掩蔽和计算损失
Masking and computing loss for a padded batch sent through an RNN with a linear output layer in pytorch
虽然是一个典型的用例,但我找不到一个简单明了的指南来说明当通过 RNN 发送时,在 pytorch 中计算填充小批量损失的规范方法是什么。
我认为规范的管道可以是:
1) pytorch RNN 需要一个填充的批量张量形状:(max_seq_len, batch_size, emb_size)
2) 所以我们给出一个嵌入层,例如这个张量:
tensor([[1, 1],
[2, 2],
[3, 9]])
9 是填充索引。批量大小为 2。嵌入层将使其形状为 (max_seq_len、batch_size、emb_size)。 batch中的sequences是降序排列的,所以我们可以pack一下。
3)我们应用pack_padded_sequence,我们应用RNN,最后我们应用pad_packed_sequence。此时我们有 (max_seq_len, batch_size, hidden_size)
4) 现在我们在结果上应用线性输出层,假设 log_softmax。所以最后我们得到了一批形状分数的张量:(max_seq_len, batch_size, linear_out_size)
我应该如何从这里计算损失,屏蔽填充部分(具有任意目标)?谢谢!
我认为 PyTocrh Chatbot Tutorial 可能对您有指导意义。
基本上,您计算有效输出值的掩码(填充无效),并使用它来计算仅这些值的损失。
请参阅教程页面上的 outputVar
和 maskNLLLoss
方法。为了您的方便,我在这里复制了代码,但您确实需要在所有代码的上下文中查看它。
# Returns padded target sequence tensor, padding mask, and max target length
def outputVar(l, voc):
indexes_batch = [indexesFromSentence(voc, sentence) for sentence in l]
max_target_len = max([len(indexes) for indexes in indexes_batch])
padList = zeroPadding(indexes_batch)
mask = binaryMatrix(padList)
mask = torch.BoolTensor(mask)
padVar = torch.LongTensor(padList)
return padVar, mask, max_target_len
def maskNLLLoss(inp, target, mask):
nTotal = mask.sum()
crossEntropy = -torch.log(torch.gather(inp, 1, target.view(-1, 1)).squeeze(1))
loss = crossEntropy.masked_select(mask).mean()
loss = loss.to(device)
return loss, nTotal.item()
虽然是一个典型的用例,但我找不到一个简单明了的指南来说明当通过 RNN 发送时,在 pytorch 中计算填充小批量损失的规范方法是什么。
我认为规范的管道可以是:
1) pytorch RNN 需要一个填充的批量张量形状:(max_seq_len, batch_size, emb_size)
2) 所以我们给出一个嵌入层,例如这个张量:
tensor([[1, 1],
[2, 2],
[3, 9]])
9 是填充索引。批量大小为 2。嵌入层将使其形状为 (max_seq_len、batch_size、emb_size)。 batch中的sequences是降序排列的,所以我们可以pack一下。
3)我们应用pack_padded_sequence,我们应用RNN,最后我们应用pad_packed_sequence。此时我们有 (max_seq_len, batch_size, hidden_size)
4) 现在我们在结果上应用线性输出层,假设 log_softmax。所以最后我们得到了一批形状分数的张量:(max_seq_len, batch_size, linear_out_size)
我应该如何从这里计算损失,屏蔽填充部分(具有任意目标)?谢谢!
我认为 PyTocrh Chatbot Tutorial 可能对您有指导意义。
基本上,您计算有效输出值的掩码(填充无效),并使用它来计算仅这些值的损失。
请参阅教程页面上的 outputVar
和 maskNLLLoss
方法。为了您的方便,我在这里复制了代码,但您确实需要在所有代码的上下文中查看它。
# Returns padded target sequence tensor, padding mask, and max target length
def outputVar(l, voc):
indexes_batch = [indexesFromSentence(voc, sentence) for sentence in l]
max_target_len = max([len(indexes) for indexes in indexes_batch])
padList = zeroPadding(indexes_batch)
mask = binaryMatrix(padList)
mask = torch.BoolTensor(mask)
padVar = torch.LongTensor(padList)
return padVar, mask, max_target_len
def maskNLLLoss(inp, target, mask):
nTotal = mask.sum()
crossEntropy = -torch.log(torch.gather(inp, 1, target.view(-1, 1)).squeeze(1))
loss = crossEntropy.masked_select(mask).mean()
loss = loss.to(device)
return loss, nTotal.item()