Commit b6df0d33 authored by limm's avatar limm
Browse files

add resources part

parent cbc25585
Pipeline #2802 canceled with stages
# 学习配置文件
为了管理深度学习实验的各种设置,我们使用配置文件来记录所有这些配置。这种配置文件系统具有模块化和继承特性,更多细节可以在{external+mmengine:doc}`MMEngine 中的教程 <advanced_tutorials/config>`
MMPretrain 主要使用 python 文件作为配置文件,所有配置文件都放置在 [`configs`](https://github.com/open-mmlab/mmpretrain/tree/main/configs) 文件夹下,目录结构如下所示:
```text
MMPretrain/
├── configs/
│ ├── _base_/ # primitive configuration folder
│ │ ├── datasets/ # primitive datasets
│ │ ├── models/ # primitive models
│ │ ├── schedules/ # primitive schedules
│ │ └── default_runtime.py # primitive runtime setting
│ ├── beit/ # BEiT Algorithms Folder
│ ├── mae/ # MAE Algorithms Folder
│ ├── mocov2/ # MoCoV2 Algorithms Folder
│ ├── resnet/ # ResNet Algorithms Folder
│ ├── swin_transformer/ # Swin Algorithms Folder
│ ├── vision_transformer/ # ViT Algorithms Folder
│ ├── ...
└── ...
```
可以使用 `python tools/misc/print_config.py /PATH/TO/CONFIG` 命令来查看完整的配置信息,从而方便检查所对应的配置文件。
本文主要讲解 MMPretrain 配置文件的命名和结构,以及如何基于已有的配置文件修改,并以 [ResNet50 配置文件](https://github.com/open-mmlab/mmpretrain/blob/main/configs/resnet/resnet50_8xb32_in1k.py) 逐行解释。
## 配置文件结构
`configs/_base_` 文件夹下有 4 个基本组件类型,分别是:
- [模型(model)](https://github.com/open-mmlab/mmpretrain/tree/main/configs/_base_/models)
- [数据(data)](https://github.com/open-mmlab/mmpretrain/tree/main/configs/_base_/datasets)
- [训练策略(schedule)](https://github.com/open-mmlab/mmpretrain/tree/main/configs/_base_/schedules)
- [运行设置(runtime)](https://github.com/open-mmlab/mmpretrain/blob/main/configs/_base_/default_runtime.py)
你可以通过继承一些基本配置文件轻松构建自己的训练配置文件。我们称这些被继承的配置文件为 _原始配置文件_,如 `_base_` 文件夹中的文件一般仅作为原始配置文件。
下面使用 [ResNet50 配置文件](https://github.com/open-mmlab/mmpretrain/blob/main/configs/resnet/resnet50_8xb32_in1k.py) 作为案例进行说明并注释每一行含义。
```python
_base_ = [ # 此配置文件将继承所有 `_base_` 中的配置
'../_base_/models/resnet50.py', # 模型配置
'../_base_/datasets/imagenet_bs32.py', # 数据配置
'../_base_/schedules/imagenet_bs256.py', # 训练策略配置
'../_base_/default_runtime.py' # 默认运行设置
]
```
我们将在下面分别解释这四个原始配置文件。
### 模型配置
模型原始配置文件包含一个 `model` 字典数据结构,主要包括网络结构、损失函数等信息:
- `type`:算法类型,我们支持了多种任务
- 对于图像分类任务,通常为 `ImageClassifier`,更多细节请参考 [API 文档](mmpretrain.models.classifiers)
- 对于自监督任务,有多种类型的算法,例如 `MoCoV2`, `BEiT`, `MAE` 等。更多细节请参考 [API 文档](mmpretrain.models.selfsup)
- 对于图像检索任务,通常为 `ImageToImageRetriever`,更多细节请参考 [API 文档](mmpretrain.models.retrievers).
通常,我们使用 **`type`字段** 来指定组件的类,并使用其他字段来传递类的初始化参数。{external+mmengine:doc}`注册器教程 <advanced_tutorials/registry>` 对其进行了详细描述。
这里我们以 [`ImageClassifier`](mmpretrain.models.classifiers.ImageClassifier) 的配置字段为例,对初始化参数进行说明:
- `backbone`: 主干网络设置,主干网络为主要的特征提取网络,比如 `ResNet`, `Swin Transformer`, `Vision Transformer` 等等。更多可用选项请参考 [API 文档](mmpretrain.models.backbones)
- 对于自监督学习,有些主干网络需要重新实现,您可以在 [API 文档](mmpretrain.models.selfsup) 中获取更多细节。
- `neck`: 颈网络设置,颈网络主要是连接主干网和头网络的中间部分,比如 `GlobalAveragePooling` 等,更多可用选项请参考 [API 文档](mmpretrain.models.necks)
- `head`: 头网络设置,头网络主要是与具体任务关联的部件,如图像分类、自监督训练等,更多可用选项请参考 [API 文档](mmpretrain.models.heads)
- `loss`: 损失函数设置, 支持 `CrossEntropyLoss`, `LabelSmoothLoss`, `PixelReconstructionLoss` 等,更多可用选项参考 [API 文档](mmpretrain.models.losses)
- `data_preprocessor`: 图像输入的预处理模块,输入在进入模型前的预处理操作,例如 `ClsDataPreprocessor`, 有关详细信息,请参阅 [API 文档](mmpretrain.models.utils.data_preprocessor)
- `train_cfg`: `ImageClassifier` 的额外训练配置。在 `ImageClassifier` 中,我们使用这一参数指定批数据增强设置,比如 `Mixup``CutMix`。详见[文档](mmpretrain.models.utils.batch_augments)
以下是 ResNet50 的模型配置['configs/_base_/models/resnet50.py'](https://github.com/open-mmlab/mmpretrain/blob/main/configs/_base_/models/resnet50.py)
```python
model = dict(
type='ImageClassifier', # 主模型类型(对于图像分类任务,使用 `ImageClassifier`)
backbone=dict(
type='ResNet', # 主干网络类型
# 除了 `type` 之外的所有字段都来自 `ResNet` 类的 __init__ 方法
# 可查阅 https://mmpretrain.readthedocs.io/zh_CN/latest/api/generated/mmpretrain.models.backbones.ResNet.html
depth=50,
num_stages=4, # 主干网络状态(stages)的数目,这些状态产生的特征图作为后续的 head 的输入。
out_indices=(3, ), # 输出的特征图输出索引。
frozen_stages=-1, # 冻结主干网的层数
style='pytorch'),
neck=dict(type='GlobalAveragePooling'), # 颈网络类型
head=dict(
type='LinearClsHead', # 分类颈网络类型
# 除了 `type` 之外的所有字段都来自 `LinearClsHead` 类的 __init__ 方法
# 可查阅 https://mmpretrain.readthedocs.io/zh_CN/latest/api/generated/mmpretrain.models.heads.LinearClsHead.html
num_classes=1000,
in_channels=2048,
loss=dict(type='CrossEntropyLoss', loss_weight=1.0), # 损失函数配置信息
topk=(1, 5), # 评估指标,Top-k 准确率, 这里为 top1 与 top5 准确率
))
```
### 数据
数据原始配置文件主要包括预处理设置、dataloader 以及 评估器等设置:
- `data_preprocessor`: 模型输入预处理配置,与 `model.data_preprocessor` 相同,但优先级更低。
- `train_evaluator | val_evaluator | test_evaluator`: 构建评估器,参考 [API 文档](mmpretrain.evaluation)
- `train_dataloader | val_dataloader | test_dataloader`: 构建 dataloader
- `batch_size`: 每个 GPU 的 batch size
- `num_workers`: 每个 GPU 的线程数
- `sampler`: 采样器配置
- `dataset`: 数据集配置
- `type`: 数据集类型, MMPretrain 支持 `ImageNet``Cifar` 等数据集 ,参考 [API 文档](mmpretrain.datasets)
- `pipeline`: 数据处理流水线,参考相关教程文档 [如何设计数据处理流水线](../advanced_guides/pipeline.md)
以下是 ResNet50 的数据配置 ['configs/_base_/datasets/imagenet_bs32.py'](https://github.com/open-mmlab/mmpretrain/blob/main/configs/_base_/datasets/imagenet_bs32.py)
```python
dataset_type = 'ImageNet'
# 预处理配置
data_preprocessor = dict(
# 输入的图片数据通道以 'RGB' 顺序
mean=[123.675, 116.28, 103.53], # 输入图像归一化的 RGB 通道均值
std=[58.395, 57.12, 57.375], # 输入图像归一化的 RGB 通道标准差
to_rgb=True, # 是否将通道翻转,从 BGR 转为 RGB 或者 RGB 转为 BGR
)
train_pipeline = [
dict(type='LoadImageFromFile'), # 读取图像
dict(type='RandomResizedCrop', scale=224), # 随机放缩裁剪
dict(type='RandomFlip', prob=0.5, direction='horizontal'), # 随机水平翻转
dict(type='PackInputs'), # 准备图像以及标签
]
test_pipeline = [
dict(type='LoadImageFromFile'), # 读取图像
dict(type='ResizeEdge', scale=256, edge='short'), # 缩放短边尺寸至 256px
dict(type='CenterCrop', crop_size=224), # 中心裁剪
dict(type='PackInputs'), # 准备图像以及标签
]
# 构造训练集 dataloader
train_dataloader = dict(
batch_size=32, # 每张 GPU 的 batchsize
num_workers=5, # 每个 GPU 的线程数
dataset=dict( # 训练数据集
type=dataset_type,
data_root='data/imagenet',
ann_file='meta/train.txt',
data_prefix='train',
pipeline=train_pipeline),
sampler=dict(type='DefaultSampler', shuffle=True), # 默认采样器
persistent_workers=True, # 是否保持进程,可以缩短每个 epoch 的准备时间
)
# 构造验证集 dataloader
val_dataloader = dict(
batch_size=32,
num_workers=5,
dataset=dict(
type=dataset_type,
data_root='data/imagenet',
ann_file='meta/val.txt',
data_prefix='val',
pipeline=test_pipeline),
sampler=dict(type='DefaultSampler', shuffle=False),
persistent_workers=True,
)
# 验证集评估设置,使用准确率为指标, 这里使用 topk1 以及 top5 准确率
val_evaluator = dict(type='Accuracy', topk=(1, 5))
test_dataloader = val_dataloader # test dataloader 配置,这里直接与 val_dataloader 相同
test_evaluator = val_evaluator # 测试集的评估配置,这里直接与 val_evaluator 相同
```
```{note}
预处理配置(`data_preprocessor`)既可以作为 `model` 的一个子字段,也可以定义在外部的 `data_preprocessor` 字段,
同时配置时,优先使用 `model.data_preprocessor` 的配置。
```
### 训练策略
训练策略原始配置文件主要包括预优化器设置和训练、验证及测试的循环控制器(LOOP):
- `optim_wrapper`: 优化器装饰器配置信息,我们使用优化器装饰配置优化进程。
- `optimizer`: 支持 `pytorch` 所有的优化器,参考相关 {external+mmengine:doc}`MMEngine <tutorials/optim_wrapper>` 文档。
- `paramwise_cfg`: 根据参数的类型或名称设置不同的优化参数,参考相关 [学习策略文档](../advanced_guides/schedule.md) 文档。
- `accumulative_counts`: 积累几个反向传播后再优化参数,你可以用它通过小批量来模拟大批量。
- `param_scheduler` : 学习率策略,你可以指定训练期间的学习率和动量曲线。有关详细信息,请参阅 MMEngine 中的 {external+mmengine:doc}`文档 <tutorials/param_scheduler>`
- `train_cfg | val_cfg | test_cfg`: 训练、验证以及测试的循环执行器配置,请参考相关的{external+mmengine:doc}`MMEngine 文档 <design/runner>`
以下是 ResNet50 的训练策略配置['configs/_base_/schedules/imagenet_bs256.py'](https://github.com/open-mmlab/mmpretrain/blob/main/configs/_base_/schedules/imagenet_bs256.py)
```python
optim_wrapper = dict(
# 使用 SGD 优化器来优化参数
optimizer=dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001))
# 学习率参数的调整策略
# 'MultiStepLR' 表示使用多步策略来调度学习率(LR)。
param_scheduler = dict(
type='MultiStepLR', by_epoch=True, milestones=[30, 60, 90], gamma=0.1)
# 训练的配置,迭代 100 个 epoch,每一个训练 epoch 后都做验证集评估
# 'by_epoch=True' 默认使用 `EpochBaseLoop`, 'by_epoch=False' 默认使用 `IterBaseLoop`
train_cfg = dict(by_epoch=True, max_epochs=100, val_interval=1)
# 使用默认的验证循环控制器
val_cfg = dict()
# 使用默认的测试循环控制器
test_cfg = dict()
# 通过默认策略自动缩放学习率,此策略适用于总批次大小 256
# 如果你使用不同的总批量大小,比如 512 并启用自动学习率缩放
# 我们将学习率扩大到 2 倍
auto_scale_lr = dict(base_batch_size=256)
```
### 运行设置
本部分主要包括保存权重策略、日志配置、训练参数、断点权重路径和工作目录等等。
以下是几乎所有算法都使用的运行配置['configs/_base_/default_runtime.py'](https://github.com/open-mmlab/mmpretrain/blob/main//configs/_base_/default_runtime.py)
```python
# 默认所有注册器使用的域
default_scope = 'mmpretrain'
# 配置默认的 hook
default_hooks = dict(
# 记录每次迭代的时间。
timer=dict(type='IterTimerHook'),
# 每 100 次迭代打印一次日志。
logger=dict(type='LoggerHook', interval=100),
# 启用默认参数调度 hook。
param_scheduler=dict(type='ParamSchedulerHook'),
# 每个 epoch 保存检查点。
checkpoint=dict(type='CheckpointHook', interval=1),
# 在分布式环境中设置采样器种子。
sampler_seed=dict(type='DistSamplerSeedHook'),
# 验证结果可视化,默认不启用,设置 True 时启用。
visualization=dict(type='VisualizationHook', enable=False),
)
# 配置环境
env_cfg = dict(
# 是否开启 cudnn benchmark
cudnn_benchmark=False,
# 设置多进程参数
mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),
# 设置分布式参数
dist_cfg=dict(backend='nccl'),
)
# 设置可视化工具
vis_backends = [dict(type='LocalVisBackend')] # 使用磁盘(HDD)后端
visualizer = dict(
type='UniversalVisualizer', vis_backends=vis_backends, name='visualizer')
# 设置日志级别
log_level = 'INFO'
# 从哪个检查点加载
load_from = None
# 是否从加载的检查点恢复训练
resume = False
```
## 继承并修改配置文件
为了精简代码、更快的修改配置文件以及便于理解,我们建议继承现有方法。
对于在同一算法文件夹下的所有配置文件,MMPretrain 推荐只存在 **一个** 对应的 _原始配置_ 文件。
所有其他的配置文件都应该继承 _原始配置_ 文件,这样就能保证配置文件的最大继承深度为 3。
例如,如果在 ResNet 的基础上做了一些修改,用户首先可以通过指定 `_base_ = './resnet50_8xb32_in1k.py'`(相对于你的配置文件的路径),来继承基础的 ResNet 结构、数据集以及其他训练配置信息,然后修改配置文件中的必要参数以完成继承。如想在基础 resnet50 的基础上使用 `CutMix` 训练增强,将训练轮数由 100 改为 300 和修改学习率衰减轮数,同时修改数据集路径,可以建立新的配置文件 `configs/resnet/resnet50_8xb32-300e_in1k.py`, 文件中写入以下内容:
```python
# 在 'configs/resnet/' 创建此文件
_base_ = './resnet50_8xb32_in1k.py'
# 模型在之前的基础上使用 CutMix 训练增强
model = dict(
train_cfg=dict(
augments=dict(type='CutMix', alpha=1.0)
)
)
# 优化策略在之前基础上训练更多个 epoch
train_cfg = dict(max_epochs=300, val_interval=10) # 训练 300 个 epoch,每 10 个 epoch 评估一次
param_scheduler = dict(step=[150, 200, 250]) # 学习率调整也有所变动
# 使用自己的数据集目录
train_dataloader = dict(
dataset=dict(data_root='mydata/imagenet/train'),
)
val_dataloader = dict(
batch_size=64, # 验证时没有反向传播,可以使用更大的 batchsize
dataset=dict(data_root='mydata/imagenet/val'),
)
test_dataloader = dict(
batch_size=64, # 测试时没有反向传播,可以使用更大的 batchsize
dataset=dict(data_root='mydata/imagenet/val'),
)
```
### 使用配置文件里的中间变量
用一些中间变量,中间变量让配置文件更加清晰,也更容易修改。
例如数据集里的 `train_pipeline` / `test_pipeline` 是作为数据流水线的中间变量。我们首先要定义它们,然后将它们传递到 `train_dataloader` / `test_dataloader` 中。如果想修改训练或测试时输入图片的大小,就需要修改 `train_pipeline` / `test_pipeline` 这些中间变量。
```python
bgr_mean = [103.53, 116.28, 123.675]
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='RandomResizedCrop', scale=224, backend='pillow', interpolation='bicubic'),
dict(type='RandomFlip', prob=0.5, direction='horizontal'),
dict(
type='RandAugment',
policies='timm_increasing',
num_policies=2,
total_level=10,
magnitude_level=6,
magnitude_std=0.5,
hparams=dict(pad_val=[round(x) for x in bgr_mean], interpolation='bicubic')),
dict(type='PackInputs'),
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='ResizeEdge', scale=236, edge='short', backend='pillow', interpolation='bicubic'),
dict(type='CenterCrop', crop_size=224),
dict(type='PackInputs')
]
train_dataloader = dict(dataset=dict(pipeline=train_pipeline))
val_dataloader = dict(dataset=dict(pipeline=val_pipeline))
test_dataloader = dict(dataset=dict(pipeline=val_pipeline))
```
### 忽略基础配置文件里的部分内容
有时,您需要设置 `_delete_=True` 去忽略基础配置文件里的一些域内容。可以查看 {external+mmengine:doc}`MMEngine 文档 <advanced_tutorials/config>` 进一步了解该设计。
以下是一个简单应用案例。 如果在上述 ResNet50 案例中 使用余弦调度 ,使用继承并直接修改会报 `get unexcepected keyword 'step'` 错,因为基础配置文件 `param_scheduler` 域信息的 `'step'` 字段被保留下来了,需要加入 `_delete_=True` 去忽略基础配置文件里的 `param_scheduler` 相关域内容:
```python
_base_ = '../../configs/resnet/resnet50_8xb32_in1k.py'
# 学习率调整策略
param_scheduler = dict(type='CosineAnnealingLR', by_epoch=True, _delete_=True)
```
### 引用基础配置文件里的变量
有时,您可以引用 `_base_` 配置信息的一些域内容,这样可以避免重复定义。可以查看 {external+mmengine:doc}`MMEngine 文档 <advanced_tutorials/config>` 进一步了解该设计。
以下是一个简单应用案例,在训练数据预处理流水线中使用 `auto augment` 数据增强,参考配置文件 [`configs/resnest/resnest50_32xb64_in1k.py`](https://github.com/open-mmlab/mmpretrain/blob/main/configs/resnest/resnest50_32xb64_in1k.py)。 在定义 `train_pipeline` 时,可以直接在 `_base_` 中加入定义 auto augment 数据增强的文件命名,再通过 `{{_base_.auto_increasing_policies}}` 引用变量:
```python
_base_ = [
'../_base_/models/resnest50.py', '../_base_/datasets/imagenet_bs64.py',
'../_base_/default_runtime.py', './_randaug_policies.py',
]
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='RandAugment',
policies={{_base_.policies}}, # 这里使用了 _base_ 里的 `policies` 参数。
num_policies=2,
magnitude_level=12),
dict(type='EfficientNetRandomCrop', scale=224, backend='pillow'),
dict(type='RandomFlip', prob=0.5, direction='horizontal'),
dict(type='ColorJitter', brightness=0.4, contrast=0.4, saturation=0.4),
dict(
type='Lighting',
eigval=EIGVAL,
eigvec=EIGVEC,
alphastd=0.1,
to_rgb=False),
dict(type='PackInputs'),
]
train_dataloader = dict(dataset=dict(pipeline=train_pipeline))
```
## 通过命令行参数修改配置信息
当用户使用脚本 "tools/train.py" 或者 "tools/test.py" 提交任务,以及使用一些工具脚本时,可以通过指定 `--cfg-options` 参数来直接修改所使用的配置文件内容。
- 更新配置文件内的字典
可以按照原始配置文件中字典的键的顺序指定配置选项。
例如,`--cfg-options model.backbone.norm_eval=False` 将主干网络中的所有 BN 模块更改为 `train` 模式。
- 更新配置文件内列表的键
一些配置字典在配置文件中会形成一个列表。例如,训练流水线 `data.train.pipeline` 通常是一个列表。
例如,`[dict(type='LoadImageFromFile'), dict(type='TopDownRandomFlip', flip_prob=0.5), ...]` 。如果要将流水线中的 `'flip_prob=0.5'` 更改为 `'flip_prob=0.0'`,您可以这样指定 `--cfg-options data.train.pipeline.1.flip_prob=0.0`
- 更新列表/元组的值。
当配置文件中需要更新的是一个列表或者元组,例如,配置文件通常会设置 `val_evaluator = dict(type='Accuracy', topk=(1, 5))`,用户如果想更改 `topk`
需要指定 `--cfg-options val_evaluator.topk="(1,3)"`。注意这里的引号 " 对于列表以及元组数据类型的修改是必要的,
并且 **不允许** 引号内所指定的值的书写存在空格。
# 准备数据集
## CustomDataset
[`CustomDataset`](mmpretrain.datasets.CustomDataset) 是一个通用的数据集类,供您使用自己的数据集。目前 `CustomDataset` 支持以下两种方式组织你的数据集文件:
### 子文件夹方式
在这种格式下,您只需要重新组织您的数据集文件夹并将所有样本放在一个文件夹中,而无需创建任何标注文件。
对于监督任务(使用 `with_label=true`),我们使用子文件夹的名称作为类别名称,如下例所示,`class_x``class_y` 将被识别为类别名称。
```text
data_prefix/
├── class_x
│ ├── xxx.png
│ ├── xxy.png
│ └── ...
│ └── xxz.png
└── class_y
├── 123.png
├── nsdf3.png
├── ...
└── asd932_.png
```
对于无监督任务(使用 `with_label=false`),我们直接加载指定文件夹下的所有样本文件:
```
data_prefix/
├── folder_1
│ ├── xxx.png
│ ├── xxy.png
│ └── ...
├── 123.png
├── nsdf3.png
└── ...
```
假如你希望将之用于训练,那么配置文件中需要添加以下配置:
```python
train_dataloader = dict(
...
# 训练数据集配置
dataset=dict(
type='CustomDataset',
data_prefix='path/to/data_prefix',
with_label=True, # 对于无监督任务,使用 False
pipeline=...
)
)
```
```{note}
如果要使用此格式,请不要指定 `ann_file`,或指定 `ann_file=''`。
请注意,子文件夹格式需要对文件夹进行扫描,这可能会导致初始化速度变慢,尤其是对于大型数据集或慢速文件 IO。
```
### 标注文件方式
标注文件格式主要使用文本文件来保存类别信息,`data_prefix` 存放图片,`ann_file` 存放标注类别信息。
如下案例,dataset 目录如下:
在这种格式中,我们使用文本标注文件来存储图像文件路径和对应的类别索引。
对于监督任务(`with_label=true`),注释文件应在一行中包含一个样本的文件路径和类别索引,并用空格分隔,如下所示:
所有这些文件路径都可以是绝对路径,也可以是相对于 `data_prefix` 的相对路径。
```text
folder_1/xxx.png 0
folder_1/xxy.png 1
123.png 4
nsdf3.png 3
...
```
```{note}
类别的索引号从 0 开始。真实标签的值应在`[0, num_classes - 1]`范围内。
此外,请使用数据集设置中的 `classes` 字段来指定每个类别的名称
```
对于无监督任务(`with_label=false`),标注文件只需要在一行中包含一个样本的文件路径,如下:
```text
folder_1/xxx.png
folder_1/xxy.png
123.png
nsdf3.png
...
```
假设整个数据集文件夹如下:
```text
data_root
├── meta
│   ├── test.txt # 测试数据集的标注文件
│   ├── train.txt # 训练数据集的标注文件
│   └── val.txt # 验证数据集的标注文件
├── train
│   ├── 123.png
│   ├── folder_1
│   │   ├── xxx.png
│   │   └── xxy.png
│   └── nsdf3.png
├── test
└── val
```
这是配置文件中的数据集设置的示例:
```python
# 训练数据设置
train_dataloader = dict(
dataset=dict(
type='CustomDataset',
data_root='path/to/data_root', # `ann_flie` 和 `data_prefix` 共同的文件路径前缀
ann_file='meta/train.txt', # 相对于 `data_root` 的标注文件路径
data_prefix='train', # `ann_file` 中文件路径的前缀,相对于 `data_root`
classes=['A', 'B', 'C', 'D', ...], # 每个类别的名称
pipeline=..., # 处理数据集样本的一系列变换操作
)
...
)
```
```{note}
有关如何使用 `CustomDataset` 的完整示例,请参阅[如何使用自定义数据集进行预训练](../notes/pretrain_custom_dataset.md)
```
## ImageNet
ImageNet 有多个版本,但最常用的一个是 [ILSVRC 2012](http://www.image-net.org/challenges/LSVRC/2012/)。 可以通过以下步骤使用它。
`````{tabs}
````{group-tab} MIM 下载
MIM支持使用一条命令行从 [OpenXLab](https://openxlab.org.cn/datasets?lang=zh-CN) 下载并预处理 ImageNet 数据集。
_需要在 [OpenXLab 官网](https://openxlab.org.cn/datasets?lang=zh-CN) 注册账号并命令行登录_。
```Bash
# 安装 OpenXLab CLI 工具
pip install -U openxlab
# 登录 OpenXLab
openxlab login
# 使用 MIM 下载数据集, 最好在 $MMPreTrain 目录执行
mim download mmpretrain --dataset imagenet1k
```
````
````{group-tab} 从官网下载
1. 注册一个帐户并登录到[下载页面](http://www.image-net.org/download-images)。
2. 找到 ILSVRC2012 的下载链接,下载以下两个文件:
- ILSVRC2012_img_train.tar (~138GB)
- ILSVRC2012_img_val.tar (~6.3GB)
3. 解压已下载的图片。
````
`````
### ImageNet数据集目录结构
我们支持两种方式组织ImageNet数据集,子目录格式和文本注释文件格式。
#### 子文件夹格式
我们提供了一个样例,您可以从这个[链接](https://download.openmmlab.com/mmpretrain/datasets/imagenet_1k.zip)下载和解压。数据集的目录结构应如下所示:
```text
data/imagenet/
├── train/
│ ├── n01440764
│ │ ├── n01440764_10026.JPEG
│ │ ├── n01440764_10027.JPEG
│ │ ├── n01440764_10029.JPEG
│ │ ├── n01440764_10040.JPEG
│ │ ├── n01440764_10042.JPEG
│ │ ├── n01440764_10043.JPEG
│ │ └── n01440764_10048.JPEG
│ ├── ...
├── val/
│ ├── n01440764
│ │ ├── ILSVRC2012_val_00000293.JPEG
│ │ ├── ILSVRC2012_val_00002138.JPEG
│ │ ├── ILSVRC2012_val_00003014.JPEG
│ │ └── ...
│ ├── ...
```
#### 文本标注文件格式
您可以从[此链接](https://download.openmmlab.com/mmclassification/datasets/imagenet/meta/caffe_ilsvrc12.tar.gz)下载并解压元数据,然后组织文件夹如下:
```text
data/imagenet/
├── meta/
│ ├── train.txt
│ ├── test.txt
│ └── val.txt
├── train/
│ ├── n01440764
│ │ ├── n01440764_10026.JPEG
│ │ ├── n01440764_10027.JPEG
│ │ ├── n01440764_10029.JPEG
│ │ ├── n01440764_10040.JPEG
│ │ ├── n01440764_10042.JPEG
│ │ ├── n01440764_10043.JPEG
│ │ └── n01440764_10048.JPEG
│ ├── ...
├── val/
│ ├── ILSVRC2012_val_00000001.JPEG
│ ├── ILSVRC2012_val_00000002.JPEG
│ ├── ILSVRC2012_val_00000003.JPEG
│ ├── ILSVRC2012_val_00000004.JPEG
│ ├── ...
```
### 配置
当您的数据集以上述方式组织时,您可以使用具有以下配置的 [`ImageNet`](mmpretrain.datasets.ImageNet) 数据集:
```python
train_dataloader = dict(
...
# 训练数据集配置
dataset=dict(
type='ImageNet',
data_root='data/imagenet/',
split='train',
pipeline=...,
)
)
val_dataloader = dict(
...
# 验证数据集配置
dataset=dict(
type='ImageNet',
data_root='data/imagenet/',
split='val',
pipeline=...,
)
)
test_dataloader = val_dataloader
```
## 支持的图像分类数据集
| 数据集 | split | 主页 |
| ----------------------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------- |
| [`Calthch101`](mmpretrain.datasets.Caltech101)(data_root[, split, pipeline, ...]) | ["train", "test"] | [Caltech 101](https://data.caltech.edu/records/mzrjq-6wc02) 数据集 |
| [`CIFAR10`](mmpretrain.datasets.CIFAR10)(data_root[, split, pipeline, ...]) | ["train", "test"] | [CIFAR10](https://www.cs.toronto.edu/~kriz/cifar.html) 数据集 |
| [`CIFAR100`](mmpretrain.datasets.CIFAR100)(data_root[, split, pipeline, ...]) | ["train", "test"] | [CIFAR100](https://www.cs.toronto.edu/~kriz/cifar.html) 数据集 |
| [`CUB`](mmpretrain.datasets.CUB)(data_root[, split, pipeline, ...]) | ["train", "test"] | [CUB-200-2011](http://www.vision.caltech.edu/datasets/cub_200_2011/) 数据集 |
| [`DTD`](mmpretrain.datasets.DTD)(data_root[, split, pipeline, ...]) | ["train", "val", "tranval", "test"] | [Describable Texture Dataset (DTD)](https://www.robots.ox.ac.uk/~vgg/data/dtd/) 数据集 |
| [`FashionMNIST`](mmpretrain.datasets.FashionMNIST) (data_root[, split, pipeline, ...]) | ["train", "test"] | [Fashion-MNIST](https://github.com/zalandoresearch/fashion-mnist) 数据集 |
| [`FGVCAircraft`](mmpretrain.datasets.FGVCAircraft)(data_root[, split, pipeline, ...]) | ["train", "val", "tranval", "test"] | [FGVC Aircraft](https://www.robots.ox.ac.uk/~vgg/data/fgvc-aircraft/) 数据集 |
| [`Flowers102`](mmpretrain.datasets.Flowers102)(data_root[, split, pipeline, ...]) | ["train", "val", "tranval", "test"] | [Oxford 102 Flower](https://www.robots.ox.ac.uk/~vgg/data/flowers/102/) 数据集 |
| [`Food101`](mmpretrain.datasets.Food101)(data_root[, split, pipeline, ...]) | ["train", "test"] | [Food101](https://data.vision.ee.ethz.ch/cvl/datasets_extra/food-101/) 数据集 |
| [`MNIST`](mmpretrain.datasets.MNIST) (data_root[, split, pipeline, ...]) | ["train", "test"] | [MNIST](http://yann.lecun.com/exdb/mnist/) 数据集 |
| [`OxfordIIITPet`](mmpretrain.datasets.OxfordIIITPet)(data_root[, split, pipeline, ...]) | ["tranval", test"] | [Oxford-IIIT Pets](https://www.robots.ox.ac.uk/~vgg/data/pets/) 数据集 |
| [`Places205`](mmpretrain.datasets.Places205)(data_root[, pipeline, ...]) | - | [Places205](http://places.csail.mit.edu/downloadData.html) 数据集 |
| [`StanfordCars`](mmpretrain.datasets.StanfordCars)(data_root[, split, pipeline, ...]) | ["train", "test"] | [StanfordCars](https://ai.stanford.edu/~jkrause/cars/car_dataset.html) 数据集 |
| [`SUN397`](mmpretrain.datasets.SUN397)(data_root[, split, pipeline, ...]) | ["train", "test"] | [SUN397](https://vision.princeton.edu/projects/2010/SUN/) 数据集 |
| [`VOC`](mmpretrain.datasets.VOC)(data_root[, image_set_path, pipeline, ...]) | ["train", "val", "tranval", "test"] | [Pascal VOC](http://host.robots.ox.ac.uk/pascal/VOC/) 数据集 |
有些数据集主页链接可能已经失效,您可以通过[OpenXLab](https://openxlab.org.cn/datasets?lang=zh-CN)下载数据集,例如 [Stanford Cars](https://openxlab.org.cn/datasets/OpenDataLab/Stanford_Cars)数据集。
## OpenMMLab 2.0 标准数据集
为了统一不同任务的数据集接口,便于多任务的算法模型训练,OpenMMLab 制定了 **OpenMMLab 2.0 数据集格式规范**, 数据集标注文件需符合该规范,数据集基类基于该规范去读取与解析数据标注文件。如果用户提供的数据标注文件不符合规定格式,用户可以选择将其转化为规定格式,并使用 OpenMMLab 的算法库基于该数据标注文件进行算法训练和测试。
OpenMMLab 2.0 数据集格式规范规定,标注文件必须为 `json``yaml``yml``pickle``pkl` 格式;标注文件中存储的字典必须包含 `metainfo``data_list` 两个字段。其中 `metainfo` 是一个字典,里面包含数据集的元信息;`data_list` 是一个列表,列表中每个元素是一个字典,该字典定义了一个原始数据(raw data),每个原始数据包含一个或若干个训练/测试样本。
假设您要使用训练数据集,那么配置文件如下所示:
```
{
'metainfo':
{
'classes': ('cat', 'dog'), # 'cat' 的类别序号为 0,'dog' 为 1。
...
},
'data_list':
[
{
'img_path': "xxx/xxx_0.jpg",
'gt_label': 0,
...
},
{
'img_path': "xxx/xxx_1.jpg",
'gt_label': 1,
...
},
...
]
}
```
同时假设数据集存放路径如下:
```text
data
├── annotations
│ ├── train.json
│ └── ...
├── train
│ ├── xxx/xxx_0.jpg
│ ├── xxx/xxx_1.jpg
│ ├── ...
```
通过以下字典构建:
```python
dataset_cfg=dict(
type='CustomDataset',
ann_file='path/to/ann_file_path',
data_prefix='path/to/images_folder',
pipeline=transfrom_list)
```
## 其他数据集
MMPretrain 还支持更多其他的数据集,可以通过查阅[数据集文档](mmpretrain.datasets)获取它们的配置信息。
如果需要使用一些特殊格式的数据集,您需要实现您自己的数据集类,请参阅[添加新数据集](../advanced_guides/datasets.md)
## 数据集包装
MMEngine 中支持以下数据包装器,您可以参考 {external+mmengine:doc}`MMEngine 教程 <advanced_tutorials/basedataset>` 了解如何使用它。
- {external:py:class}`~mmengine.dataset.ConcatDataset`
- {external:py:class}`~mmengine.dataset.RepeatDataset`
- {external:py:class}`~mmengine.dataset.ClassBalancedDataset`
除上述之外,MMPretrain 还支持了[KFoldDataset](mmpretrain.datasets.KFoldDataset),需用通过使用 `tools/kfold-cross-valid.py` 来使用它。
# 下游任务
## 检测
我们使用 MMDetection 进行图像检测。首先确保您已经安装了 [MIM](https://github.com/open-mmlab/mim),这也是 OpenMMLab 的一个项目。
```shell
pip install openmim
mim install 'mmdet>=3.0.0rc0'
```
此外,请参考 MMDetection 的[安装](https://mmdetection.readthedocs.io/en/dev-3.x/get_started.html)[数据准备](https://mmdetection.readthedocs.io/en/dev-3.x/user_guides/dataset_prepare.html)
### 训练
安装完后,您可以使用如下的简单命令运行 MMDetection。
```shell
# distributed version
bash tools/benchmarks/mmdetection/mim_dist_train_c4.sh ${CONFIG} ${PRETRAIN} ${GPUS}
bash tools/benchmarks/mmdetection/mim_dist_train_fpn.sh ${CONFIG} ${PRETRAIN} ${GPUS}
# slurm version
bash tools/benchmarks/mmdetection/mim_slurm_train_c4.sh ${PARTITION} ${CONFIG} ${PRETRAIN}
bash tools/benchmarks/mmdetection/mim_slurm_train_fpn.sh ${PARTITION} ${CONFIG} ${PRETRAIN}
```
- `${CONFIG}`:直接用 MMDetection 中的配置文件路径即可。对于一些算法,我们有一些修改过的配置文件,
可以在相应算法文件夹下的 `benchmarks` 文件夹中找到。另外,您也可以从头开始编写配置文件。
- `${PRETRAIN}`:预训练模型文件
- `${GPUS}`:使用多少 GPU 进行训练,对于检测任务,我们默认使用 8 个 GPU。
例子:
```shell
bash ./tools/benchmarks/mmdetection/mim_dist_train_c4.sh \
configs/byol/benchmarks/mask-rcnn_r50-c4_ms-1x_coco.py \
https://download.openmmlab.com/mmselfsup/1.x/byol/byol_resnet50_16xb256-coslr-200e_in1k/byol_resnet50_16xb256-coslr-200e_in1k_20220825-de817331.pth 8
```
### 测试
在训练之后,您可以运行如下命令测试您的模型。
```shell
# distributed version
bash tools/benchmarks/mmdetection/mim_dist_test.sh ${CONFIG} ${CHECKPOINT} ${GPUS}
# slurm version
bash tools/benchmarks/mmdetection/mim_slurm_test.sh ${PARTITION} ${CONFIG} ${CHECKPOINT}
```
备注:
- `${CHECKPOINT}`:您想测试的训练好的检测模型。
例子:
```shell
bash ./tools/benchmarks/mmdetection/mim_dist_test.sh \
configs/benchmarks/mmdetection/coco/mask-rcnn_r50_fpn_ms-1x_coco.py \
https://download.openmmlab.com/mmselfsup/1.x/byol/byol_resnet50_16xb256-coslr-200e_in1k/byol_resnet50_16xb256-coslr-200e_in1k_20220825-de817331.pth 8
```
## 分割
我们使用 MMSegmentation 进行图像分割。首先确保您已经安装了 [MIM](https://github.com/open-mmlab/mim),这也是 OpenMMLab 的一个项目。
```shell
pip install openmim
mim install 'mmsegmentation>=1.0.0rc0'
```
此外,请参考 MMSegmentation 的[安装](https://mmsegmentation.readthedocs.io/en/dev-1.x/get_started.html)[数据准备](https://mmsegmentation.readthedocs.io/en/dev-1.x/user_guides/2_dataset_prepare.html)
### 训练
在安装完后,可以使用如下简单命令运行 MMSegmentation。
```shell
# distributed version
bash tools/benchmarks/mmsegmentation/mim_dist_train.sh ${CONFIG} ${PRETRAIN} ${GPUS}
# slurm version
bash tools/benchmarks/mmsegmentation/mim_slurm_train.sh ${PARTITION} ${CONFIG} ${PRETRAIN}
```
备注:
- `${CONFIG}`:直接用 MMSegmentation 中的配置文件路径即可。对于一些算法,我们有一些修改过的配置文件,
可以在相应算法文件夹下的 `benchmarks` 文件夹中找到。另外,您也可以从头开始编写配置文件。
- `${PRETRAIN}`:预训练模型文件
- `${GPUS}`:使用多少 GPU 进行训练,对于检测任务,我们默认使用 8 个 GPU。
例子:
```shell
bash ./tools/benchmarks/mmsegmentation/mim_dist_train.sh \
configs/benchmarks/mmsegmentation/voc12aug/fcn_r50-d8_4xb4-20k_voc12aug-512x512.py \
https://download.openmmlab.com/mmselfsup/1.x/byol/byol_resnet50_16xb256-coslr-200e_in1k/byol_resnet50_16xb256-coslr-200e_in1k_20220825-de817331.pth 4
```
### 测试
在训练之后,您可以运行如下命令测试您的模型。
```shell
# distributed version
bash tools/benchmarks/mmsegmentation/mim_dist_test.sh ${CONFIG} ${CHECKPOINT} ${GPUS}
# slurm version
bash tools/benchmarks/mmsegmentation/mim_slurm_test.sh ${PARTITION} ${CONFIG} ${CHECKPOINT}
```
备注:
- `${CHECKPOINT}`:您想测试的训练好的分割模型。
例子:
```shell
bash ./tools/benchmarks/mmsegmentation/mim_dist_test.sh \
configs/benchmarks/mmsegmentation/voc12aug/fcn_r50-d8_4xb4-20k_voc12aug-512x512.py \
https://download.openmmlab.com/mmselfsup/1.x/byol/byol_resnet50_16xb256-coslr-200e_in1k/byol_resnet50_16xb256-coslr-200e_in1k_20220825-de817331.pth 4
```
# 使用现有模型进行推理
本文将展示如何使用以下API:
- [**`list_models`**](mmpretrain.apis.list_models): 列举 MMPretrain 中所有可用模型名称
- [**`get_model`**](mmpretrain.apis.get_model): 通过模型名称或模型配置文件获取模型
- [**`inference_model`**](mmpretrain.apis.inference_model): 使用与模型相对应任务的推理器进行推理。主要用作快速
展示。如需配置进阶用法,还需要直接使用下列推理器。
- 推理器:
1. [**`ImageClassificationInferencer`**](mmpretrain.apis.ImageClassificationInferencer):
对给定图像执行图像分类。
2. [**`ImageRetrievalInferencer`**](mmpretrain.apis.ImageRetrievalInferencer):
从给定的一系列图像中,检索与给定图像最相似的图像。
3. [**`ImageCaptionInferencer`**](mmpretrain.apis.ImageCaptionInferencer):
生成给定图像的一段描述。
4. [**`VisualQuestionAnsweringInferencer`**](mmpretrain.apis.VisualQuestionAnsweringInferencer):
根据给定的图像回答问题。
5. [**`VisualGroundingInferencer`**](mmpretrain.apis.VisualGroundingInferencer):
根据一段描述,从给定图像中找到一个与描述对应的对象。
6. [**`TextToImageRetrievalInferencer`**](mmpretrain.apis.TextToImageRetrievalInferencer):
从给定的一系列图像中,检索与给定文本最相似的图像。
7. [**`ImageToTextRetrievalInferencer`**](mmpretrain.apis.ImageToTextRetrievalInferencer):
从给定的一系列文本中,检索与给定图像最相似的文本。
8. [**`NLVRInferencer`**](mmpretrain.apis.NLVRInferencer):
对给定的一对图像和一段文本进行自然语言视觉推理(NLVR 任务)。
9. [**`FeatureExtractor`**](mmpretrain.apis.FeatureExtractor):
通过视觉主干网络从图像文件提取特征。
## 列举可用模型
列出 MMPreTrain 中的所有已支持的模型。
```python
>>> from mmpretrain import list_models
>>> list_models()
['barlowtwins_resnet50_8xb256-coslr-300e_in1k',
'beit-base-p16_beit-in21k-pre_3rdparty_in1k',
...]
```
`list_models` 支持 Unix 文件名风格的模式匹配,你可以使用 \*\* * \*\* 匹配任意字符。
```python
>>> from mmpretrain import list_models
>>> list_models("*convnext-b*21k")
['convnext-base_3rdparty_in21k',
'convnext-base_in21k-pre-3rdparty_in1k-384px',
'convnext-base_in21k-pre_3rdparty_in1k']
```
你还可以使用推理器的 `list_models` 方法获取对应任务可用的所有模型。
```python
>>> from mmpretrain import ImageCaptionInferencer
>>> ImageCaptionInferencer.list_models()
['blip-base_3rdparty_caption',
'blip2-opt2.7b_3rdparty-zeroshot_caption',
'flamingo_3rdparty-zeroshot_caption',
'ofa-base_3rdparty-finetuned_caption']
```
## 获取模型
选定需要的模型后,你可以使用 `get_model` 获取特定模型。
```python
>>> from mmpretrain import get_model
# 不加载预训练权重的模型
>>> model = get_model("convnext-base_in21k-pre_3rdparty_in1k")
# 加载默认的权重文件
>>> model = get_model("convnext-base_in21k-pre_3rdparty_in1k", pretrained=True)
# 加载制定的权重文件
>>> model = get_model("convnext-base_in21k-pre_3rdparty_in1k", pretrained="your_local_checkpoint_path")
# 指定额外的模型初始化参数,例如修改 head 中的 num_classes。
>>> model = get_model("convnext-base_in21k-pre_3rdparty_in1k", head=dict(num_classes=10))
# 另外一个例子:移除模型的 neck,head 模块,直接从 backbone 中的 stage 1, 2, 3 输出
>>> model_headless = get_model("resnet18_8xb32_in1k", head=None, neck=None, backbone=dict(out_indices=(1, 2, 3)))
```
获得的模型是一个通常的 PyTorch Module
```python
>>> import torch
>>> from mmpretrain import get_model
>>> model = get_model('convnext-base_in21k-pre_3rdparty_in1k', pretrained=True)
>>> x = torch.rand((1, 3, 224, 224))
>>> y = model(x)
>>> print(type(y), y.shape)
<class 'torch.Tensor'> torch.Size([1, 1000])
```
## 在给定图像上进行推理
这里是一个例子,我们将使用 ResNet-50 预训练模型对给定的 [图像](https://github.com/open-mmlab/mmpretrain/raw/main/demo/demo.JPEG) 进行分类。
```python
>>> from mmpretrain import inference_model
>>> image = 'https://github.com/open-mmlab/mmpretrain/raw/main/demo/demo.JPEG'
>>> # 如果你没有图形界面,请设置 `show=False`
>>> result = inference_model('resnet50_8xb32_in1k', image, show=True)
>>> print(result['pred_class'])
sea snake
```
上述 `inference_model` 接口可以快速进行模型推理,但它每次调用都需要重新初始化模型,也无法进行多个样本的推理。
因此我们需要使用推理器来进行多次调用。
```python
>>> from mmpretrain import ImageClassificationInferencer
>>> image = 'https://github.com/open-mmlab/mmpretrain/raw/main/demo/demo.JPEG'
>>> inferencer = ImageClassificationInferencer('resnet50_8xb32_in1k')
>>> # 注意推理器的输出始终为一个结果列表,即使输入只有一个样本
>>> result = inferencer('https://github.com/open-mmlab/mmpretrain/raw/main/demo/demo.JPEG')[0]
>>> print(result['pred_class'])
sea snake
>>>
>>> # 你可以对多张图像进行批量推理
>>> image_list = ['demo/demo.JPEG', 'demo/bird.JPEG'] * 16
>>> results = inferencer(image_list, batch_size=8)
>>> print(len(results))
32
>>> print(results[1]['pred_class'])
house finch, linnet, Carpodacus mexicanus
```
通常,每个样本的结果都是一个字典。比如图像分类的结果是一个包含了 `pred_label``pred_score``pred_scores``pred_class` 等字段的字典:
```python
{
"pred_label": 65,
"pred_score": 0.6649366617202759,
"pred_class":"sea snake",
"pred_scores": array([..., 0.6649366617202759, ...], dtype=float32)
}
```
你可以为推理器配置额外的参数,比如使用你自己的配置文件和权重文件,在 CUDA 上进行推理:
```python
>>> from mmpretrain import ImageClassificationInferencer
>>> image = 'https://github.com/open-mmlab/mmpretrain/raw/main/demo/demo.JPEG'
>>> config = 'configs/resnet/resnet50_8xb32_in1k.py'
>>> checkpoint = 'https://download.openmmlab.com/mmclassification/v0/resnet/resnet50_8xb32_in1k_20210831-ea4938fc.pth'
>>> inferencer = ImageClassificationInferencer(model=config, pretrained=checkpoint, device='cuda')
>>> result = inferencer(image)[0]
>>> print(result['pred_class'])
sea snake
```
## 使用 Gradio 推理示例
我们还提供了一个基于 gradio 的推理示例,提供了 MMPretrain 所支持的所有任务的推理展示功能,你可以在 [projects/gradio_demo/launch.py](https://github.com/open-mmlab/mmpretrain/blob/main/projects/gradio_demo/launch.py) 找到这一例程。
请首先使用 `pip install -U gradio` 安装 `gradio` 库。
这里是界面效果预览:
<img src="https://user-images.githubusercontent.com/26739999/236147750-90ccb517-92c0-44e9-905e-1473677023b1.jpg" width="100%"/>
## 从图像中提取特征
`model.extract_feat` 相比,`FeatureExtractor` 用于直接从图像文件中提取特征,而不是从一批张量中提取特征。简单说,`model.extract_feat` 的输入是 `torch.Tensor``FeatureExtractor` 的输入是图像。
```
>>> from mmpretrain import FeatureExtractor, get_model
>>> model = get_model('resnet50_8xb32_in1k', backbone=dict(out_indices=(0, 1, 2, 3)))
>>> extractor = FeatureExtractor(model)
>>> features = extractor('https://github.com/open-mmlab/mmpretrain/raw/main/demo/demo.JPEG')[0]
>>> features[0].shape, features[1].shape, features[2].shape, features[3].shape
(torch.Size([256]), torch.Size([512]), torch.Size([1024]), torch.Size([2048]))
```
# 测试
## 单机单卡测试
你可以使用 `tools/test.py` 在电脑上用 CPU 或是 GPU 进行模型的测试。
以下是测试脚本的完整用法:
```shell
python tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [ARGS]
```
````{note}
默认情况下,MMPretrain 会自动调用你的 GPU 进行测试。如果你有 GPU 但仍想使用 CPU 进行测试,请设置环境变量 `CUDA_VISIBLE_DEVICES` 为空或者 -1 来对禁用 GPU。
```bash
CUDA_VISIBLE_DEVICES=-1 python tools/test.py ${CONFIG_FILE} ${CHECKPOINT_FILE} [ARGS]
```
````
| 参数 | 描述 |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CONFIG_FILE` | 配置文件的路径。 |
| `CHECKPOINT_FILE` | 权重文件路径(支持 http 链接,你可以在[这里](https://mmpretrain.readthedocs.io/en/latest/modelzoo_statistics.html)寻找需要的权重文件)。 |
| `--work-dir WORK_DIR` | 用来保存测试指标结果的文件夹。 |
| `--out OUT` | 用来保存测试输出的文件。 |
| `--out-item OUT_ITEM` | 指定测试输出文件的内容,可以为 "pred" 或 "metrics",其中 "pred" 表示保存所有模型输出,这些数据可以用于离线测评;"metrics" 表示输出测试指标。默认为 "pred"。 |
| `--cfg-options CFG_OPTIONS` | 重载配置文件中的一些设置。使用类似 `xxx=yyy` 的键值对形式指定,这些设置会被融合入从配置文件读取的配置。你可以使用 `key="[a,b]"` 或者 `key=a,b` 的格式来指定列表格式的值,且支持嵌套,例如 \`key="[(a,b),(c,d)]",这里的引号是不可省略的。另外每个重载项内部不可出现空格。 |
| `--show-dir SHOW_DIR` | 用于保存可视化预测结果图像的文件夹。 |
| `--show` | 在窗口中显示预测结果图像。 |
| `--interval INTERVAL` | 每隔多少样本进行一次预测结果可视化。 |
| `--wait-time WAIT_TIME` | 每个窗口的显示时间(单位为秒)。 |
| `--no-pin-memory` | 是否在 dataloaders 中关闭 `pin_memory` 选项 |
| `--tta` | 是否开启 Test-Time-Aug (TTA). 如果配置文件有 `tta_pipeline``tta_model`,将使用这些配置指定 TTA transforms,并且决定如何融合 TTA 的结果。 否则,通过平均分类分数使用 flip TTA。 |
| `--launcher {none,pytorch,slurm,mpi}` | 启动器,默认为 "none"。 |
## 单机多卡测试
我们提供了一个 shell 脚本,可以使用 `torch.distributed.launch` 启动多 GPU 任务。
```shell
bash ./tools/dist_test.sh ${CONFIG_FILE} ${CHECKPOINT_FILE} ${GPU_NUM} [PY_ARGS]
```
| 参数 | 描述 |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `CONFIG_FILE` | 配置文件的路径。 |
| `CHECKPOINT_FILE` | 权重文件路径(支持 http 链接,你可以在[这里](https://mmpretrain.readthedocs.io/en/latest/modelzoo_statistics.html)寻找需要的权重文件)。 |
| `GPU_NUM` | 使用的 GPU 数量。 |
| `[PY_ARGS]` | `tools/test.py` 支持的其他可选参数,参见[上文](#单机单卡测试)。 |
你还可以使用环境变量来指定启动器的额外参数,比如用如下命令将启动器的通讯端口变更为 29666:
```shell
PORT=29666 bash ./tools/dist_test.sh ${CONFIG_FILE} ${CHECKPOINT_FILE} ${GPU_NUM} [PY_ARGS]
```
如果你希望使用不同的 GPU 进行多项测试任务,可以在启动时指定不同的通讯端口和不同的可用设备。
```shell
CUDA_VISIBLE_DEVICES=0,1,2,3 PORT=29500 bash ./tools/dist_test.sh ${CONFIG_FILE1} ${CHECKPOINT_FILE} 4 [PY_ARGS]
CUDA_VISIBLE_DEVICES=4,5,6,7 PORT=29501 bash ./tools/dist_test.sh ${CONFIG_FILE2} ${CHECKPOINT_FILE} 4 [PY_ARGS]
```
## 多机测试
### 同一网络下的多机
如果你希望使用同一局域网下连接的多台电脑进行一个测试任务,可以使用如下命令:
在第一台机器上:
```shell
NNODES=2 NODE_RANK=0 PORT=$MASTER_PORT MASTER_ADDR=$MASTER_ADDR bash tools/dist_test.sh $CONFIG $CHECKPOINT_FILE $GPUS
```
在第二台机器上:
```shell
NNODES=2 NODE_RANK=1 PORT=$MASTER_PORT MASTER_ADDR=$MASTER_ADDR bash tools/dist_test.sh $CONFIG $CHECKPOINT_FILE $GPUS
```
和单机多卡相比,你需要指定一些额外的环境变量:
| 环境变量 | 描述 |
| ------------- | ---------------------------------------------- |
| `NNODES` | 机器总数。 |
| `NODE_RANK` | 本机的序号 |
| `PORT` | 通讯端口,它在所有机器上都应当是一致的。 |
| `MASTER_ADDR` | 主机的 IP 地址,它在所有机器上都应当是一致的。 |
### Slurm 管理下的多机集群
如果你在 [slurm](https://slurm.schedmd.com/) 集群上,可以使用 `tools/slurm_test.sh` 脚本启动任务。
```shell
[ENV_VARS] ./tools/slurm_test.sh ${PARTITION} ${JOB_NAME} ${CONFIG_FILE} ${CHECKPOINT_FILE} [PY_ARGS]
```
这里是该脚本的一些参数:
| 参数 | 描述 |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `PARTITION` | 使用的集群分区。 |
| `JOB_NAME` | 任务的名称,你可以随意起一个名字。 |
| `CONFIG_FILE` | 配置文件路径。 |
| `CHECKPOINT_FILE` | 权重文件路径(支持 http 链接,你可以在[这里](https://mmpretrain.readthedocs.io/en/latest/modelzoo_statistics.html)寻找需要的权重文件)。 |
| `[PY_ARGS]` | `tools/test.py` 支持的其他可选参数,参见[上文](#单机单卡测试)。 |
这里是一些你可以用来配置 slurm 任务的环境变量:
| 环境变量 | 描述 |
| --------------- | ------------------------------------------------------------------------------------------ |
| `GPUS` | 使用的 GPU 总数,默认为 8。 |
| `GPUS_PER_NODE` | 每个节点分配的 GPU 数,你可以根据节点情况指定。默认为 8。 |
| `CPUS_PER_TASK` | 每个任务分配的 CPU 数(通常一个 GPU 对应一个任务)。默认为 5。 |
| `SRUN_ARGS` | `srun` 命令支持的其他参数。可用的选项参见[官方文档](https://slurm.schedmd.com/srun.html)。 |
# 训练
在本教程中,我们将介绍如何使用 MMPretrain 中提供的脚本启动训练任务。
如果你需要了解一些具体的训练例子,可以查阅 [如何在自定义数据集上进行模型预训练](../notes/pretrain_custom_dataset.md)[如何在自定义数据集上微调模型](../notes/finetune_custom_dataset.md).
## 单机单卡训练
你可以使用 `tools/train.py` 在电脑上用 CPU 或是 GPU 进行模型的训练。
以下是训练脚本的完整用法:
```shell
python tools/train.py ${CONFIG_FILE} [ARGS]
```
````{note}
默认情况下,MMPretrain 会自动调用你的 GPU 进行训练。如果你有 GPU 但仍想使用 CPU 进行训练,请设置环境变量 `CUDA_VISIBLE_DEVICES` 为空或者 -1 来对禁用 GPU。
```bash
CUDA_VISIBLE_DEVICES=-1 python tools/train.py ${CONFIG_FILE} [ARGS]
```
````
| 参数 | 描述 |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CONFIG_FILE` | 配置文件的路径。 |
| `--work-dir WORK_DIR` | 用来保存训练日志和权重文件的文件夹,默认是 `./work_dirs` 目录下,与配置文件同名的文件夹。 |
| `--resume [RESUME]` | 恢复训练。如果指定了权重文件路径,则从指定的权重文件恢复;如果没有指定,则尝试从最新的权重文件进行恢复。 |
| `--amp` | 启用混合精度训练。 |
| `--no-validate` | **不建议** 在训练过程中不进行验证集上的精度验证。 |
| `--auto-scale-lr` | 自动根据实际的批次大小(batch size)和预设的批次大小对学习率进行缩放。 |
| `--no-pin-memory` | 是否在 dataloaders 中关闭 `pin_memory` 选项 |
| `--no-persistent-workers` | 是否在 dataloaders 中关闭 `persistent_workers` 选项 |
| `--cfg-options CFG_OPTIONS` | 重载配置文件中的一些设置。使用类似 `xxx=yyy` 的键值对形式指定,这些设置会被融合入从配置文件读取的配置。你可以使用 `key="[a,b]"` 或者 `key=a,b` 的格式来指定列表格式的值,且支持嵌套,例如 \`key="[(a,b),(c,d)]",这里的引号是不可省略的。另外每个重载项内部不可出现空格。 |
| `--launcher {none,pytorch,slurm,mpi}` | 启动器,默认为 "none"。 |
## 单机多卡训练
我们提供了一个 shell 脚本,可以使用 `torch.distributed.launch` 启动多 GPU 任务。
```shell
bash ./tools/dist_train.sh ${CONFIG_FILE} ${GPU_NUM} [PY_ARGS]
```
| 参数 | 描述 |
| ------------- | ---------------------------------------------------------------- |
| `CONFIG_FILE` | 配置文件的路径。 |
| `GPU_NUM` | 使用的 GPU 数量。 |
| `[PY_ARGS]` | `tools/train.py` 支持的其他可选参数,参见[上文](#单机单卡训练)。 |
你还可以使用环境变量来指定启动器的额外参数,比如用如下命令将启动器的通讯端口变更为 29666:
```shell
PORT=29666 bash ./tools/dist_train.sh ${CONFIG_FILE} ${GPU_NUM} [PY_ARGS]
```
如果你希望使用不同的 GPU 进行多项训练任务,可以在启动时指定不同的通讯端口和不同的可用设备。
```shell
CUDA_VISIBLE_DEVICES=0,1,2,3 PORT=29500 bash ./tools/dist_train.sh ${CONFIG_FILE1} 4 [PY_ARGS]
CUDA_VISIBLE_DEVICES=4,5,6,7 PORT=29501 bash ./tools/dist_train.sh ${CONFIG_FILE2} 4 [PY_ARGS]
```
## 多机训练
### 同一网络下的多机
如果你希望使用同一局域网下连接的多台电脑进行一个训练任务,可以使用如下命令:
在第一台机器上:
```shell
NNODES=2 NODE_RANK=0 PORT=$MASTER_PORT MASTER_ADDR=$MASTER_ADDR bash tools/dist_train.sh $CONFIG $GPUS
```
在第二台机器上:
```shell
NNODES=2 NODE_RANK=1 PORT=$MASTER_PORT MASTER_ADDR=$MASTER_ADDR bash tools/dist_train.sh $CONFIG $GPUS
```
和单机多卡相比,你需要指定一些额外的环境变量:
| 环境变量 | 描述 |
| ------------- | ---------------------------------------------- |
| `NNODES` | 机器总数。 |
| `NODE_RANK` | 本机的序号 |
| `PORT` | 通讯端口,它在所有机器上都应当是一致的。 |
| `MASTER_ADDR` | 主机的 IP 地址,它在所有机器上都应当是一致的。 |
通常来说,如果这几台机器之间不是高速网络连接,训练速度会非常慢。
### Slurm 管理下的多机集群
如果你在 [slurm](https://slurm.schedmd.com/) 集群上,可以使用 `tools/slurm_train.sh` 脚本启动任务。
```shell
[ENV_VARS] ./tools/slurm_train.sh ${PARTITION} ${JOB_NAME} ${CONFIG_FILE} ${WORK_DIR} [PY_ARGS]
```
这里是该脚本的一些参数:
| 参数 | 描述 |
| ------------- | ---------------------------------------------------------------- |
| `PARTITION` | 使用的集群分区。 |
| `JOB_NAME` | 任务的名称,你可以随意起一个名字。 |
| `CONFIG_FILE` | 配置文件路径。 |
| `WORK_DIR` | 用以保存日志和权重文件的文件夹。 |
| `[PY_ARGS]` | `tools/train.py` 支持的其他可选参数,参见[上文](#单机单卡训练)。 |
这里是一些你可以用来配置 slurm 任务的环境变量:
| 环境变量 | 描述 |
| --------------- | ------------------------------------------------------------------------------------------ |
| `GPUS` | 使用的 GPU 总数,默认为 8。 |
| `GPUS_PER_NODE` | 每个节点分配的 GPU 数,你可以根据节点情况指定。默认为 8。 |
| `CPUS_PER_TASK` | 每个任务分配的 CPU 数(通常一个 GPU 对应一个任务)。默认为 5。 |
| `SRUN_ARGS` | `srun` 命令支持的其他参数。可用的选项参见[官方文档](https://slurm.schedmd.com/srun.html)。 |
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment