《TSM: Temporal Shift Module for Efficient Video Understanding》论文笔记

本文介绍了一种名为Time Shift Module (TSM)的技术,它通过在相邻帧间交换部分通道信息,实现在几乎不增加计算量的情况下提升2DCNN的视频理解能力。TSM在设计上避免了数据大量移动导致的效率降低,并保持了良好的空间特征学习能力。实验结果显示,TSM在视频识别任务上显著提高了模型性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://blog.youkuaiyun.com/SIGAI_优快云/article/details/84585363

前言

本文论共两篇,一篇为v1版此处,v2版此处,后者为主要在前者上加上了online版本。

论文采用时间位移模块,即移动相邻帧之间的部分通道信息使相邻帧之间信息交换,可以基本不增加计算量的情况下嵌入到任何2D CNN中。

TSM模块

在这里插入图片描述

2.1、Intuition

一个正常的卷积操作,例如kernel为3的1D卷积, w = ( w 1 , w 2 , w 3 ) w=(w_1, w_2, w_3) w=(w1,w2,w3), 输入X为一个无限长的1D矢量,则有 Y = c o n v ( W , X ) , 即 Y i = w 1 X i − 1 + w 2 X i + w 3 X i + 1 Y=conv(W,X),即Y_i=w_1X_{i-1}+w_2X_i+w_3X_{i+1} Y=conv(W,X)Yi=w1Xi1+w2Xi+w3Xi+1,可以分解为两步,
1 ) 位 移 : x i − 1 = X i − 1 , x i 0 = X i , x i + 1 = X i + 1 1)位移: x_i^{-1}=X_{i-1}, x_i^{0}=X_{i}, x_i^{+1}=X_{i+1} 1:xi1=Xi1xi0=Xixi+1=Xi+1
2 ) 累 加 : Y = w 1 X i − 1 + w 2 X i + w 3 X i + 1 2)累加: Y=w_1X_{i-1}+w_2X_i+w_3X_{i+1} 2:Y=w1Xi1+w2Xi+w3Xi+1

2.2、Navie Shift Dose Not Work

Navie Shift指的是论文《Shift: A Zero FLOP, Zero Parameter Alternative to Spatial Convolutions》,其在不同的空间方向上移动其输入张量的每个通道
在这里插入图片描述
把空间位移策略直接应用到时间维度既不能提高性能也不能提高效率。如果我们移位全部或者大部分通道,会导致两个问题:(1)由于大量数据的移动导致效率更差,数据移动增加推理时间;(2)由于糟糕的空间建模能力导致效能降低,通过将部分通道移动到相邻帧,当前帧不在获得通道信息,损害2DCNN的空间建模能力。相比于TSN,当使用naive shift精度下降2.6%。

2.3、模块设计

(1)减少数据移动:移动部分通道的策略
(2)保持空间特征学习能力:在残差块中shift 1/4(每个方向1/8)的通道

3、TSM Video Network

3.1、Offline Models with Bi-directional TSM

3.2、Online Models with Uni-directional TSM

通过从以前帧转移到当前帧,实现在线识别。
在这里插入图片描述在inference阶段,对于每一帧,保存每个残差块的前1/8的特征图并缓存在寄存器中。对于下一帧,用缓存的特征图替换当前特征图的前1/8。即使用7/8的当前特征图和1/8的旧特征图组合来生成下一层并重复。使用单向TSM进行在线视频识别具有几个独特的优势:
(1)低延迟推断。 对于每个帧,我们只需要替换和缓存1/8的特征,而不需要进行任何额外的计算。 因此,给出全帧预测的延迟几乎与2D CNN基线相同。 像ECO这样的现有方法使用多帧来给出一个预测,这可能在在线预测期间引入大的延迟
(2)内存消耗低。 由于我们只缓存了内存中的一小部分功能,因此内存消耗很低。 对于ResNet-50,我们只需要3.8MB内存缓存来存储中间功能
(3)多级时间融合。 大多数在线方法像TRN或中级时间融合ECO等特征提取后实现晚期时间融合,而我们的TSM能够实现所有级别的时间融合。 通过实验(表2),我们发现多级时间融合对于复杂的时间建模非常重要

4、实验

见论文

code

shift code

def shift(x, n_segment, fold_div=3):
    nt, c, h, w = x.size()
    n_batch = nt // n_segment
    x = x.view(n_batch, n_segment, c, h, w)

    out = torch.zeros_like(x)
    fold = c // fold_div
    out[:, :-1, :fold] = x[:, 1:, :fold]  # shift left
    out[:, 1:, fold: 2 * fold] = x[:, :-1, fold: 2 * fold]  # shift right
    out[:, :, 2 * fold:] = x[:, :, 2 * fold:]  # not shift
    return out.view(nt, c, h, w)
import torchvision
if isinstance(net, torchvision.models.ResNet):
    if place == 'block':
        def make_block_temporal(stage, this_segment):
            blocks = list(stage.children())
            print('=> Processing stage with {} blocks'.format(len(blocks)))
            for i, b in enumerate(blocks):
                blocks[i] = TemporalShift(b, n_segment=this_segment, n_div=n_div)
            return nn.Sequential(*(blocks))

        net.layer1 = make_block_temporal(net.layer1, n_segment_list[0])
        net.layer2 = make_block_temporal(net.layer2, n_segment_list[1])
        net.layer3 = make_block_temporal(net.layer3, n_segment_list[2])
        net.layer4 = make_block_temporal(net.layer4, n_segment_list[3])

    elif 'blockres' in place:
        n_round = 1
        if len(list(net.layer3.children())) >= 23:
            print('=> Using n_round {} to insert temporal shift'.format(n_round))

        def make_block_temporal(stage, this_segment):
            blocks = list(stage.children())
            print('=> Processing stage with {} blocks residual'.format(len(blocks)))
            for i, b in enumerate(blocks):
                if i % n_round == 0:
                    blocks[i].conv1 = TemporalShift(b.conv1, n_segment=this_segment, n_div=n_div)
            return nn.Sequential(*blocks)

        net.layer1 = make_block_temporal(net.layer1, n_segment_list[0])
        net.layer2 = make_block_temporal(net.layer2, n_segment_list[1])
        net.layer3 = make_block_temporal(net.layer3, n_segment_list[2])
        net.layer4 = make_block_temporal(net.layer4, n_segment_list[3])

在这里插入图片描述

### 实现Temporal Shift Module (TSM) Temporal Shift Module (TSM) 是一种高效的视频理解技术,通过在卷积神经网络中引入时间维度的信息来提升模型性能[^1]。以下是有关 TSM 的实现方法及其核心概念: #### 1. **TSM的核心思想** TSM 利用通道级别的信息共享机制,在不增加额外参数的情况下捕获时间依赖关系。其主要特点是通过对输入特征图进行切片操作,将前一帧的部分通道移动到当前帧,后一帧的部分通道也移入当前帧,从而模拟时间上的信息传递[^2]。 #### 2. **PyTorch中的TSM实现** 以下是一个简单的 PyTorch 实现示例,展示了如何定义和应用 Temporal Shift 操作: ```python import torch import torch.nn as nn class TemporalShift(nn.Module): def __init__(self, net, n_segment=3, n_div=8): super(TemporalShift, self).__init__() self.net = net self.n_segment = n_segment self.fold_div = n_div def forward(self, x): nt, c, h, w = x.size() n_batch = nt // self.n_segment x = x.view(n_batch, self.n_segment, c, h, w) fold = c // self.fold_div out = torch.zeros_like(x) out[:, :-1, :fold] = x[:, 1:, :fold] # shift left out[:, 1:, fold: 2 * fold] = x[:, :-1, fold: 2 * fold] # shift right out[:, :, 2 * fold:] = x[:, :, 2 * fold:] # no shift return out.view(nt, c, h, w).contiguous() # 使用示例 base_model = nn.Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2)) tsm_layer = TemporalShift(base_model, n_segment=3, n_div=8) input_tensor = torch.randn((9, 3, 224, 224)) # 假设有3个片段 output = tsm_layer(input_tensor) print(output.shape) ``` 上述代码实现了基本的时间位移模块 `TemporalShift`,其中: - 参数 `n_segment` 表示每批数据中有多少个连续帧。 - 参数 `n_div` 控制每个通道被分割的比例,用于决定哪些通道参与左移或右移操作。 #### 3. **训练流程概述** 为了完成完整的 TSM 训练过程,可以参考以下步骤(基于 UCF101 数据集为例): - 准备好视频剪辑的数据加载器,确保每次迭代返回多个连续帧组成的批量。 - 将基础 CNN 模型(如 ResNet 或 MobileNet)替换为其对应的 TSM 版本。 - 定义损失函数并优化权重更新逻辑。 具体可参见飞桨 AI Studio 提供的相关教程链接,这些资源详细描述了从零开始搭建整个工作流的过程。 #### 4. **注意事项** 当实际部署时需要注意几个方面: - 输入张量形状应满足 `(batch_size * num_segments, channels, height, width)` 格式以便于后续处理。 - 如果 GPU 显存不足,则可以通过减少批次大小或者调整分辨率解决内存占用过高问题。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值