PyTorch RNN-BiLSTM 情感分析准确率低
Posted
技术标签:
【中文标题】PyTorch RNN-BiLSTM 情感分析准确率低【英文标题】:PyTorch RNN-BiLSTM sentiment analysis low accuracy 【发布时间】:2020-02-12 17:45:15 【问题描述】:我将 PyTorch 与一组电影评论一起使用,每个评论都标记为正面或负面。每条评论都被截断或填充为 60 个单词,我的批量大小为 32。这个 60x32 的张量被馈送到一个嵌入层为 100 的嵌入层,从而产生一个 60x32x100 的张量。然后我使用每个评论的未填充长度来打包嵌入输出,并将其提供给带有hidden dim = 256
的 BiLSTM 层。
然后我将其填充回来,应用一个变换(试图获得前向和后向方向的最后一个隐藏状态)并将变换馈送到一个 512x1 的线性层。这是我的模块,我通过此处未显示的 sigmoid 传递最终输出
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])
尝试获取最后一个隐藏的 torch.Size([32, 512])
在线性torch.Size([32, 1])之后
我希望填充后的 lstm 输出为 [60, 32, 512]
,但它在第一维中始终小于 60。
我正在使用 optim.SGD
和 nn.BCEWithLogitsLoss()
训练 10 个 epoch。我的训练准确率始终在 52% 左右,测试准确率始终在 50% 左右,因此模型的表现并不比随机猜测好。我确信我的数据在我的tochtext.data.Dataset
中得到了正确处理。我是否错误地转发了我的张量?
我尝试在我的 lstm、packed_seq
函数和 pad_packed_seq
函数中使用 batch_first=True
,这会在馈送到线性层之前破坏我的转换。
更新
我添加了 init_hidden
方法并尝试不使用 pack/pad 序列方法,但仍然得到相同的结果
【问题讨论】:
这里不清楚,但您是否在每次迭代中将隐藏状态清零?导致您的模型类缺少 LSTM 网络的典型init_hidden()
方法。另一个罪魁祸首可能是 pack-pad 功能?我会先尝试不使用它们,以确保一切正常。
我添加了 init_hidden
并尝试不使用 pack/pad 功能,但仍然得到相同的结果。是否有正确的方法可以从我在 lstm 和线性层之间进行的 3 种可能的转换中获取最后一个隐藏状态?所有 3 个都给出大致相同的结果
根据pad_packed_sequence
的文档,返回的张量是“T x B x *,其中T是最长序列的长度”。我的解释是 T 是批次中最长的长度。这可以解释为什么它总是 total_length 将其填充到固定长度。
pad_packed_sequence
的 PyTorch 文档说输出张量“批量元素将按其长度递减排序。”那么在计算loss的时候,有没有恢复batch的原始顺序呢?
谢谢,我没有恢复原来的顺序。目前我在不使用 pack/pad 功能的情况下运行它并获得 50% 的准确度。我正在尝试先在没有这些功能的情况下提高准确性,然后再将它们添加回来
【参考方案1】:
我将优化器从 SGD 更改为 Adam,并将层从 2 更改为 1,我的模型开始学习,准确率 > 75%
【讨论】:
以上是关于PyTorch RNN-BiLSTM 情感分析准确率低的主要内容,如果未能解决你的问题,请参考以下文章