如何解决用于视频识别的CNN + RNN架构
我正在尝试使用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以完成我的任务。这就是为什么我不单独计算图像的嵌入。
那么我的问题如下:
-
我的输入数据的形状是否正确,以便在我的上下文中处理成批的视频?还是应该使用PackedSequence以外的其他东西?
-
在我的转发功能中,如何使用VGG和GRU单元处理一批图像序列?我不能直接将PackedSequence作为VGG的输入,所以如何进行?
-
这种方法似乎尊重“火炬手做事方式”吗?还是我的方法有缺陷?
解决方法
我终于找到了使之工作的解决方案。这是一个简化但完整的示例,说明了我如何创建一个能够使用packedSequence作为输入的VideoRNN:
var width = element && element.getBoundingClientRect && element.getBoundingClientRect().width;
关键是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,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
)
方法,该方法可以在CNN网络中馈送PackedSequence并检索由嵌入制成的新PackedSequence作为输出。
希望您会发现它有用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。