File size: 6,135 Bytes
d3dbf03 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# 自定义数据流水线
在本教程中,我们将介绍如何为你的任务构建数据流水线(即,数据转换)的一些方法。
- [自定义数据流水线](#自定义数据流水线)
- [数据流水线设计](#数据流水线设计)
- [修改训练/测试数据流水线](#修改训练/测试数据流水线)
- [加载](#加载)
- [采样帧和其他处理](#采样帧和其他处理)
- [格式化](#格式化)
- [添加新的数据转换](#添加新的数据转换)
## 数据流水线设计
数据流水线指的是从数据集索引样本时处理数据样本字典的过程,它包括一系列的数据转换。每个数据转换接受一个 `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!'),
...
]
```
|