目录
0 参考资料
MMAction2 学习笔记 (四)——实用工具及demo演示:https://blog.youkuaiyun.com/Jason_____Wang/article/details/121488466
mmaction2官网_日志分析:https://mmaction2.readthedocs.io/zh_CN/latest/useful_tools.html#id2
mmaction2官网_训练配置:https://mmaction2.readthedocs.io/zh_CN/latest/getting_started.html#id10
mmaction2官网_如何编写配置文件:https://mmaction2.readthedocs.io/zh_CN/latest/tutorials/1_config.html#id7
1 GPU平台
使用的AI极链平台搭建:https://cloud.videojj.com/auth/register?inviter=18452&activityChannel=student_invite
这篇博客直说训练配置、日志分析、测试结果分析
自定义数据集或者训练ava数据集可以参考以前的博客:
自定义ava数据集及训练与测试 完整版 时空动作/行为 视频数据集制作 yolov5, deep sort, VIA MMAction, SlowFast
【mmaction2 slowfast 行为分析(商用级别)】总目录
2 训练配置(Training setting)
对日志的分析,当然是需要先进行训练咯,为了能得到更加详细全面的训练日志,我们需要先知道,训练有哪些配置?
2.1 官网的训练配置文档
在mmaction2的中训练配置(下面的大部分是从官网的文档里抄的,有中英对照处即为我抄的)
所有的输出(日志文件和模型权重文件)会被将保存到工作目录下。工作目录通过配置文件中的参数 work_dir
指定。
All outputs (log files and checkpoints) will be saved to the working directory, which is specified by
work_dir
in the config file.
默认情况下,MMAction2 在每个周期后会在验证集上评估模型,可以通过在训练配置中修改 interval 参数来更改评估间隔
By default we evaluate the model on the validation set after each epoch, you can change the evaluation interval by modifying the interval argument in the training config
evaluation = dict(interval=5) # This evaluate the model per 5 epoch.
上面这段代码在(其中一个config):https://github.com/open-mmlab/mmaction2/blob/master/configs/detection/ava/slowfast_context_kinetics_pretrained_r50_4x16x1_20e_ava_rgb.py
根据 Linear Scaling Rule,当 GPU 数量或每个 GPU 上的视频批大小改变时,用户可根据批大小按比例地调整学习率
,如,当 4 GPUs x 2 video/gpu 时,lr=0.01;当 16 GPUs x 4 video/gpu 时,lr=0.08。
According to the Linear Scaling Rule, you need to set the
learning rate
proportional to the batch size if you use different GPUs or videos per GPU, e.g., lr=0.01 for 4 GPUs x 2 video/gpu and lr=0.08 for 16 GPUs x 4 video/gpu.
python tools/train.py ${CONFIG_FILE} [optional arguments]
接下来说说可选参数(Optional arguments):
--validate (强烈建议)
:在训练期间每 k 个周期进行一次验证(默认值为 5,可通过修改每个配置文件中的 evaluation 字典变量的 interval 值进行改变)。
--validate (strongly recommended)
: Perform evaluation at every k (default value is 5, which can be modified by changing the interval value in evaluation dict in each config file) epochs during the training.--test-last
:在训练结束后使用最后一个检查点的参数进行测试,将测试结果存储在 ${WORK_DIR}/last_pred.pkl 中。
--test-last
: Test the final checkpoint when training is over, save the prediction to ${WORK_DIR}/last_pred.pkl.--test-best
:在训练结束后使用效果最好的检查点的参数进行测试,将测试结果存储在 ${WORK_DIR}/best_pred.pkl 中。
--test-best
: Test the best checkpoint when training is over, save the prediction to ${WORK_DIR}/best_pred.pkl.--work-dir ${WORK_DIR}
:覆盖配置文件中指定的工作目录。
--work-dir ${WORK_DIR}
: Override the working directory specified in the config file.--resume-from ${CHECKPOINT_FILE}
:从以前的模型权重文件恢复训练。
--resume-from ${CHECKPOINT_FILE}
: Resume from a previous checkpoint file.
resume-from 和 load-from 的不同点: resume-from 加载模型参数和优化器状态,并且保留检查点所在的周期数,常被用于恢复意外被中断的训练。 load-from 只加载模型参数,但周期数从 0 开始计数,常被用于微调模型。
Difference between resume-from and load-from: resume-from loads both the model weights and optimizer status, and the epoch is also inherited from the specified checkpoint. It is usually used for resuming the training process that is interrupted accidentally. load-from only loads the model weights and the training epoch starts from 0. It is usually used for finetuning.
2.2 我的训练配置
我所采用的单个GPU上的指令如下:
cd /home/MPCLST/mmaction2_YF
python tools/train.py configs/detection/ava/my_slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb.py --validate --test-best
其中
/home/MPCLST/mmaction2_YF为mmation2的地址
configs/detection/ava/my_slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb.py为配置文件地址
我这里就讲训练后的配置文件放在csdn中,供大家下载使用
22-8-4 mmaction2 slowfast训练日志:https://download.youkuaiyun.com/download/WhiffeYF/86337607
包含配置文件:my_slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb.py
训练结束后使用最好的checkpoint的参数进行测试,将测试结果存储在:part_0.pkl
训练过程的记录:20220804_185539.log.json
然后说说训练配置文件有哪些地方我修改了:
首先修改类别数量,我的动作类别71个,所有num_classes = 动作类别数 + 1(背景) = 72
在data中也要加入num_classes,因为默认的是80,不添加的话,训练时会出现维度不匹配的情况。
data_root、anno_root 修改为自定义数据集的位置
2.3训练过程中遇到的问题:
在训练结束后,准备对最好的训练模型进行测试结果记录的时候,出现以下错误
...
2022-08-05 18:51:43,918 - mmaction - INFO - Epoch(val) [50][77] mAP@0.5IOU: 0.1576
INFO:mmaction:Epoch(val) [50][77] mAP@0.5IOU: 0.1576
2022-08-05 18:51:46,160 - mmaction - INFO - load checkpoint from local path: /home/MPCLST/mmaction2_YF/work_dirs/ava2/slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb/best_mAP@0.5IOU_epoch_19.pth
INFO:mmaction:load checkpoint from local path: /home/MPCLST/mmaction2_YF/work_dirs/ava2/slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb/best_mAP@0.5IOU_epoch_19.pth
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 77/77, 7.5 task/s, elapsed: 10s, ETA: 0sTraceback (most recent call last):
File "tools/train.py", line 201, in <module>
main()
File "tools/train.py", line 189, in main
train_model(
File "/home/MPCLST/mmaction2_YF/mmaction/apis/train.py", line 253, in train_model
outputs = multi_gpu_test(runner.model, test_dataloader, tmpdir,
File "/opt/conda/lib/python3.8/site-packages/mmcv/engine/test.py", line 87, in multi_gpu_test
results = collect_results_cpu(results, len(dataset), tmpdir)
File "/opt/conda/lib/python3.8/site-packages/mmcv/engine/test.py", line 130, in collect_results_cpu
dist.barrier()
File "/opt/conda/lib/python3.8/site-packages/torch/distributed/distributed_c10d.py", line 2419, in barrier
default_pg = _get_default_group()
File "/opt/conda/lib/python3.8/site-packages/torch/distributed/distributed_c10d.py", line 347, in _get_default_group
raise RuntimeError("Default process group has not been initialized, "
RuntimeError: Default process group has not been initialized, please make sure to call init_process_group.
通过: File “/home/MPCLST/mmaction2_YF/mmaction/apis/train.py”, line 253, in train_model
outputs = multi_gpu_test(runner.model, test_dataloader, tmpdir,
我们定位到错误的地方:
由此可知,测试最好的模型时,采用的是多GPU,我采用的是单个GPU训练。
那我们就采用多GPU训练,但是不是从头开始训练,而是从以前的模型权重文件恢复训练。
先迁移目标主机,让其有2块GPU
命令如下:
./tools/dist_train.sh configs/detection/ava/my_slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb.py 2 --resume-from /home/MPCLST/mmaction2_YF/work_dirs/ava2/slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb/latest.pth --validate --test-best
2.4训练结果
2.5 官网的时空动作检测的配置文件系统解析(Config System for Spatio-Temporal Action Detection)
这一小节抄的官网,因为我所使用的配置文件,几乎与官网相同,所以直接用官网的解析。
以 FastRCNN 为例
An Example of FastRCNN
# 模型设置 model setting
model = dict( # 模型的配置 Config of the model
type='FastRCNN', # 时空检测器类型 Type of the detector
backbone=dict( # Backbone 字典设置 Dict for backbone
type='ResNet3dSlowOnly', # Backbone 名 Name of the backbone
depth=50, # ResNet 模型深度 Depth of ResNet model
pretrained=None, # 预训练模型的 url 或文件位置 The url/site of the pretrained model
pretrained2d=False, # 预训练模型是否为 2D 模型 If the pretrained model is 2D
lateral=False, # backbone 是否有侧连接 If the backbone is with lateral connections
num_stages=4, # ResNet 模型阶数 Stages of ResNet model
conv1_kernel=(1, 7, 7), # Conv1 卷积核尺寸 Conv1 kernel size
conv1_stride_t=1, # Conv1 时序步长 Conv1 temporal stride
pool1_stride_t=1, # Pool1 时序步长 Pool1 temporal stride
spatial_strides=(1, 2, 2, 1)), # 每个 ResNet 阶的空间步长 The spatial stride for each ResNet stage
roi_head=dict( # roi_head 字典设置 Dict for roi_head
type='AVARoIHead', # roi_head 名 Name of the roi_head
bbox_roi_extractor=dict( # bbox_roi_extractor 字典设置 Dict for bbox_roi_extractor
type='SingleRoIExtractor3D', # bbox_roi_extractor 名 Name of the bbox_roi_extractor
roi_layer_type='RoIAlign', # RoI op 类型 Type of the RoI op
output_size=8, # RoI op 输出特征尺寸 Output feature size of the RoI op
with_temporal_pool=True), # 时序维度是否要经过池化 If temporal dim is pooled
bbox_head=dict( # bbox_head 字典设置 Dict for bbox_head
type='BBoxHeadAVA', # bbox_head 名 Name of the bbox_head
in_channels=2048, # 输入特征通道数 Number of channels of the input feature
num_classes=81, # 动作类别数 + 1(背景) Number of action classes + 1
multilabel=True, # 数据集是否多标签 If the dataset is multilabel
dropout_ratio=0.5)), # dropout 比率 The dropout ratio used
# 模型训练和测试的设置 model training and testing settings
train_cfg=dict( # 训练 FastRCNN 的超参配置 Training config of FastRCNN
rcnn=dict( # rcnn 训练字典设置 Dict for rcnn training config
assigner=dict( # assigner 字典设置 Dict for assigner
type='MaxIoUAssignerAVA', # assigner 名 Name of the assigner
pos_iou_thr=0.9, # 正样本 IoU 阈值, > pos_iou_thr -> positive ,IoU threshold for positive examples, > pos_iou_thr -> positive
neg_iou_thr=0.9, # 负样本 IoU 阈值, < neg_iou_thr -> negative,IoU threshold for negative examples, < neg_iou_thr -> negative
min_pos_iou=0.9), # 正样本最小可接受 IoU Minimum acceptable IoU for positive examples
sampler=dict( # sample 字典设置 Dict for sample
type='RandomSampler', # sampler 名 Name of the sampler
num=32, # sampler 批大小 Batch Size of the sampler
pos_fraction=1, # sampler 正样本边界框比率 Positive bbox fraction of the sampler
neg_pos_ub=-1, # 负样本数转正样本数的比率上界 Upper bound of the ratio of num negative to num positive
add_gt_as_proposals=True), # 是否添加 ground truth 为候选 Add gt bboxes as proposals
pos_weight=1.0, # 正样本 loss 权重 Loss weight of positive examples
debug=False)), # 是否为 debug 模式 Debug mode
test_cfg=dict( # 测试 FastRCNN 的超参设置 Testing config of FastRCNN
rcnn=dict( # rcnn 测试字典设置 Dict for rcnn testing config
action_thr=0.002))) # 某行为的阈值 The threshold of an action
# 数据集设置 dataset settings
dataset_type = 'AVADataset' # 训练,验证,测试的数据集类型 Type of dataset for training, validation and testing
data_root = 'data/ava/rawframes' # 训练集的根目录 Root path to data
anno_root = 'data/ava/annotations' # 标注文件目录 Root path to annotations
ann_file_train = f'{anno_root}/ava_train_v2.1.csv' # 训练集的标注文件 Path to the annotation file for training
ann_file_val = f'{anno_root}/ava_val_v2.1.csv' # 验证集的标注文件 Path to the annotation file for validation
exclude_file_train = f'{anno_root}/ava_train_excluded_timestamps_v2.1.csv' # 训练除外数据集文件路径 Path to the exclude annotation file for training
exclude_file_val = f'{anno_root}/ava_val_excluded_timestamps_v2.1.csv' # 验证除外数据集文件路径 Path to the exclude annotation file for validation
label_file = f'{anno_root}/ava_action_list_v2.1_for_activitynet_2018.pbtxt' # 标签文件路径 Path to the label file
proposal_file_train = f'{anno_root}/ava_dense_proposals_train.FAIR.recall_93.9.pkl' # 训练样本检测候选框的文件路径 Path to the human detection proposals for training examples
proposal_file_val = f'{anno_root}/ava_dense_proposals_val.FAIR.recall_93.9.pkl' # 验证样本检测候选框的文件路径 Path to the human detection proposals for validation examples
img_norm_cfg = dict( # 图像正则化参数设置 Config of image normalization used in data pipeline
mean=[123.675, 116.28, 103.53], # 图像正则化平均值 Mean values of different channels to normalize
std=[58.395, 57.12, 57.375], # 图像正则化方差 Std values of different channels to normalize
to_bgr=False) # 是否将通道数从 RGB 转为 BGR Whether to convert channels from RGB to BGR
train_pipeline = [ # 训练数据前处理流水线步骤组成的列表 List of training pipeline steps
dict( # SampleFrames 类的配置 Config of SampleFrames
type='AVASampleFrames', # 选定采样哪些视频帧 Sample frames pipeline, sampling frames from video
clip_len=4, # 每个输出视频片段的帧 Frames of each sampled output clip
frame_interval=16), # 所采相邻帧的时序间隔 Temporal interval of adjacent sampled frames
dict( # RawFrameDecode 类的配置 Config of RawFrameDecode
type='RawFrameDecode'), # 给定帧序列,加载对应帧,解码对应帧 Load and decode Frames pipeline, picking raw frames with given indices
dict( # RandomRescale 类的配置 Config of RandomRescale
type='RandomRescale', # 给定一个范围,进行随机短边缩放 Randomly rescale the shortedge by a given range
scale_range=(256, 320)), # RandomRescale 的短边缩放范围 The shortedge size range of RandomRescale
dict( # RandomCrop 类的配置 Config of RandomCrop
type='RandomCrop', # 给定一个尺寸进行随机裁剪 Randomly crop a patch with the given size
size=256), # 裁剪尺寸 The size of the cropped patch
dict( # Flip 类的配置 Config of Flip
type='Flip', # 图片翻转 Flip Pipeline
flip_ratio=0.5), # 执行翻转几率 Probability of implementing flip
dict( # Normalize 类的配置 Config of Normalize
type='Normalize', # 图片正则化 Normalize pipeline
**img_norm_cfg), # 图片正则化参数 Config of image normalization
dict( # FormatShape 类的配置 Config of FormatShape
type='FormatShape', # 将图片格式转变为给定的输入格式 Format shape pipeline, Format final image shape to the given input_format
input_format='NCTHW', # 最终的图片组成格式 Final image shape format
collapse=True), # 去掉 N 梯度当 N == 1 Collapse the dim N if N == 1
dict( # Rename 类的配置 Config of Rename
type='Rename', # 重命名 key 名 Rename keys
mapping=dict(imgs='img')), # 改名映射字典 The old name to new name mapping
dict( # ToTensor 类的配置 Config of ToTensor
type='ToTensor', # ToTensor 类将其他类型转化为 Tensor 类型 Convert other types to tensor type pipeline
keys=['img', 'proposals', 'gt_bboxes', 'gt_labels']), # 将被从其他类型转化为 Tensor 类型的特征 Keys to be converted from image to tensor
dict( # ToDataContainer 类的配置 Config of ToDataContainer
type='ToDataContainer', # 将一些信息转入到 ToDataContainer 中 Convert other types to DataContainer type pipeline
fields=[ # 转化为 Datacontainer 的域 Fields to convert to DataContainer
dict( # 域字典 Dict of fields
key=['proposals', 'gt_bboxes', 'gt_labels'], # 将转化为 DataContainer 的键 Keys to Convert to DataContainer
stack=False)]), # 是否要堆列这些 tensor Whether to stack these tensor
dict( # Collect 类的配置 Config of Collect
type='Collect', # Collect 类决定哪些键会被传递到时空检测器中 Collect pipeline that decides which keys in the data should be passed to the detector
keys=['img', 'proposals', 'gt_bboxes', 'gt_labels'], # 输入的键 Keys of input ,Keys of input
meta_keys=['scores', 'entity_ids']), # 输入的元键 Meta keys of input
]
val_pipeline = [ # 验证数据前处理流水线步骤组成的列表 List of validation pipeline steps
dict( # SampleFrames 类的配置 Config of SampleFrames
type='AVASampleFrames', # 选定采样哪些视频帧 Sample frames pipeline, sampling frames from video
clip_len=4, # 每个输出视频片段的帧 Frames of each sampled output clip
frame_interval=16), # 所采相邻帧的时序间隔 Temporal interval of adjacent sampled frames
dict( # RawFrameDecode 类的配置 Config of RawFrameDecode
type='RawFrameDecode'), # 给定帧序列,加载对应帧,解码对应帧 Load and decode Frames pipeline, picking raw frames with given indices
dict( # Resize 类的配置 Config of Resize
type='Resize', # 调整图片尺寸 Resize pipeline
scale=(-1, 256)), # 调整比例 The scale to resize images
dict( # Normalize 类的配置 Config of Normalize
type='Normalize', # 图片正则化 Normalize pipeline
**img_norm_cfg), # 图片正则化参数 Config of image normalization
dict( # FormatShape 类的配置 Config of FormatShape
type='FormatShape', # 将图片格式转变为给定的输入格式 Format shape pipeline, Format final image shape to the given input_format
input_format='NCTHW', # 最终的图片组成格式 Final image shape format
collapse=True), # 去掉 N 梯度当 N == 1 Collapse the dim N if N == 1
dict( # Rename 类的配置 Config of Rename
type='Rename', # 重命名 key 名 Rename keys
mapping=dict(imgs='img')), # 改名映射字典 The old name to new name mapping
dict( # ToTensor 类的配置 Config of ToTensor
type='ToTensor', # ToTensor 类将其他类型转化为 Tensor 类型 Convert other types to tensor type pipeline
keys=['img', 'proposals']), # 将被从其他类型转化为 Tensor 类型的特征 Keys to be converted from image to tensor
dict( # ToDataContainer 类的配置 Config of ToDataContainer ,Convert other types to DataContainer type pipeline
type='ToDataContainer', # 将一些信息转入到 ToDataContainer 中
fields=[ # 转化为 Datacontainer 的域
dict( # 域字典
key=['proposals'], # 将转化为 DataContainer 的键
stack=False)]), # 是否要堆列这些 tensor
dict( # Collect 类的配置
type='Collect', # Collect 类决定哪些键会被传递到时空检测器中
keys=['img', 'proposals'], # 输入的键
meta_keys=['scores', 'entity_ids'], # 输入的元键
nested=True) # 是否将数据包装为嵌套列表
]
data = dict( # 数据的配置
videos_per_gpu=16, # 单个 GPU 的批大小
workers_per_gpu=2, # 单个 GPU 的 dataloader 的进程
val_dataloader=dict( # 验证过程 dataloader 的额外设置
videos_per_gpu=1), # 单个 GPU 的批大小
train=dict( # 训练数据集的设置
type=dataset_type,
ann_file=ann_file_train,
exclude_file=exclude_file_train,
pipeline=train_pipeline,
label_file=label_file,
proposal_file=proposal_file_train,
person_det_score_thr=0.9,
data_prefix=data_root),
val=dict( # 验证数据集的设置
type=dataset_type,
ann_file=ann_file_val,
exclude_file=exclude_file_val,
pipeline=val_pipeline,
label_file=label_file,
proposal_file=proposal_file_val,
person_det_score_thr=0.9,
data_prefix=data_root))
data['test'] = data['val'] # 将验证数据集设置复制到测试数据集设置
# 优化器设置
optimizer = dict(
# 构建优化器的设置,支持:
# (1) 所有 PyTorch 原生的优化器,这些优化器的参数和 PyTorch 对应的一致;
# (2) 自定义的优化器,这些优化器在 `constructor` 的基础上构建。
# 更多细节可参考 "tutorials/5_new_modules.md" 部分
type='SGD', # 优化器类型, 参考 https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/optimizer/default_constructor.py#L13
lr=0.2, # 学习率, 参数的细节使用可参考 PyTorch 的对应文档
momentum=0.9, # 动量大小
weight_decay=0.00001) # SGD 优化器权重衰减
optimizer_config = dict( # 用于构建优化器钩子的设置
grad_clip=dict(max_norm=40, norm_type=2)) # 使用梯度裁剪
lr_config = dict( # 用于注册学习率调整钩子的设置
policy='step', # 调整器策略, 支持 CosineAnnealing,Cyclic等方法。更多细节可参考 https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/lr_updater.py#L9
step=[40, 80], # 学习率衰减步长
warmup='linear', # Warmup 策略
warmup_by_epoch=True, # Warmup 单位为 epoch 还是 iteration
warmup_iters=5, # warmup 数
warmup_ratio=0.1) # 初始学习率为 warmup_ratio * lr
total_epochs = 20 # 训练模型的总周期数
checkpoint_config = dict( # 模型权重文件钩子设置,更多细节可参考 https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/hooks/checkpoint.py
interval=1) # 模型权重文件保存间隔
workflow = [('train', 1)] # runner 的执行流. [('train', 1)] 代表只有一个执行流,并且这个名为 train 的执行流只执行一次
evaluation = dict( # 训练期间做验证的设置
interval=1, save_best='mAP@0.5IOU') # 执行验证的间隔,以及设置 `mAP@0.5IOU` 作为指示器,用于存储最好的模型权重文件
log_config = dict( # 注册日志钩子的设置
interval=20, # 打印日志间隔
hooks=[ # 训练期间执行的钩子
dict(type='TextLoggerHook'), # 记录训练过程信息的日志
])
# 运行设置
dist_params = dict(backend='nccl') # 建立分布式训练的设置,其中端口号也可以设置
log_level = 'INFO' # 日志等级
work_dir = ('./work_dirs/ava/' # 记录当前实验日志和模型权重文件的文件夹
'slowonly_kinetics_pretrained_r50_4x16x1_20e_ava_rgb')
load_from = ('https://download.openmmlab.com/mmaction/recognition/slowonly/' # 从给定路径加载模型作为预训练模型. 这个选项不会用于断点恢复训练
'slowonly_r50_4x16x1_256e_kinetics400_rgb/'
'slowonly_r50_4x16x1_256e_kinetics400_rgb_20200704-a69556c6.pth')
resume_from = None # 加载给定路径的模型权重文件作为断点续连的模型, 训练将从该时间点保存的周期点继续进行
3 日志分析
3.1 官网日志分析教程
官网给了多个日志分析的代码:https://mmaction2.readthedocs.io/zh_CN/latest/useful_tools.html#id2
输入变量指定一个训练日志文件,可通过 tools/analysis/analyze_logs.py 脚本绘制 loss/top-k 曲线。本功能依赖于 seaborn,使用前请先通过 pip install seaborn 安装依赖包。
tools/analysis/analyze_logs.py plots loss/top-k acc curves given a training log file. Run pip install seaborn first to install the dependency.
python tools/analysis/analyze_logs.py plot_curve ${JSON_LOGS} [--keys ${KEYS}] [--title ${TITLE}] [--legend ${LEGEND}] [--backend ${BACKEND}] [--style ${STYLE}] [--out ${OUT_FILE}]
例如(Examples:):
绘制某日志文件对应的分类损失曲线图。
Plot the classification loss of some run.
python tools/analysis/analyze_logs.py plot_curve log.json --keys loss_cls --legend loss_cls
绘制某日志文件对应的 top-1 和 top-5 准确率曲线图,并将曲线图导出为 PDF 文件。
Plot the top-1 acc and top-5 acc of some run, and save the figure to a pdf.
python tools/analysis/analyze_logs.py plot_curve log.json --keys top1_acc top5_acc --out results.pdf
3.2 我的日志分析
当然,如果你直接使用官网的代码,大概率会报错,因为跑slowfast的训练后,生成的训练日志里面,没有:loss_cls、top-5。
只有:recall@top5、loss_action_cls
3.2.1 错误展示
展示一个错误例子
执行:
cd /home/MPCLST/mmaction2_YF/
python ./tools/analysis/analyze_logs.py plot_curve ./work_dirs/avaT2/slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb/20220804_141745.log.json \
--keys loss_cls \
--legend loss_cls
然后就会有如下报错
Traceback (most recent call last):
File "./tools/analysis/analyze_logs.py", line 176, in <module>
main()
File "./tools/analysis/analyze_logs.py", line 172, in main
eval(args.task)(log_dicts, args)
File "./tools/analysis/analyze_logs.py", line 61, in plot_curve
raise KeyError(
KeyError: './work_dirs/avaT2/slowfast_kinetics_pretrained_r50_4x16x1_20e_ava_rgb/20220804_141745.log.json does not contain metric loss_cls'
原因就是训练日志里没有:loss_cls,要换成loss_action_cls
3.2.2 损失曲线图
正确的命令如下:
cd /home/MPCLST/mmaction2_YF/
python ./tools/analysis/analyze_logs.py plot_curve ./1.log.json \
--keys loss_action_cls \
--legend loss_action_cls \
--out ./Aresults.pdf
3.2.3 prec@top3 prec@top5曲线
python ./tools/analysis/analyze_logs.py plot_curve ./1.log.json \
--keys prec@top3 prec@top5 \
--out Aresults2.pdf
3.2.4 recall@top3 recall@top5
python ./tools/analysis/analyze_logs.py plot_curve ./1.log.json \
--keys recall@top3 recall@top5 \
--out Aresults3.pdf
4 测试结果分析
测试结果在:22-8-4 mmaction2 slowfast训练日志:https://download.youkuaiyun.com/download/WhiffeYF/86337607
其中part_0.pkl即为测试结果