如何传递给可变长度的线性数据?

How to pass to Linear data with variable length?

我试图通过首先将数据传递给 RNN 然后传递给线性来进行序列分类,通常我只是将输出从 [batch_size, sequence_size, hidden_size] 重塑为 [batch_size, sequence_size*hidden_size] 以将其传递给线性,但在这种情况下我有不同长度的序列,所以 RNN 的输出可能是 [batch_size, 32, hidden_size][batch_size, 29, hidden_size],所以我不知道用什么形状来初始化线性层(代替问号在下面的代码中)。有可能吗?

    class RNN(nn.Module):
        def __init__(self, input_size, hidden_size, num_classes=4):
            super().__init__()
            self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
            self.fc = nn.Linear(hidden_size*????, num_classes)
    
        def forward(self, x):
            #x=[batch_size, sequence_length]
            out, h_n = self.rnn(x)  #out=[batch_size, sequence_length, hidden_size]
            out = torch.reshape(out, (BATCH_SIZE, -1)) #out=[batch_size, sequence_length*hidden_size]
            out = self.fc(out)  #out=[batch_size, num_classes]
            return x

目前每个批次都填充到批次中最长的序列,是否可以将所有序列填充到相同的长度来解决这个问题?将输入形状更改为线性会导致一些不良副作用吗?

线性层旨在将固定数量的特征作为输入。如果你真的想传递一个可变大小的输入,你可以尝试某种插补(例如,创建一个适合最大长度的线性层,只要输入大小较小,就用特征的平均值填充)。但我认为在这种情况下(或与此相关的大多数情况下)这是不可取的。

既然你想做序列分类,你为什么不只传递 RNN 创建的输入摘要(最后一个时间步的输出)而不是整个输出,即传递 [batch_size, hidden_size](最后一个RNN 的输出)作为线性层的输入。那么你的线性层将是 hidden_size x num_classes

代码如下所示:

class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes=4):
        super().__init__()
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        #x=[batch_size, sequence_length]
        out, h_n = self.rnn(x)  #out=[batch_size, sequence_length, hidden_size]
        out = out[:, -1, :]  #out=[batch_size, hidden_size]
        out = self.fc(out)  #out=[batch_size, num_classes]
        return x

这是可行的,因为 RNN 可以学习将整个输入汇总到最后一步。此外,您可以尝试使用 LSTM 而不是 RNN,因为它可能能够更好地实现此摘要(因为它可以更轻松地处理 long-term 依赖项)。