以下链接是个人关于mmaction2(SlowFast-动作识别) 所有见解,如有错误欢迎大家指出,我会第一时间纠正。有兴趣的朋友可以加微信:a944284742相互讨论技术。若是帮助到了你什么,一定要记得点赞!因为这是对我最大的鼓励。
动作识别0-00:mmaction2(SlowFast)-目录-史上最新无死角讲解
该章节的内容比较单调,把 cfg 文件注释单独作为一篇博客列出来,是为了大家方便查找和分析(如果有错误的地方,需要大家及时指出)。阅读过前面博客的朋友,我相信大家注意到了,本人的configs/recognition/slowfast/my_slowfast_r50_4x16x1_256e_ucf101_rgb.py复制于configs/recognition/slowfast/slowfast_r50_4x16x1_256e_kinetics400_rgb.py,然后再上面做了一些修改(这里解决了前面CosineAnealing报错的问题,修改成CosineAnnealing即可)。本人注释如下:
model = dict(
type='Recognizer3D', # 使用3D识别卷积(相对于2D,增加了时间维度)
backbone=dict( # 主干网络相关配置
type='ResNet3dSlowFast', #
pretrained=None,
resample_rate=8, # tau, 其对应论文中的参数τ
speed_ratio=8, # alpha, 其对应论文中的参数α
channel_ratio=8, # beta_inv, 其对应论文中β的倒数
slow_pathway=dict( # 慢速路径
type='resnet3d', # 使用resnet3d网络
depth=50, # 其深度为50
pretrained=None, # 不使用预训练模型
lateral=True, # 是否使用侧面链接的方式
conv1_kernel=(1, 7, 7), # 第一层卷积核大小
dilations=(1, 1, 1, 1),
conv1_stride_t=1, # 第一层卷积层在时序维度上的步伐
pool1_stride_t=1, # 第一个池化层在时序方向上的步伐
inflate=(0, 0, 1, 1),
norm_eval=False), # 验证的时候是否使用正则化
fast_pathway=dict( # 快速路径
type='resnet3d', # 使用resnet3d网络
depth=50, # 其深度为50
pretrained=None, # 不使用预训练模型
lateral=False, # 是否使用侧面链接的方式
base_channels=8, # 基础通道数目
conv1_kernel=(5, 7, 7), # 第一层卷积核大小
conv1_stride_t=1, # 第一层卷积层在时序维度上的步伐
pool1_stride_t=1, # 第一个池化层在时序方向上的步伐
norm_eval=False)), # 验证的时候是否使用正则化
cls_head=dict( # 头部的分类网络
type='SlowFastHead',
in_channels=2304, # 2048+256,特征连接的通道数
#num_classes=400,
num_classes=101, # 训练数据的类别总数
spatial_type='avg', #
dropout_ratio=0.5)) # 放置过拟合
train_cfg = None
test_cfg = dict(average_clips=None)
# 来自源slowfast_r50_4x16x1_256e_kinetics400_rgb.py
#dataset_type = 'RawframeDataset'
#data_root = 'data/kinetics400/rawframes_train'
#data_root_val = 'data/kinetics400/rawframes_val'
#ann_file_train = 'data/kinetics400/kinetics400_train_list_rawframes.txt'
#ann_file_val = 'data/kinetics400/kinetics400_val_list_rawframes.txt'
#ann_file_test = 'data/kinetics400/kinetics400_val_list_rawframes.txt'
# 如果使用图像帧的方式训练
# dataset_type = 'RawframeDataset'
# data_root = 'data/ucf101/rawframes'
# data_root_val = 'data/ucf101/rawframes'
# ann_file_train = 'data/ucf101/ucf101_train_split_1_rawframes.txt'
# ann_file_val = 'data/ucf101/ucf101_val_split_1_rawframes.txt'
# ann_file_test = 'data/ucf101/ucf101_val_split_1_rawframes.txt'
# 如果使用加载源视频进行训练
dataset_type = 'VideoDataset'
data_root = 'data/ucf101/videos'
data_root_val = 'data/ucf101/videos'
ann_file_train = 'data/ucf101/ucf101_train_split_1_videos.txt'
ann_file_val = 'data/ucf101/ucf101_val_split_1_videos.txt'
ann_file_test = 'data/ucf101/ucf101_val_split_1_videos.txt'
# 图像进行正则化处理
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_bgr=False)
# 训练,验证,评估数据转换的序列
train_pipeline = [
dict(type='DecordInit'), # 直接加载视频数据需要需要此项配置
# num_clips=1表示采集一个clip(可以简单理解为batch_size=1,后续其会被覆盖),
# clip_len=32,frame_interval=2 表示沿时序维度方向,以间隔为2帧的方式,采集32帧图像
#dict(type='SampleFrames', clip_len=32, frame_interval=2, num_clips=1),
dict(type='SampleFrames', clip_len=16, frame_interval=2, num_clips=1),
#dict(type='FrameSelector'), # 如果加载数据帧进行采样需要此项配置
dict(type='DecordDecode'), # # 如果直接加载视频数据需要需要此项配置
# 对图像大小进行缩放
dict(type='Resize', scale=(-1, 256)),
# 进行随机剪裁
dict(type='RandomResizedCrop'),
# 对剪裁过的图像进行缩放
dict(type='Resize', scale=(224, 224), keep_ratio=False),
# 以0.5的概率进行水平翻转
dict(type='Flip', flip_ratio=0.5),
# 进行正则化处理
dict(type='Normalize', **img_norm_cfg),
# 调整输出形状
dict(type='FormatShape', input_format='NCTHW'),
# 统一数据格式
dict(type='Collect', keys=['imgs', 'label'], meta_keys=[]),
# 转换为pytorch需要的Tensor数组
dict(type='ToTensor', keys=['imgs', 'label'])
]
# 同上
val_pipeline = [
dict(type='DecordInit'),
#dict(type='SampleFrames',clip_len=32,frame_interval=2,num_clips=1,test_mode=True),
dict(type='SampleFrames', clip_len=16, frame_interval=2, num_clips=1, test_mode=True),
#dict(type='FrameSelector'),
dict(type='DecordDecode'),
dict(type='Resize', scale=(-1, 256)),
dict(type='CenterCrop', crop_size=224),
dict(type='Flip', flip_ratio=0),
dict(type='Normalize', **img_norm_cfg),
dict(type='FormatShape', input_format='NCTHW'),
dict(type='Collect', keys=['imgs', 'label'], meta_keys=[]),
dict(type='ToTensor', keys=['imgs'])
]
# 同上
test_pipeline = [
dict(type='DecordInit'),
#dict(type='SampleFrames',clip_len=32,frame_interval=2,num_clips=1,test_mode=True),
dict(type='SampleFrames', clip_len=16, frame_interval=2, num_clips=1, test_mode=True),
#dict(type='FrameSelector'),
dict(type='DecordDecode'),
dict(type='Resize', scale=(-1, 256)),
dict(type='ThreeCrop', crop_size=256),
dict(type='Flip', flip_ratio=0),
dict(type='Normalize', **img_norm_cfg),
dict(type='FormatShape', input_format='NCTHW'),
dict(type='Collect', keys=['imgs', 'label'], meta_keys=[]),
dict(type='ToTensor', keys=['imgs'])
]
# 数据加载的相关配置
data = dict(
videos_per_gpu=4, #每个GPU加载8个视频数据,可以理解为batch_size
workers_per_gpu=4, #每个GPU分配4个线程
# 指定训练,验证,测试数据集路径文件夹配置
train=dict(
type=dataset_type,
ann_file=ann_file_train,
data_prefix=data_root,
pipeline=train_pipeline),
val=dict(
type=dataset_type,
ann_file=ann_file_val,
data_prefix=data_root_val,
pipeline=val_pipeline),
test=dict(
type=dataset_type,
ann_file=ann_file_test,
data_prefix=data_root_val,
pipeline=test_pipeline))
# optimizer,模型训练的优化器
optimizer = dict(
type='SGD', lr=0.1, momentum=0.9,
weight_decay=0.0001) # this lr is used for 8 gpus
# 优化器的相关配置
optimizer_config = dict(grad_clip=dict(max_norm=40, norm_type=2))
# learning policy,学习率的衰减策略
lr_config = dict(policy='CosineAnealing', min_lr=0)
#lr_config = dict(policy='step', step=[40,60])
# 总共迭代次数
total_epochs = 256
# 每间隔多少个epoch进行一次模型保存
# checkpoint_config = dict(interval=4)
checkpoint_config = dict(interval=1)
workflow = [('train', 1)]
# 设置模型评估验证的方式
evaluation = dict(
interval=5, metrics=['top_k_accuracy', 'mean_class_accuracy'], topk=(1, 5))
# log打印保存的相关设置
log_config = dict(
interval=20,
hooks=[
dict(type='TextLoggerHook'),
# dict(type='TensorboardLoggerHook'),
])
dist_params = dict(backend='nccl')
# 信息打印等级
log_level = 'INFO'
# 输出保存目录
work_dir = './work_dirs/slowfast_r50_3d_4x16x1_256e_kinetics400_rgb'
# 加载的预训练模型
load_from = None
# 是否继续训练
resume_from = None
# 寻找没用的参数
find_unused_parameters = False