我在使用从这个github获取的编码器时,遇到了输出不一致的问题。
编码器的结构如下所示:
class Encoder(nn.Module): r"""Applies a multi-layer LSTM to an variable length input sequence. """ def __init__(self, input_size, hidden_size, num_layers, dropout=0.0, bidirectional=True, rnn_type='lstm'): super(Encoder, self).__init__() self.input_size = 40 self.hidden_size = 512 self.num_layers = 8 self.bidirectional = True self.rnn_type = 'lstm' self.dropout = 0.0 if self.rnn_type == 'lstm': self.rnn = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, dropout=dropout, bidirectional=bidirectional) def forward(self, padded_input, input_lengths): """ Args: padded_input: N x T x D input_lengths: N Returns: output, hidden - **output**: N x T x H - **hidden**: (num_layers * num_directions) x N x H """ total_length = padded_input.size(1) # get the max sequence length packed_input = pack_padded_sequence(padded_input, input_lengths, batch_first=True,enforce_sorted=False) packed_output, hidden = self.rnn(packed_input) pdb.set_trace() output, _ = pad_packed_sequence(packed_output, batch_first=True, total_length=total_length) return output, hidden
所以它仅由一个RNN LSTM单元组成,如果我打印这个编码器,输出是这样的:
LSTM(40, 512, num_layers=8, batch_first=True, bidirectional=True)
所以它的输出尺寸应该是512对吗?但是当我输入一个尺寸为torch.Size([16, 1025, 40])
的张量时(16个样本,每个样本有1025个40大小的向量,这些向量被打包以适应RNN),RNN的输出尺寸变成了1024,torch.Size([16, 1025, 1024])
,而不是应该的512,对吗?
我是不是遗漏了什么?
回答:
设置bidirectional=True
会使LSTM成为双向的,这意味着会有两个LSTM,一个从左到右,另一个从右到左。
output 的形状为(seq_len, batch, num_directions * hidden_size):包含来自LSTM最后一层的输出特征(h_t)的张量,对于每个t。如果输入是
torch.nn.utils.rnn.PackedSequence
,输出也将是打包序列。对于未打包的情况,可以使用
output.view(seq_len, batch, num_directions, hidden_size)
来分离方向,前向和后向分别为方向0和1。同样,在打包的情况下也可以分离方向。
由于使用了双向LSTM,您的输出尺寸为[batch, seq_len, 2 * hidden_size]
(在您的案例中,batch
和seq_len
因为设置了batch_first=True
而交换了位置)。两个方向的输出被拼接在一起,以便包含两者的信息,如果您想分别处理它们,可以很容易地分开它们。