C3D的视频分类

article/2025/10/14 15:47:26

很久之前做了C3D的视频分类,现在详细把整个项目的细节描述一下。
首先介绍一下C3D:对于一段视频来说,它是连续的帧图像叠加起来的,所以可以考虑在生成通道图像的时候,把多帧图像叠加的特性讨论进去。

一个视频段输入,其大小为 c∗l∗h∗w ,其中c为图像通道(一般为3),l为视频序列的长度,h和w分别为视频的宽与高。进行一次kernel size为3∗3∗3,stride为1,padding=True,滤波器个数为K的3D 卷积后,输出的大小为K∗l∗h∗w。池化同理。

作者对卷积核做了研究,发现3*3的卷积核最有效。基于3D卷积操作,共有8次卷积操作,4次池化操作。其中卷积核的大小均为3∗3∗3,步长为1∗1∗1。池化核的大小为2∗2∗2,步长为2∗2∗2,但第一层池化除外,其大小和步长均为1∗2∗2。这是为了不过早缩减时序上的长度。最终网络在经过两次全连接层和softmax层后就得到了最终的输出结果。网络的输入尺寸为3∗16∗112∗112,即一次输入16帧图像。
github地址:https://github.com/hx173149/C3D-tensorflow
训练过程:首先按照train.list,test.list将文件分类。然后使用ffmpeg,将视频分割,这里每5帧取一张图片。
模型代码:

def conv3d(name, l_input, w, b):  	return tf.nn.bias_add(            tf.nn.conv3d(l_input, w, strides=[1, 1, 1, 1, 1], padding='SAME'),          b          )def max_pool(name, l_input, k):   
return tf.nn.max_pool3d(l_input, ksize=[1, k, 2, 2, 1], strides=[1, k, 2, 2, 1], padding='SAME', name=name)def inference_c3d(_X, _dropout, batch_size, _weights, _biases):# Convolution Layer  conv1 = conv3d('conv1', _X, _weights['wc1'], _biases['bc1'])  conv1 = tf.nn.relu(conv1, 'relu1')  pool1 = max_pool('pool1', conv1, k=1)# Convolution Layer  conv2 = conv3d('conv2', pool1, _weights['wc2'], _biases['bc2'])  conv2 = tf.nn.relu(conv2, 'relu2')  pool2 = max_pool('pool2', conv2, k=2)# Convolution Layer  conv3 = conv3d('conv3a', pool2, _weights['wc3a'], _biases['bc3a'])  conv3 = tf.nn.relu(conv3, 'relu3a')  conv3 = conv3d('conv3b', conv3, _weights['wc3b'], _biases['bc3b'])  conv3 = tf.nn.relu(conv3, 'relu3b')  pool3 = max_pool('pool3', conv3, k=2)# Convolution Layer  conv4 = conv3d('conv4a', pool3, _weights['wc4a'], _biases['bc4a'])  conv4 = tf.nn.relu(conv4, 'relu4a')  conv4 = conv3d('conv4b', conv4, _weights['wc4b'], _biases['bc4b'])  conv4 = tf.nn.relu(conv4, 'relu4b')  pool4 = max_pool('pool4', conv4, k=2)# Convolution Layer  conv5 = conv3d('conv5a', pool4, _weights['wc5a'], _biases['bc5a'])  conv5 = tf.nn.relu(conv5, 'relu5a')  conv5 = conv3d('conv5b', conv5, _weights['wc5b'], _biases['bc5b'])  conv5 = tf.nn.relu(conv5, 'relu5b')  pool5 = max_pool('pool5', conv5, k=2)# Fully connected layer  pool5 = tf.transpose(pool5, perm=[0,1,4,2,3])  dense1 = tf.reshape(pool5, [batch_size, _weights['wd1'].get_shape().as_list()[0]]) # Reshape conv3 output to fit dense layer input  dense1 = tf.matmul(dense1, _weights['wd1']) + _biases['bd1']dense1 = tf.nn.relu(dense1, name='fc1') # Relu activation  dense1 = tf.nn.dropout(dense1, _dropout)dense2 = tf.nn.relu(tf.matmul(dense1, _weights['wd2']) + _biases['bd2'], name='fc2') # Relu activation  dense2 = tf.nn.dropout(dense2, _dropout)# Output: class prediction  out = tf.matmul(dense2, _weights['out']) + _biases['out']return out

模型的损失函数:

def tower_loss(name_scope, logit, labels):  cross_entropy_mean = tf.reduce_mean(                  tf.nn.sparse_softmax_cross_entropy_with_logits   (labels=labels,logits=logit)                  )       #交叉熵损失函数tf.summary.scalar(                  name_scope + '_cross_entropy',                  cross_entropy_mean                  )  weight_decay_loss = tf.get_collection('weightdecay_losses')  tf.summary.scalar(name_scope + '_weight_decay_loss', tf.reduce_mean(weight_decay_loss) )# Calculate the total loss for the current tower.  total_loss = cross_entropy_mean + weight_decay_loss   tf.summary.scalar(name_scope + '_total_loss', tf.reduce_mean(total_loss) )  return total_loss

损失函数为交叉熵损失函数+regularization正则化(weight_decay)。
weight_decay:权衰量,weight decay是放在正则项(regularization)前面的一个系数,正则项一般指示模型的复杂度,所以weight decay的作用是调节模型复杂度对损失函数的影响,它是为了调节正则项在损失函数中占的权重。权重越大,则说明正则项对损失函数的影响越大。

另一种理解是:没有使用regularization的时候,网络训练只是通过交叉熵损失函数改变权值,这时候梯度下降的通道只有一个,当到达一定效果时,就容易在局部极小值的附近打转。增加regularization,使得改变了整个模型的梯度,跳出了局部极值的怪圈,使得整个函数目标函数分布改变了。regularization loss 的作用是不让某一权值很大,并调节其他权值,使得所有权值都相差在一定范围,使得各个神经元都能充分使用。有时需要交叉训练,比如一会儿让用于分类发loss做主导(learning_rate大,weight_decay小),有时则反过来,有时都小。

这里参数初始化的方式使用了Xavier初始化方法。

迭代更新模型的时候,使用了指数滑动平均。

variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY)  
variables_averages_op = variable_averages.apply(tf.trainable_variables())    
train_op = tf.group(apply_gradient_op1, apply_gradient_op2, variables_averages_op)

介绍一下指数滑动平均:
在采用随机梯度下降算法训练神经网络时,使用 tf.train.ExponentialMovingAverage 滑动平均操作的意义在于提高模型在测试数据上的健壮性(robustness)。在训练神经网络时,不断保持和更新每个参数的滑动平均值,在验证和测试时,参数的值使用其滑动平均值,能有效提高神经网络的准确率。

在这里插入图片描述
decay用于控制模型更新的速度。ExponentialMovingAverage 对每一个(待更新训练学习的)变量(variable)都会维护一个影子变量(shadow variable)。影子变量的初始值就是这个变量的初始值,
decay越大越趋于稳定。实际运用中,decay 一般会设置为十分接近 1 的常数(0.99或0.999)。为了使得模型在训练的初始阶段更新得更快,ExponentialMovingAverage 还提供了 num_updates 参数来动态设置 decay 的大小:
在这里插入图片描述
关于学习率:
这个模型把特征提取和分类分别处理

 opt_stable = tf.train.AdamOptimizer(1e-4)opt_finetuning = tf.train.AdamOptimizer(1e-3)...varlist2 = [ weights['out'],biases['out'] ]varlist1 = list( set(weights.values() + biases.values()) - set(varlist2) )...grads1 = opt_stable.compute_gradients(loss, varlist1)grads2 = opt_finetuning.compute_gradients(loss, varlist2)

在这篇github代码里,作者提供了预训练模型,所以分别采用学习率为0.0001和0.001的Adam优化算法来优化网络的特征提取器和分类器。
自己对于模型优化的看法:
这个模型比较老了,使用了dropout正则化的方式,可以将其替换成BN层。同时可以参考resnet结构,把时间和空间的维度分别拿出来进行卷积操作,如时间:3∗1∗1 + 空间:1∗3∗3。同时可以考虑光流,把光流也作为另一个模型的输入,将两个模型融合起来。


http://chatgpt.dhexx.cn/article/AHT0CjDo.shtml

相关文章

C3D源码解读(基于3D卷积的动作识别)

UCF数据集下载地址:https://www.crcv.ucf.edu/data/UCF101.php 1.推理效果与项目配置 执行inference.py,需要指定3个参数,第一个是标签文件地址,存储了各个标签的含义,第二个是权重文件地址,第三个是要进行推理的视频…

C3D代码总结(Pytorch)

C3D代码总结(Pytorch) github:https://github.com/Niki173/C3D 介绍数据介绍文件介绍具体操作流程运行结果 介绍: 本次C3D模型用的是pytorch框架,我们在UCF101和HMDB51数据集上训练这些模型,本次实验以U…

C3D论文笔记

论文链接:http://vlg.cs.dartmouth.edu/c3d/c3d_video.pdf 代码链接:https://github.com/jfzhang95/pytorch-video-recognition 1. C3D是什么? C3D,全称Convolutional 3D,即3D卷积。3D卷积方法是把视频划分成很多固定…

C3D网络介绍

1. 模型简介 C3D模型广泛用于3D视觉任务。C3D网络的构造类似于常见的2D卷积网,主要区别在于C3D使用像卷积3D这样的3D操作,而2D卷积网则是通常的2D架构。要了解有关C3D网络的更多信息,您可以阅读原始论文学习3D卷积网络的时空特征。 3D卷积图…

视频分析模型(行为识别):C3D

C3D 文章目录 C3D1. 简介1.1 背景1.2 C3D特点1.3 视频描述符1.4 C3D的结果 2. 架构2.1 工作流程2.2 网络结构2.3 3D卷积和池化2.4 kernel 的时间深度 3. 可视化3.1 特征图3.2 特征嵌入 4. 应用场景4.1 动作识别4.2 动作相似度标注4.3 场景和目标识别4.4 运行时间分析 1. 简介 …

C3D论文精读

论文地址:https://vlg.cs.dartmouth.edu/c3d/c3d_video.pdf Abstract 作者的研究结果有三个方面: 1)与二维相比,三维卷积网更适合时空特征学习;2)所有层具有333的小卷积核的同构架构是3D卷积网的最佳架构之一;3)学习到的特征&am…

基于C3D网络的视频分析与动作识别

卷积神经网络(CNN)被广泛应用于计算机视觉中,包括分类、检测、分割等任务。这些任务一般都是针对图像进行的,使用的是二维卷积(即卷积核的维度为二维)。而对于基于视频分析的问题,2D convolutio…

《QDebug 2022年12月》

一、Qt Widgets 问题交流 二、Qt Quick 问题交流 1、在 C 中关联 QQuickWindow 的 closing 信号提示 "使用了未定义类型QQuickCloseEvent" 因为 closing 信号中的参数类型是 private 模块中定义的,但是通过第二句提示我们知道找到了完整定义才能使用 Q_…

4.4 案例8 用qDebug()输出信息

本案例对应的源代码目录:src/chapter04/ks04_04。 在开发C/S(Client/Server,客户端/服务端)模式的软件时,服务端程序(有时也称作服务)经常运行在两种模式下。 (1)终端模…

Qt扫盲-QDebug理论总结

QDebug理论使用总结 一、概述二、使用1. 基础使用2. 格式化选项3.将自定义类型写入流 一、概述 每当开发人员需要将调试或跟踪信息写入设备、文件、字符串或控制台时,都会使用QDebug。这个就可以方便我们调试,基本上Qt所有的内容都能通过调试打印出来&a…

Qt重定向QDebug,自定义一个简易的日志管理类

0.前言 相对于第三方的日志库,在 Qt 中使用 QDebug 打印更便捷,有时候也需要对 QDebug 输出进行重定向,如写入文件等。 在 Qt4 中使用 qInstallMsgHandler 函数设置重定向的函数指针: typedef void (*QtMsgHandler)(QtMsgType,…

qDebug 控制台输出

做个小笔记:qDebug 控制台输出 Ⅰ&#xff1a;*.pro文件中添加 win32:CONFIG console Ⅱ&#xff1a;配置项目运行设置&#xff0c;将Run in terminal 复选框打勾 Ⅲ&#xff1a;添加头文件 #include <QDebug> Ⅳ&#xff1a;用qDebug()<<"xxxx";输…

Qt ——debug调试

程序调试&#xff1a; 方法一&#xff1a;断点调试法方法二&#xff1a;使用qDebug()函数 方法一&#xff1a;断点调试法 我们可以在程序加断点&#xff0c;然后再利用单步调试查看变量的值是否异常。 1. 设置断点。 可以左击相应的代码行前的区域&#xff08;下图用红色框标…

jadx反编译—下载和使用(傻瓜教程,非常详细)

原文地址 一、在GitHub上直接下载 下载地址 可以下这个版本&#xff1a; 二、运行图形化界面 1、将zip文件解压后定位到在lib文件夹中&#xff0c;在此处打开命令行 2、运行jadx-gui-0.7.1.jar&#xff08;前提是已经装好了JDK1.8&#xff09; 命令如下&#xff1a; <sp…

Android APK 反编译工具 JADX

文章目录 JADX 介绍JADX 安装JADX 使用补充APK 目录结构含义APK 打包流程 JADX 介绍 GitHub 地址&#xff1a;https://github.com/skylot/jadx JADX 支持将 APK, dex, aar, zip 中的 dalvik 字节码反编译为 Java 代码&#xff0c;也支持反编译 AndroidManifest.xml 和 resource…

jadx-gui 重命名功能

jad-gui 是大家常用的一款反编译工具&#xff0c;其中有些小使用技巧可以帮助大家更快的“学习”知识。 安装 方法参考项目GitHub主页 重命名 最新的 1.2.0 版本支持了方法、类、字段的重命名&#xff0c;这是一个非常有用的功能&#xff0c;之前反编译出来的都是混淆后的名…

Android 反编译神器jadx的使用

一、前言 今天介绍一个非常好用的反编译的工具 jadx 。jadx 的功能非常的强大&#xff0c;对我而言&#xff0c;基本上满足日常反编译需求。 jadx 优点&#xff1a; 图形化的界面。拖拽式的操作。反编译输出 Java 代码。导出 Gradle 工程。 这些优点都让 jadx 成为我反编译…

jadx工具windows下载

Release v1.2.0 skylot/jadx GitHubDex to Java decompiler. Contribute to skylot/jadx development by creating an account on GitHub.https://github.com/skylot/jadx/releases/tag/v1.2.0选择第三个jadx-gui-1.2.0-with-jre-win.zip解压exe可正常使用

jadx反编译—下载和使用

一、在GitHub上直接下载 https://github.com/skylot/jadx 可以下这个版本&#xff1a; 二、运行图形化界面 1、将zip文件解压后定位到在lib文件夹中&#xff0c;在此处打开命令行 2、运行jadx-gui-0.7.1.jar&#xff08;前提是已经装好了JDK1.8&#xff09; 命令如下&#xf…

jadx初识

一.jadx介绍 一款相对流行的反编译工具 下载&#xff1a;https://github.com/skylot/jadx/releases/tag/v1.0.0 解压后得到这么几个文件&#xff1a; 启动&#xff1a;&#xff08;以下来两个文件都可以&#xff09; 启动后的界面&#xff1a; 二.使用 打开之后&#xff0c;你可…