行为识别框架Slowfast解读

在这里插入图片描述

SlowFast使用了一个慢速高分辨率CNN(Slow通道)来分析视频中的静态内容(环境),同时使用一个快速低分辨率CNN(Fast通道)来分析视频中的动态内容(动作)

为了更好的提取slow分支特征,slow通道的计算会更加复杂,Slow通道的计算成本要比Fast通道高4倍。

双分支提取

Slow通道和Fast通道都使用3D RestNet模型,捕捉若干帧之后立即运行3D卷积操作。

Slow通道使用一个较大的时序跨度(即每秒跳过的帧数),通常设置为16,这意味着大约1秒可以采集2帧。
Fast通道使用一个非常小的时序跨度τ/α,其中α通常设置为8,以便1秒可以采集15帧。Fast通道通过使用小得多的卷积宽度(使用的滤波器数量)来保持轻量化,通常设置为慢通道卷积宽度的⅛,这个值被标记为β。使用小一些的卷积宽度的原因是Fast通道需要的计算量要比Slow通道小4倍,虽然它的时序频率更高。
在这里插入图片描述

3D卷积核的尺寸记作{T×S², C} ,其中T、S和C分别表示时序Temporal(time), 空间Spatial(weight x height)和频道Channel(channel)的尺寸。跨度记作{temporal stride, spatial stride ^ 2}。速度比率(跳帧率) 为 α = 8 ,频道比率为1/β = 1/8。τ 设置为 16。绿色表示高一些的时序分辨率,Fast通道中的橙色表示较少的频道。
在这里插入图片描述
在这里插入图片描述

特征融合

在这里插入图片描述
如图中所示,来自Fast通道的数据通过侧向连接被送入Slow通道,这使得Slow通道可以了解Fast通道的处理结果。单一数据样本的shape在两个通道间是不同的(Fast通道是{αT, S², βC} 而Slow通道是 {T, S², αβC}),这要求SlowFast对Fast通道的结果进行数据变换,然后融入Slow通道。论文给出了三种进行数据变换的技术思路,其中第三个思路在实践中最有效。
效果:(3)>(1)>(2)

(1)Time-to-channel:将{αT, S², βC} 变形转置为 {T , S², αβC},就是说把α帧压入一帧
(2)Time-strided采样:简单地每隔α帧进行采样,{αT , S², βC} 就变换为 {T , S², βC}
(3)Time-strided卷积: 用一个5×12的核进行3d卷积, 2βC输出频道,跨度= α.

有趣的是,研究人员发现双向侧链接,即将Slow通道结果也送入Fast通道,对性能没有改善。

在每个通道的末端,SlowFast执行全局平均池化,一个用来降维的标准操作,然后组合两个通道的结果并送入一个全连接分类层,该层使用softmax来识别图像中发生的动作。

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SlowFast架构是一种在视频行为识别中广泛使用的架构,它结合了慢速和快速两种不同的卷积神经网络。以下是SlowFast架构的核心代码: ```python import torch import torch.nn as nn import torch.nn.functional as F class Bottleneck(nn.Module): def __init__(self, in_planes, planes, stride=1): super(Bottleneck, self).__init__() self.conv1 = nn.Conv3d(in_planes, planes, kernel_size=1, bias=False) self.bn1 = nn.BatchNorm3d(planes) self.conv2 = nn.Conv3d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False) self.bn2 = nn.BatchNorm3d(planes) self.conv3 = nn.Conv3d(planes, planes*4, kernel_size=1, bias=False) self.bn3 = nn.BatchNorm3d(planes*4) self.shortcut = nn.Sequential() if stride != 1 or in_planes != planes*4: self.shortcut = nn.Sequential( nn.Conv3d(in_planes, planes*4, kernel_size=1, stride=stride, bias=False), nn.BatchNorm3d(planes*4) ) def forward(self, x): out = F.relu(self.bn1(self.conv1(x))) out = F.relu(self.bn2(self.conv2(out))) out = self.bn3(self.conv3(out)) out += self.shortcut(x) out = F.relu(out) return out class SlowFast(nn.Module): def __init__(self, block, num_blocks, num_classes=10): super(SlowFast, self).__init__() self.in_planes = 64 self.fast = nn.Sequential( nn.Conv3d(3, 8, kernel_size=(1, 5, 5), stride=(1, 2, 2), padding=(0, 2, 2), bias=False), nn.BatchNorm3d(8), nn.ReLU(inplace=True), nn.Conv3d(8, 16, kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1), bias=False), nn.BatchNorm3d(16), nn.ReLU(inplace=True), nn.Conv3d(16, 32, kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1), bias=False), nn.BatchNorm3d(32), nn.ReLU(inplace=True), nn.Conv3d(32, 64, kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1), bias=False), nn.BatchNorm3d(64), nn.ReLU(inplace=True) ) self.slow = nn.Sequential( nn.Conv3d(3, 64, kernel_size=(1, 1, 1), stride=(1, 1, 1), padding=(0, 0, 0), bias=False), nn.BatchNorm3d(64), nn.ReLU(inplace=True), nn.Conv3d(64, 64, kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1), bias=False), nn.BatchNorm3d(64), nn.ReLU(inplace=True), nn.Conv3d(64, 64, kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1), bias=False), nn.BatchNorm3d(64), nn.ReLU(inplace=True), nn.Conv3d(64, 128, kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1), bias=False), nn.BatchNorm3d(128), nn.ReLU(inplace=True) ) self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1) self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2) self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2) self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2) self.avgpool = nn.AdaptiveAvgPool3d((1, 1, 1)) self.fc = nn.Linear(512 * block.expansion, num_classes) def _make_layer(self, block, planes, num_blocks, stride): strides = [stride] + [1]*(num_blocks-1) layers = [] for stride in strides: layers.append(block(self.in_planes, planes, stride)) self.in_planes = planes * block.expansion return nn.Sequential(*layers) def forward(self, x): fast = self.fast(x[:, :, ::2]) slow = self.slow(x[:, :, ::16]) x = torch.cat([slow, fast], dim=2) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avgpool(x) x = x.view(x.size(0), -1) x = self.fc(x) return x ``` 该代码定义了SlowFast架构中的Bottleneck块和SlowFast类,用于构建整个网络。其中,Bottleneck块是SlowFast中的基本块,用于构建各个层;SlowFast类则是整个网络的主体部分,定义了各个层的结构和前向传播的过程。在构建网络时,可以根据需要调整Bottleneck块和SlowFast类的超参数,以满足不同的视频行为识别任务需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuezero_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值