我的目标是对句子进行多类分类。我的RNN(LSTM或GRU)的输入是可变长度序列的批量输入(使用Glove嵌入进行索引)。此输入右侧用零填充。我的GRU RNN重新定义的转发是:
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, **kwargs):
"""Forward propagation of activations"""
if self.gpu:
x = Variable(x).cuda()
lengths = Variable(lengths).cuda()
else:
x = Variable(x)
lengths = Variable(lengths)
# batch_size = int(x.size()[0])
# h_0 = Variable(torch.zeros(self.total_layers, batch_size, self.hidden_size)).cuda()
# Embed and pack the padded sequence
embs = self.embeddings(x)
packed = pack_padded_sequence(embs, list(lengths.data), batch_first=True)
out_packed, _ = self.gru(packed)
out_unpacked, _ = pad_packed_sequence(out_packed, batch_first=True)
out_last = self.last_timestep(out_unpacked, lengths)
output = self.lin(out_last)
return output
至于训练,我使用CrossEntropyLoss。但是,当我测试预测时,无论句子输入如何,它总是预测同一个类。此外,RNN的最终输出(可变输出)几乎相同!仔细观察后,我发现问题出现在反向传播中。
对于许多参数,梯度非常低(大约10 ^ -3,有些低得多)。而且,我不确定包装或填充是否有帮助?我试过运行代码而没有任何打包(只是在填充输入上向前跑)并得到相同的输出,这让我相信我在打包和解包时做错了。我真的很感激任何帮助。谢谢!