mmaction2 / Vibevoice /zh_cn /advanced_guides /customize_pipeline.md
niobures's picture
mmaction2
d3dbf03 verified
# 自定义数据流水线
在本教程中,我们将介绍如何为你的任务构建数据流水线(即,数据转换)的一些方法。
- [自定义数据流水线](#自定义数据流水线)
- [数据流水线设计](#数据流水线设计)
- [修改训练/测试数据流水线](#修改训练/测试数据流水线)
- [加载](#加载)
- [采样帧和其他处理](#采样帧和其他处理)
- [格式化](#格式化)
- [添加新的数据转换](#添加新的数据转换)
## 数据流水线设计
数据流水线指的是从数据集索引样本时处理数据样本字典的过程,它包括一系列的数据转换。每个数据转换接受一个 `dict` 作为输入,对其进行处理,并产生一个 `dict` 作为输出,供序列中的后续数据转换使用。
以下是一个例子,用于使用 `VideoDataset` 在 Kinetics 上训练 SlowFast 的数据流水线。这个数据流水线首先使用 [`decord`](https://github.com/dmlc/decord) 读取原始视频并随机采样一个视频剪辑,该剪辑包含 `32` 帧,帧间隔为 `2`。然后,它对所有帧应用随机大小调整的裁剪和随机水平翻转,然后将数据形状格式化为 `NCTHW`,在这个例子中,它是 `(1, 3, 32, 224, 224)`
```python
train_pipeline = [
dict(type='DecordInit',),
dict(type='SampleFrames', clip_len=32, frame_interval=2, num_clips=1),
dict(type='DecordDecode'),
dict(type='Resize', scale=(-1, 256)),
dict(type='RandomResizedCrop'),
dict(type='Resize', scale=(224, 224), keep_ratio=False),
dict(type='Flip', flip_ratio=0.5),
dict(type='FormatShape', input_format='NCTHW'),
dict(type='PackActionInputs')
]
```
MMAction2 中所有可用的数据转换的详细列表可以在 [mmaction.datasets.transforms](mmaction.datasets.transforms) 中找到。
## 修改训练/测试数据流水线
MMAction2 的数据流水线非常灵活,因为几乎每一步的数据预处理都可以从配置文件中进行配置。然而,对于一些用户来说,这种多样性可能会让人感到不知所措。
以下是一些用于构建动作识别任务数据流水线的一般实践和指南。
### 加载
在数据流水线的开始,通常是加载视频。然而,如果帧已经被提取出来,你应该使用 `RawFrameDecode` 并修改数据集类型为 `RawframeDataset`
```python
train_pipeline = [
dict(type='SampleFrames', clip_len=32, frame_interval=2, num_clips=1),
dict(type='RawFrameDecode'),
dict(type='Resize', scale=(-1, 256)),
dict(type='RandomResizedCrop'),
dict(type='Resize', scale=(224, 224), keep_ratio=False),
dict(type='Flip', flip_ratio=0.5),
dict(type='FormatShape', input_format='NCTHW'),
dict(type='PackActionInputs')
]
```
如果你需要从具有不同格式(例如,`pkl``bin`等)的文件或从特定位置加载数据,你可以创建一个新的加载转换并将其包含在数据流水线的开始。有关更多详细信息,请参阅[添加新的数据转换](#添加新的数据转换)。
### 采样帧和其他处理
在训练和测试过程中,我们可能会有从视频中采样帧的不同策略。
例如,当测试 SlowFast 时,我们会均匀地采样多个剪辑,如下所示:
```python
test_pipeline = [
...
dict(
type='SampleFrames',
clip_len=32,
frame_interval=2,
num_clips=10,
test_mode=True),
...
]
```
在上述例子中,每个视频将均匀地采样10个视频剪辑,每个剪辑包含32帧。 `test_mode=True` 用于实现这一点,与训练期间的随机采样相反。
另一个例子涉及 `TSN/TSM` 模型,它们从视频中采样多个片段:
```python
train_pipeline = [
...
dict(type='SampleFrames', clip_len=1, frame_interval=1, num_clips=8),
...
]
```
通常,数据流水线中的数据增强只处理视频级的转换,例如调整大小或裁剪,而不处理像视频标准化或 mixup/cutmix 这样的转换。这是因为我们可以在批量视频数据上进行视频标准化和 mixup/cutmix,以使用 GPU 加速处理。要配置视频标准化和 mixup/cutmix,请使用 [mmaction.models.utils.data_preprocessor](mmaction.models.utils.data_preprocessor)。
### 格式化
格式化涉及从数据信息字典中收集训练数据,并将其转换为与模型兼容的格式。
在大多数情况下,你可以简单地使用 [`PackActionInputs`](mmaction.datasets.transforms.PackActionInputs),它将以 `NumPy Array` 格式的图像转换为 `PyTorch Tensor`,并将地面真实类别信息和其他元信息打包为一个类似字典的对象 [`ActionDataSample`](mmaction.structures.ActionDataSample)。
```python
train_pipeline = [
...
dict(type='PackActionInputs'),
]
```
## 添加新的数据转换
1. 要创建一个新的数据转换,编写一个新的转换类在一个 Python 文件中,例如,名为 `my_transforms.py`。数据转换类必须继承 [`mmcv.transforms.BaseTransform`](mmcv.transforms.BaseTransform) 类,并重写 `transform` 方法,该方法接受一个 `dict` 作为输入并返回一个 `dict`。最后,将 `my_transforms.py` 放在 `mmaction/datasets/transforms/` 文件夹中。
```python
from mmcv.transforms import BaseTransform
from mmaction.datasets import TRANSFORMS
@TRANSFORMS.register_module()
class MyTransform(BaseTransform):
def __init__(self, msg):
self.msg = msg
def transform(self, results):
# 修改数据信息字典 `results`。
print(msg, 'MMAction2.')
return results
```
2.`mmaction/datasets/transforms/__init__.py` 中导入新类。
```python
...
from .my_transform import MyTransform
__all__ = [
..., 'MyTransform'
]
```
3. 在配置文件中使用它。
```python
train_pipeline = [
...
dict(type='MyTransform', msg='Hello!'),
...
]
```