【问题标题】:CNN + RNN architecture for video recognition用于视频识别的 CNN + RNN 架构
【发布时间】:2020-12-13 11:11:43
【问题描述】:

我正在尝试使用 pytorch 复制 in this paper 提出的 ConvNet + LSTM 方法。但我正在努力寻找在我的模型中结合 CNN 和 LSTM 的正确方法。这是我的尝试:

class VideoRNN(nn.Module):
  def __init__(self, hidden_size, n_classes):
    super(VideoRNN, self).__init__()

    self.hidden_size = hidden_size

    vgg = models.vgg16(pretrained=True)
    embed = nn.Sequential(*list(vgg.classifier.children())[:-1])
    vgg.classifier = embed
    
    for param in vgg.parameters():
      param.requires_grad = False


    self.embedding = vgg
    self.GRU = nn.GRU(4096, hidden_size)


  def forward(self, input, hidden=None):
    embedded = self.embedding(input)
    output, hidden = self.gru(output, hidden)
    output = self.classifier(output.view(-1, 4096))

    return output, hidden

由于我的视频长度可变,我提供 PackedSequence 作为输入。它由形状为 (M,B,C,H,W) 的张量创建,其中 M 是最大序列长度,B 是批量大小。 C,H,W是每帧的通道、高度和宽度。

我希望预先训练的 CNN 成为模型的一部分,因为我稍后可能会解冻某些层以针对我的任务微调 CNN。这就是为什么我没有单独计算图像的嵌入。

我的问题如下:

  1. 为了在我的上下文中处理批量视频,我的输入数据的形状是否正确,或者我应该使用 PackedSequence 以外的其他东西?

  2. 在我的转发功能中,我如何使用我的 VGG 和我的 GRU 单元处理一批图像序列?我无法直接将 PackedSequence 作为 VGG 的输入,我该如何继续?

  3. 这种方法似乎尊重“pytorch 做事方式”还是我的方法有缺陷?

【问题讨论】:

    标签: deep-learning computer-vision pytorch lstm conv-neural-network


    【解决方案1】:

    我终于找到了使它起作用的解决方案。这是一个简化但完整的示例,说明我如何设法创建一个能够使用 packedSequence 作为输入的 VideoRNN:

        class VideoRNN(nn.Module):
        def __init__(self, n_classes, batch_size, device):
            super(VideoRNN, self).__init__()
    
            self.batch = batch_size
            self.device = device
    
            # Loading a VGG16
            vgg = models.vgg16(pretrained=True)
    
            # Removing last layer of vgg 16
            embed = nn.Sequential(*list(vgg.classifier.children())[:-1])
            vgg.classifier = embed
    
            # Freezing the model 3 last layers
            for param in vgg.parameters():
                param.requires_grad = False
    
            self.embedding = vgg
            self.gru = nn.LSTM(4096, 2048, bidirectional=True)
    
            # Classification layer (*2 because bidirectionnal)
            self.classifier = nn.Sequential(
                nn.Linear(2048 * 2, 256),
                nn.ReLU(),
                nn.Linear(256, n_classes),
            )
    
        def forward(self, input):
            hidden = torch.zeros(2, self.batch , 2048).to(
                self.device
            )
    
            c_0 = torch.zeros(self.num_layer * 2, self.batch, 2048).to(
                self.device
            )
    
            embedded = self.simple_elementwise_apply(self.embedding, input)
            output, hidden = self.gru(embedded, (hidden, c_0))
            hidden = hidden[0].view(-1, 2048 * 2)
    
            output = self.classifier(hidden)
    
            return output
    
        def simple_elementwise_apply(self, fn, packed_sequence):
            return torch.nn.utils.rnn.PackedSequence(
                fn(packed_sequence.data), packed_sequence.batch_sizes
            )
    

    关键是 simple_elementwise_apply 方法允许在 CNN 网络中输入 PackedSequence 并检索由嵌入制成的新 PackedSequence 作为输出。

    我希望你会发现它有用。

    【讨论】:

      猜你喜欢
      • 2017-11-20
      • 2019-11-24
      • 2020-10-23
      • 2022-01-17
      • 2019-07-29
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多