PyTorch RNN-BiLSTM情绪分析准确性低

时间:2019-10-16 02:29:32

标签: python pytorch lstm recurrent-neural-network sentiment-analysis

我正在将PyTorch与一组训练有素的电影评论一起使用,每个电影评论都标记为肯定或否定。每个评论都将被截断或填充为60个单词,并且我的批处理大小为32。此60x32张量将被馈送到嵌入层,其中嵌入的暗淡为100,从而产生60x32x100张量。然后,我使用每个评论的未填充长度来打包嵌入输出,并使用hidden dim = 256将其输入到BiLSTM层。

然后我将其填充回去,应用变换(以尝试获取向前和向后方向的最后一个隐藏状态),并将变换输入到512x1的线性层。这是我的模块,我将最终输出通过此处未显示的S型信号传递

class RNN(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, 
                 bidirectional, dropout, pad_idx):

        super().__init__()
        self.el = nn.Embedding(vocab_size, embedding_dim)
        print('vocab size is ', vocab_size)
        print('embedding dim is ', embedding_dim)
        self.hidden_dim = hidden_dim
        self.num_layers = n_layers # 2
        self.lstm = nn.LSTM(input_size=embedding_dim, hidden_size=hidden_dim, num_layers=n_layers, dropout=dropout, bidirectional=bidirectional)
        # Have an output layer for outputting a single output value
        self.linear = nn.Linear(2*hidden_dim, output_dim)

    def init_hidden(self):
        return (torch.zeros(self.n_layers*2, 32, self.hidden_dim).to(device), 
                torch.zeros(self.n_layers*2, 32, self.hidden_dim).to(device))

    def forward(self, text, text_lengths):
        print('input text size ', text.size())
        embedded = self.el(text)
        print('embedded size ', embedded.size())
        packed_seq = torch.nn.utils.rnn.pack_padded_sequence(embedded, lengths=text_lengths, enforce_sorted=False)
        packed_out, (ht, ct) = self.lstm(packed_seq, None)
        out_rnn, out_lengths = torch.nn.utils.rnn.pad_packed_sequence(packed_out)
        print('padded lstm out ', out_rnn.size())        
        #out_rnn = out_rnn[-1] #this works
        #out_rnn = torch.cat((out_rnn[-1, :, :self.hidden_dim], out_rnn[0, :, self.hidden_dim:]), dim=1) # this works
        out_rnn = torch.cat((ht[-1], ht[0]), dim=1) #this works
        #out_rnn = out_rnn[:, -1, :] #doesn't work maybe should
        print('attempt to get last hidden ', out_rnn.size())
        linear_out = self.linear(out_rnn)
        print('after linear ', linear_out.size())
        return linear_out

我尝试了3种不同的变换,以使尺寸适合线性层

out_rnn = out_rnn[-1] #this works
out_rnn = torch.cat((out_rnn[-1, :, :self.hidden_dim], out_rnn[0, :, self.hidden_dim:]), dim=1) # this works
out_rnn = torch.cat((ht[-1], ht[0]), dim=1) #this works

这些都产生这样的输出

  

输入文本大小torch.Size([60,32])

     

嵌入式大小torch.Size([60,32,100])

     

将lstm填充为torch.Size([36,32,512])

     

尝试获取最后一个隐藏的割炬.Size([32,512])

     

线性割炬后尺寸([32,1])

我希望填充的lstm输出为[60, 32, 512],但是在第一维中它总是小于60。

我正在使用optim.SGDnn.BCEWithLogitsLoss()训练10个时期。我的训练准确度始终在52%左右,而测试准确度始终在50%左右,因此该模型的效果并不比随机猜测好。我确定tochtext.data.Dataset中的数据已正确处理。我是否将张量错误地传递?

我曾尝试在lstm,batch_first=True函数和packed_seq函数中使用pad_packed_seq,但在输入线性层之前中断了我的转换。

更新 我添加了init_hidden方法,并尝试了不使用pack / pad序列方法的情况,但仍然得到了相同的结果

1 个答案:

答案 0 :(得分:0)

我将优化器从SGD更改为Adam,并将层数从2更改为1,并且我的模型开始学习,准确度> 75%