整体比较分散,可能很多源码都需要修改,需要有耐心。
一、数据准备
PS
调研后,上手容易代码比较简洁的是:https://github.com/Niki173/C3D/tree/main
因为源码很多参数都写死到了源码中,没有解耦,并且默认只支持ucf101和hmdb51两个数据集,所以建议最快的方式是将自己的数据集命名为ucf101然后修改对应的参数。以下均以此为前提进行说明。
1、数据组织结构
一般建议是准备原始视频文件,然后源码会自动拆帧为图片,这里以ucf101为例
抽帧前的视频组织形式,不区分train/val/test, 不同类别的视频数据放到不同的文件夹中。
Ucf101
—class_name_1
——video_1
——…
—...
PS:这里要注意视频长度不要过长,因为源码是一次性将一个视频所有帧读到内存然后进行crop指定帧数(16帧)和大小(112),所以也要看你的特征不被crop掉(源码是先缩放到128*171然后随机crop 112*112)
源码处理完后的路径如下,要注意默认源码会按照4帧间隔,6:2:2(近似)分割train/val/test集合。
Ucf101
—train
——class_name_1
———video_frames_dir_1
———…
——...
—val
——class_name_1
———video_frames_dir_1
———…
——…
—test
——class_name_1
———video_frames_dir_1
———…
——...
2、修改数据源和类别数(必选)
https://github.com/Niki173/C3D/blob/main/train.py#L28
建议复用ucf101,只修改对应的num_classes变量的值。
3、修改label信息(必选)
https://github.com/Niki173/C3D/blob/main/dataloaders/dataset.py#L58
源码仅仅实现了ucf101、hmdb51,这里有两种方式,最简单的就是复用ucf101的名字,只不过是自己的数据,然后删除掉源码的“dataloaders/ucf_labels.txt ”文件,让源码自己根据数据重新生成,也可以自己修改这个文件,文件的格式如下:
4、修改视频文件路径(必须)
这里源码的处理逻辑是自动一级一级检查图片帧目录,是否存在,并且会检查第一个类别的第一个视频的图片帧的分辨率是否符合要求。
https://github.com/Niki173/C3D/blob/main/mypath.py
5、修改视频帧尺寸(可选)
逻辑是抽帧的时候resize成这个尺寸,然后训练的时候中心crop成112。源码需要修改两个地方。
1)https://github.com/Niki173/C3D/blob/main/dataloaders/dataset.py#L31
2)https://github.com/Niki173/C3D/blob/main/dataloaders/dataset.py#L105
6、修改归一化特征值(可选)
https://github.com/Niki173/C3D/blob/main/dataloaders/dataset.py#L208
7、修改是否需要test(可选)
一般现实工程数据较少时或者上线有其他测试集,建议关闭test分割,方式就是注销相关代码,下面标红框。
https://github.com/Niki173/C3D/blob/main/dataloaders/dataset.py#L115
https://github.com/Niki173/C3D/blob/main/train.py#L23
https://github.com/Niki173/C3D/blob/main/train.py#L100
注销红框
8、修改抽帧间隔(可选)
默认是4秒。
https://github.com/Niki173/C3D/blob/main/dataloaders/dataset.py#L170
二、训练超参数
https://github.com/Niki173/C3D/blob/main/train.py#L21
三、网络结构
1、C3D结构
2、R(2+1)D结构
3、区别
1)R2D模块就是传统的2d卷积,将输入c×l×h×w看作是cl×h×w(把多张当作一整张),只是将2d卷积作用于multi-frames上。
2)f-R2D,采取R2D相反的方式,分别对每帧做操作,在最后全局池化层在做所有帧的信息融合。
3)C3D:就是将时间维度单独成一维。网络结构如上面的图。
4)R3D模块就是前面讲的C3D模块,只不过是放到ResNet网络中。
5)R(2+1)D:作者设计了2d卷积和1d卷积filter个数的匹配公式。相比于R3D,虽然参数没变,但由于R(2+1)D添加更多Relu激活层,模型的表达能力应该更强,同时也更容易训练优化。
6)P3D:R(2+1)D更接近P3D-A,把R(2+1)D都设计为相同的block,但P3D的第一层使用的是2d卷积。
开源实现
https://github.com/HHTseng/video-classification
https://github.com/kenshohara/3D-ResNets-PyTorch
几个不同网络区别:[论文笔记] C3D | P3D | R2D - 知乎
C3D代码总结(Pytorch)-CSDN博客