百度Paddle视频分类论文3D Resnet论文复现

前段时间参加了百度深度学习论文复现营——视频分类论文复现,在此做一些学习记录,希望可以帮助到有需要的朋友

学习资源

百度顶会论文复现营 https://aistudio.baidu.com/aistudio/education/group/info/1340

1. 视频分类论文综述

1.1 任务介绍

任务:将视频分到指定类别集合的一个或多个,精细粒度:主要行为识别
应用场景:视频自动标注、视频搜索、监控视频行为理解、自动驾驶、互联网视频合规审查
数据集

  • HMDB-51 (2011)
  • UCF-101(2012)
  • Kinetics(2017~2019)

1.2 任务介绍

  • 视频由空间维度和时间维度组成
  • 静态图像特征:场景/目标及其关系等
  • 运动特征:目标的帧间运动等
  • 音频特征:语音内容、说话人等
  • 外部特征:目标关系先验、运动模式等

1.3 主流方法

  • 双流网络
    人类有两条视觉信息处理通道,一条侧重于静态视觉场景/目标,另一条侧重于运动。
    输入:静态图像和两帧图像之间的光流
  • 静态图像特征融合
    提取视频不同时刻多帧图像的特征,聚合生成视频级特征,进而分类。
    代表:LRCN(CNN+LSTN)、ActionVLAD、Attention Cluster
  • 3D卷积
    C3D、P3D、I3D(将2D卷积膨胀为3D卷积的方法)

1.4 趋势展望

  • 训练加速:挂载成熟模块(无需训练)、避免复杂光流计算
  • 测试加速:轻量级主干网(加速推理)
  • 设计轻量化的视频分类模型
  • 引入新的信息模态(如:人体关键点分布)

2. 复现论文介绍:3D Resnet

Reference:(ICCV2017 workshop)Learning Spatio-Temporal Features with 3D Residual Networks for Action Recognition
原文地址:论文
Github地址:代码
点评:整篇论文的创新性在于拓展了2D Resnet,以及贡献代码的简洁性

3. 复现步骤

3.1 整体流程

  • 数据集获取 √
  • 数据预处理
  • 构建前向网络 √
  • 构建反向传播 √
  • 精度对齐:小数据集训练(2个epoch)

3.2 精度对齐

  • 去除随机性:去除dropout等 √
  • 数据对齐:输入数据 √
  • 模型参数对齐:
    pytorch 和 Paddle 网络参数输出并手动对齐 √
    pytorch预训练模型参数转换为Paddle √
    将保存的模型载入并设置Paddle模型初始化 √
  • Loss对齐
  • 小规模实验

4. 实际复现问题

因实际复现时间受限,实际完成了√部分的复现,最后测试集分类准确率为44%,验收标准为92%

(1)借用百度baseline

参考项目:https://aistudio.baidu.com/aistudio/projectdetail/674480
调用config文件报错 KeyError:’TRAIN’
原因是路径出错,configs写成了config,不过报错应该先提示找不到文件比较人性化。
此外配置中对应参数应改为论文参数:

seg_num = 1 #划分为几段
seglen = 16 #每个片段取n帧(随机抽)

(2)BatchNorm3d 对应paddle的BatchNorm

torch 与 paddle API对照表中对应的应该是batch_norm,实际应该用BatchNorm
在这里插入图片描述
在这里插入图片描述

(3)Paddle中的API勘误

Fluid.dygrapy.Conv3D( num_fliters = ) 报错提示没有num_fliters 参数,实际是num_filters
在这里插入图片描述

(4)如何遍历模块的问题

Pytorch中nn.moudles可以返回网络各层模块,对应paddle中用fluid.dygraph.Layer.sublayers 代替

总结

第一次复现paddle,中间也有很多对原文代码不理解复现不到位的地方,欢迎大家指正
Github 地址:Resnet3DPaddle
Ai Studio 地址:Paddle论文复现3DResnet

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用 PaddlePaddle 框架实现 ResNet 网络的代码: ```python import paddle import paddle.nn as nn class BasicBlock(nn.Layer): expansion = 1 def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(BasicBlock, self).__init__() self.conv1 = nn.Conv2D(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias_attr=False) self.bn1 = nn.BatchNorm2D(out_channels) self.relu = nn.ReLU() self.conv2 = nn.Conv2D(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias_attr=False) self.bn2 = nn.BatchNorm2D(out_channels) self.downsample = downsample self.stride = stride def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out class Bottleneck(nn.Layer): expansion = 4 def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(Bottleneck, self).__init__() self.conv1 = nn.Conv2D(in_channels, out_channels, kernel_size=1, bias_attr=False) self.bn1 = nn.BatchNorm2D(out_channels) self.conv2 = nn.Conv2D(out_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias_attr=False) self.bn2 = nn.BatchNorm2D(out_channels) self.conv3 = nn.Conv2D(out_channels, out_channels * self.expansion, kernel_size=1, bias_attr=False) self.bn3 = nn.BatchNorm2D(out_channels * self.expansion) self.relu = nn.ReLU() self.downsample = downsample self.stride = stride def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) out = self.relu(out) out = self.conv3(out) out = self.bn3(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out class ResNet(nn.Layer): def __init__(self, block, layers, num_classes=1000): super(ResNet, self).__init__() self.in_channels = 64 self.conv1 = nn.Conv2D(3, 64, kernel_size=7, stride=2, padding=3, bias_attr=False) self.bn1 = nn.BatchNorm2D(64) self.relu = nn.ReLU() self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1) self.layer1 = self._make_layer(block, 64, layers[0]) self.layer2 = self._make_layer(block, 128, layers[1], stride=2) self.layer3 = self._make_layer(block, 256, layers[2], stride=2) self.layer4 = self._make_layer(block, 512, layers[3], stride=2) self.avgpool = nn.AdaptiveAvgPool2D((1, 1)) self.fc = nn.Linear(512 * block.expansion, num_classes) def _make_layer(self, block, out_channels, blocks, stride=1): downsample = None if stride != 1 or self.in_channels != out_channels * block.expansion: downsample = nn.Sequential( nn.Conv2D(self.in_channels, out_channels * block.expansion, kernel_size=1, stride=stride, bias_attr=False), nn.BatchNorm2D(out_channels * block.expansion) ) layers = [] layers.append(block(self.in_channels, out_channels, stride, downsample)) self.in_channels = out_channels * block.expansion for _ in range(1, blocks): layers.append(block(self.in_channels, out_channels)) return nn.Sequential(*layers) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu(x) x = self.maxpool(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avgpool(x) x = paddle.flatten(x, 1) x = self.fc(x) return x def resnet18(num_classes=1000): return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes) def resnet34(num_classes=1000): return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes) def resnet50(num_classes=1000): return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes) def resnet101(num_classes=1000): return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes) def resnet152(num_classes=1000): return ResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes) ``` 以上代码定义了 BasicBlock 和 Bottleneck 两个块,并使用它们构建了 ResNet 模型。其中,ResNet 可以选择使用不同的块和层数来构建不同版本的网络。通过调用 `resnet18()`,`resnet34()`,`resnet50()`,`resnet101()` 和 `resnet152()` 函数可以得到不同版本的 ResNet 网络。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值