pytorch nllloss функция несоответствие формы цели - PullRequest
1 голос
/ 08 февраля 2020

Я тренирую модель LSTM, используя pytorch с размером пакета 256 и NLLLoss () в качестве функции потерь. У функции потерь возникают проблемы с формой данных.

Вывод softmax из прямой передачи имеет форму torch.Size([256, 4, 1181]), где 256 - размер пакета, 4 - длина последовательности, а 1181 - размер речи.

Цель имеет форму torch.Size([256, 4]), где 256 - размер пакета, а 4 - длина выходной последовательности.

Когда я раньше проводил тестирование с размером пакета 1, модель работает нормально, но когда я добавить размер партии, это ломается. Я прочитал, что NLLLoss () может принимать цель класса в качестве ввода вместо одной горячей закодированной цели.

Я неправильно понимаю? Или я не правильно отформатировал форму цели?

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])

1 Ответ

2 голосов
/ 11 февраля 2020

Ваша входная форма для функции потерь равна (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))
...