用于视频识别的CNN+RNN架构



我正在尝试使用pytorch复制本文中提出的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做事方式;还是应该是我的方法有缺陷?

我终于找到了让它发挥作用的解决方案。下面是一个简化但完整的例子,说明我是如何创建一个能够使用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
)

关键是CCD_ 1方法允许在CNN网络中馈送PackedSequence并检索由嵌入作为输出的新PackedSequence。

我希望你会觉得它有用。

最新更新