pytorch nllloss 函数目标形状不匹配
pytorch nllloss function target shape mismatch
我正在使用批量大小为 256 的 pytorch 和 NLLLoss() 作为损失函数来训练 LSTM 模型。
损失函数的数据形状有问题。
前向传递的 softmax 输出具有 torch.Size([256, 4, 1181])
的形状,其中 256 是批量大小,4 是序列长度,1181 是词汇量大小。
目标的形状为 torch.Size([256, 4])
,其中 256 是批量大小,4 是输出序列长度。
当我之前测试批大小为 1 时,模型运行良好,但当我添加批大小时,它出现故障。我读到 NLLLoss() 可以将 class 目标作为输入而不是一个热编码目标。
我是不是误会了?还是我没有正确格式化目标的形状?
class LSTM(nn.Module):
def __init__(self, embed_size=100, hidden_size=100, vocab_size=1181, embedding_matrix=...):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.word_embeddings = nn.Embedding(vocab_size, embed_size)
self.word_embeddings.load_state_dict({'weight': torch.Tensor(embedding_matrix)})
self.word_embeddings.weight.requires_grad = False
self.lstm = nn.LSTM(embed_size, hidden_size)
self.hidden2out = nn.Linear(hidden_size, vocab_size)
def forward(self, tokens):
batch_size, num_steps = tokens.shape
embeds = self.word_embeddings(tokens)
lstm_out, _ = self.lstm(embeds.view(batch_size, num_steps, -1))
out_space = self.hidden2out(lstm_out.view(batch_size, num_steps, -1))
out_scores = F.log_softmax(out_space, dim=1)
return out_scores
model = LSTM(self.config.embed_size, self.config.hidden_size, self.config.vocab_size, self.embedding_matrix)
loss_function = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=self.config.lr)
错误:
~/anaconda3/lib/python3.7/site-packages/torch/nn/functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
1846 if target.size()[1:] != input.size()[2:]:
1847 raise ValueError('Expected target size {}, got {}'.format(
-> 1848 out_size, target.size()))
1849 input = input.contiguous().view(n, c, 1, -1)
1850 target = target.contiguous().view(n, 1, -1)
ValueError: Expected target size (256, 554), got torch.Size([256, 4])
损失函数的输入形状是 (N, d, C) = (256, 4, 1181)
,目标形状是 (N, d) = (256, 4)
,但是,根据 NLLLoss 上的文档,输入应该是 (N, C, d)
(N, d)
.
的目标
假设 x
是您的网络输出,y
是目标,那么您可以通过转置 x
的不正确维度来计算损失,如下所示:
loss = loss_function(x.transpose(1, 2), y)
或者,由于 NLLLoss 只是对所有响应进行平均,因此您可以通过将 x
和 y
重塑为 (N*d, C)
和 (N*d)
张量来避免创建数据副本,并且得到相同的结果:
loss = loss_function(x.reshape(N*d, C), y.reshape(N*d))
我正在使用批量大小为 256 的 pytorch 和 NLLLoss() 作为损失函数来训练 LSTM 模型。 损失函数的数据形状有问题。
前向传递的 softmax 输出具有 torch.Size([256, 4, 1181])
的形状,其中 256 是批量大小,4 是序列长度,1181 是词汇量大小。
目标的形状为 torch.Size([256, 4])
,其中 256 是批量大小,4 是输出序列长度。
当我之前测试批大小为 1 时,模型运行良好,但当我添加批大小时,它出现故障。我读到 NLLLoss() 可以将 class 目标作为输入而不是一个热编码目标。
我是不是误会了?还是我没有正确格式化目标的形状?
class LSTM(nn.Module):
def __init__(self, embed_size=100, hidden_size=100, vocab_size=1181, embedding_matrix=...):
super(LSTM, self).__init__()
self.hidden_size = hidden_size
self.word_embeddings = nn.Embedding(vocab_size, embed_size)
self.word_embeddings.load_state_dict({'weight': torch.Tensor(embedding_matrix)})
self.word_embeddings.weight.requires_grad = False
self.lstm = nn.LSTM(embed_size, hidden_size)
self.hidden2out = nn.Linear(hidden_size, vocab_size)
def forward(self, tokens):
batch_size, num_steps = tokens.shape
embeds = self.word_embeddings(tokens)
lstm_out, _ = self.lstm(embeds.view(batch_size, num_steps, -1))
out_space = self.hidden2out(lstm_out.view(batch_size, num_steps, -1))
out_scores = F.log_softmax(out_space, dim=1)
return out_scores
model = LSTM(self.config.embed_size, self.config.hidden_size, self.config.vocab_size, self.embedding_matrix)
loss_function = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=self.config.lr)
错误:
~/anaconda3/lib/python3.7/site-packages/torch/nn/functional.py in nll_loss(input, target, weight, size_average, ignore_index, reduce, reduction)
1846 if target.size()[1:] != input.size()[2:]:
1847 raise ValueError('Expected target size {}, got {}'.format(
-> 1848 out_size, target.size()))
1849 input = input.contiguous().view(n, c, 1, -1)
1850 target = target.contiguous().view(n, 1, -1)
ValueError: Expected target size (256, 554), got torch.Size([256, 4])
损失函数的输入形状是 (N, d, C) = (256, 4, 1181)
,目标形状是 (N, d) = (256, 4)
,但是,根据 NLLLoss 上的文档,输入应该是 (N, C, d)
(N, d)
.
假设 x
是您的网络输出,y
是目标,那么您可以通过转置 x
的不正确维度来计算损失,如下所示:
loss = loss_function(x.transpose(1, 2), y)
或者,由于 NLLLoss 只是对所有响应进行平均,因此您可以通过将 x
和 y
重塑为 (N*d, C)
和 (N*d)
张量来避免创建数据副本,并且得到相同的结果:
loss = loss_function(x.reshape(N*d, C), y.reshape(N*d))