# Migration from MMAction2 0.x MMAction2 1.x introduced major refactorings and modifications including some BC-breaking changes. We provide this tutorial to help you migrate your projects from MMAction2 0.x smoothly. ## New dependencies MMAction2 1.x depends on the following packages. You are recommended to prepare a new clean environment and install them according to [install tutorial](./get_started/installation.md) 1. [MMEngine](https://github.com/open-mmlab/mmengine): MMEngine is a foundational library for training deep learning model introduced in OpenMMLab 2.0 architecture. 2. [MMCV](https://github.com/open-mmlab/mmcv): MMCV is a foundational library for computer vision. MMAction2 1.x requires `mmcv>=2.0.0` which is more compact and efficient than `mmcv-full==2.0.0`. ## Configuration files In MMAction2 1.x, we refactored the structure of configuration files. The configuration files with the old style will be incompatible. In this section, we will introduce all changes of the configuration files. And we assume you are already familiar with the [config files](./user_guides/config.md). ### Model settings No changes in `model.backbone` and `model.neck`. For `model.cls_head`, we move the `average_clips` inside it, which is originally set in `model.test_cfg`. ### Data settings #### Changes in **`data`** - The original `data` field is splited to `train_dataloader`, `val_dataloader` and `test_dataloader`. This allows us to configure them in fine-grained. For example, you can specify different sampler and batch size during training and test. - The `videos_per_gpu` is renamed to `batch_size`. - The `workers_per_gpu` is renamed to `num_workers`.
Original | ```python data = dict( videos_per_gpu=32, workers_per_gpu=2, train=dict(...), val=dict(...), test=dict(...), ) ``` |
New | ```python train_dataloader = dict( batch_size=32, num_workers=2, dataset=dict(...), sampler=dict(type='DefaultSampler', shuffle=True) # necessary ) val_dataloader = dict( batch_size=32, num_workers=2, dataset=dict(...), sampler=dict(type='DefaultSampler', shuffle=False) # necessary ) test_dataloader = val_dataloader ``` |
Original | ```python train_pipeline = [ dict(type='DecordInit'), dict(type='SampleFrames', clip_len=1, frame_interval=1, num_clips=8), dict(type='DecordDecode'), dict(type='Resize', scale=(-1, 256)), dict( type='MultiScaleCrop', input_size=224, scales=(1, 0.875, 0.75, 0.66), random_crop=False, max_wh_scale_gap=1), dict(type='Resize', scale=(224, 224), keep_ratio=False), dict(type='Flip', flip_ratio=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='FormatShape', input_format='NCHW'), dict(type='Collect', keys=['imgs', 'label'], meta_keys=[]), dict(type='ToTensor', keys=['imgs', 'label']) ] ``` |
New | ```python model.data_preprocessor = dict( mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=False) train_pipeline = [ dict(type='DecordInit'), dict(type='SampleFrames', clip_len=1, frame_interval=1, num_clips=5), dict(type='DecordDecode'), dict(type='Resize', scale=(-1, 256)), dict( type='MultiScaleCrop', input_size=224, scales=(1, 0.875, 0.75, 0.66), random_crop=False, max_wh_scale_gap=1), dict(type='Resize', scale=(224, 224), keep_ratio=False), dict(type='Flip', flip_ratio=0.5), dict(type='FormatShape', input_format='NCHW'), dict(type='PackActionInputs') ] ``` |
Original | ```python evaluation = dict( interval=5, metrics=['top_k_accuracy', 'mean_class_accuracy']) ``` |
New | ```python val_evaluator = dict( type='AccMetric', metric_list=('top_k_accuracy', 'mean_class_accuracy')) test_evaluator = val_evaluator ``` |
Original | ```python optimizer = dict( type='AdamW', lr=0.0015, weight_decay=0.3, paramwise_cfg = dict( norm_decay_mult=0.0, bias_decay_mult=0.0, )) optimizer_config = dict(grad_clip=dict(max_norm=1.0)) ``` |
New | ```python optim_wrapper = dict( optimizer=dict(type='AdamW', lr=0.0015, weight_decay=0.3), paramwise_cfg = dict( norm_decay_mult=0.0, bias_decay_mult=0.0, ), clip_gard=dict(max_norm=1.0), ) ``` |
Original | ```python lr_config = dict( policy='CosineAnnealing', min_lr=0, warmup='linear', warmup_iters=5, warmup_ratio=0.01, warmup_by_epoch=True) ``` |
New | ```python param_scheduler = [ # warmup dict( type='LinearLR', start_factor=0.01, by_epoch=True, end=5, # Update the learning rate after every iters. convert_to_iter_based=True), # main learning rate scheduler dict(type='CosineAnnealingLR', by_epoch=True, begin=5), ] ``` |
Original | ```python runner = dict(type='EpochBasedRunner', max_epochs=100) ``` |
New | ```python # The `val_interval` is the original `evaluation.interval`. train_cfg = dict(type='EpochBasedTrainLoop', max_epochs=100, val_begin=1, val_interval=1) val_cfg = dict(type='ValLoop') # Use the default validation loop. test_cfg = dict(type='TestLoop') # Use the default test loop. ``` |
Original | ```python log_config = dict( interval=100, hooks=[ dict(type='TextLoggerHook'), dict(type='TensorboardLoggerHook'), ]) ``` |
New | ```python default_hooks = dict( ... logger=dict(type='LoggerHook', interval=100), ) visualizer = dict( type='ActionVisualizer', vis_backends=[dict(type='LocalVisBackend'), dict(type='TensorboardVisBackend')], ) ``` |