PyTorch permute 在 RCNN 中的应用

3
我在使用PyTorch实现RCNN文本分类,需要使用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,以下是示例:

2个回答

3
permute函数的作用是根据所需的排序方式重新排列原张量,注意permute函数与reshape函数不同,因为在应用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 将在最后一维上进行池化。

排列与重塑的良好描述。 - Jacob Quisenberry

2

我添加了这个答案来提供额外的PyTorch特定细节。

nn.LSTMnn.Linear之间使用permute是必要的,因为LSTM的输出形状与Linear期望的输入形状不相符。

nn.LSTM输出output, (h_n, c_n)。张量output的形状为seq_len, batch, num_directions * hidden_size nn.LSTMnn.Linear期望一个形状为N,∗,H的输入张量,其中N是批大小,H是输入特征数。nn.Linear

nn.Linearnn.MaxPool1d之间使用permute是必要的,因为nn.Linear的输出是N,L,C,其中N是批大小,C是特征数,而L是序列长度。nn.MaxPool1d期望一个形状为N,C,L的输入张量。nn.MaxPool1d

我在GitHub和gitee上回顾了七个使用PyTorch进行文本分类的RCNN实现,并发现permutetranspose是将一个层的输出转换为后续层的输入的常规方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接