PyTorch 置换在 RCNN 中的使用

Use of PyTorch permute in RCNN

我正在研究使用 PyTorch 进行文本分类的 RCNN 实现。 Full Code。有两点使用 permute 函数置换张量的维度。第一个是在 LSTM 层之后和 tanh 之前。第二个是在线性层之后和最大池化层之前。

能否请您解释一下为什么排列是必要的或有用的?

相关代码

    def forward(self, x):
        # x.shape = (seq_len, batch_size)
        embedded_sent = self.embeddings(x)
        # embedded_sent.shape = (seq_len, batch_size, embed_size)

        lstm_out, (h_n,c_n) = self.lstm(embedded_sent)
        # lstm_out.shape = (seq_len, batch_size, 2 * hidden_size)
        
        input_features = torch.cat([lstm_out,embedded_sent], 2).permute(1,0,2)
        # final_features.shape = (batch_size, seq_len, embed_size + 2*hidden_size)
        
        linear_output = self.tanh(
            self.W(input_features)
        )
        # linear_output.shape = (batch_size, seq_len, hidden_size_linear)
        
        linear_output = linear_output.permute(0,2,1) # Reshaping fot max_pool
        
        max_out_features = F.max_pool1d(linear_output, linear_output.shape[2]).squeeze(2)
        # max_out_features.shape = (batch_size, hidden_size_linear)
        
        max_out_features = self.dropout(max_out_features)
        final_out = self.fc(max_out_features)
        return self.softmax(final_out)

其他存储库中的类似代码

RCNN 的类似实现使用 permutetranspose。以下是示例:

permute函数所做的是根据所需的顺序重新排列原始张量,注意permutereshape函数不同,因为当应用 permute 时,张量中的元素遵循您提供的索引,而在 reshape 中不是。

示例代码:

import torch 
var = torch.randn(2, 4)
pe_var = var.permute(1, 0)
re_var = torch.reshape(var, (4, 2))
print("Original size:\n{}\nOriginal var:\n{}\n".format(var.size(), var) + 
      "Permute size:\n{}\nPermute var:\n{}\n".format(pe_var.size(), pe_var) + 
      "Reshape size:\n{}\nReshape var:\n{}\n".format(re_var.size(), re_var))

输出:

Original size:
torch.Size([2, 4])
Original var:
tensor([[ 0.8250, -0.1984,  0.5567, -0.7123],
        [-1.0503,  0.0470, -1.9473,  0.9925]])
Permute size:
torch.Size([4, 2])
Permute var:
tensor([[ 0.8250, -1.0503],
        [-0.1984,  0.0470],
        [ 0.5567, -1.9473],
        [-0.7123,  0.9925]])
Reshape size:
torch.Size([4, 2])
Reshape var:
tensor([[ 0.8250, -0.1984],
        [ 0.5567, -0.7123],
        [-1.0503,  0.0470],
        [-1.9473,  0.9925]])

考虑到 permute 的作用,我们可以看到首先 permute 所做的是重新排序连接张量以使其适合 self.W 的输入格式,即批处理为第一维;第二个 permute 做类似的事情,因为我们想沿着序列最大池化 linear_output,而 F.max_pool1d 将沿着最后一个维度池化。

我添加这个答案是为了提供更多特定于 PyTorch 的详细信息。

需要在nn.LSTMnn.Linear之间使用permute,因为LSTM的输出形状与Linear的预期输入形状不对应。

nn.LSTM 输出 output, (h_n, c_n)。张量 output 的形状为 seq_len, batch, num_directions * hidden_size nn.LSTM. nn.Linear expects an input tensor with shape N,∗,H, where N is batch size and H is number of input features. nn.Linear.

需要在nn.Linearnn.MaxPool1d之间使用permute,因为nn.Linear的输出是N,L,C,其中N是batch size,C是特征的数量,L是序列长度。 nn.MaxPool1d 需要形状为 N、C、L 的输入张量。nn.MaxPool1d

我在 GitHub 和 gitee 上用 PyTorch 回顾了 RCNN 的七种文本分类实现,发现 permutetranspose 是将一层的输出转换为后续层的输入。