You need to sign in or sign up before continuing.
Commit b6df0d33 authored by limm's avatar limm
Browse files

add resources part

parent cbc25585
Pipeline #2802 canceled with stages
var collapsedSections = ['进阶教程', '模型库', '可视化', '分析工具', '部署', '其他说明'];
$(document).ready(function () {
$('.model-summary').DataTable({
"stateSave": false,
"lengthChange": false,
"pageLength": 20,
"order": [],
"language": {
"info": "显示 _START_ 至 _END_ 条目(总计 _TOTAL_ )",
"infoFiltered": "(筛选自 _MAX_ 条目)",
"search": "搜索:",
"zeroRecords": "没有找到任何条目",
"paginate": {
"next": "下一页",
"previous": "上一页"
},
}
});
});
{% extends "layout.html" %}
{% block body %}
<h1>未找到页面</h1>
<p>
未找到你要打开的页面。
</p>
<p>
如果你是从旧版本文档跳转至此,可能是对应的页面被移动了。请从左侧的目录中寻找新版本文档,或者跳转至<a href="{{ pathto(root_doc) }}">首页</a>
</p>
<p>
如果你找不到希望打开的文档,欢迎在 <a href="https://github.com/open-mmlab/mmpretrain/issues/new/choose">Issue</a> 中告诉我们!
</p>
{% endblock %}
.. role:: hidden
:class: hidden-section
.. currentmodule:: {{ module }}
{{ name | underline}}
.. autoclass:: {{ name }}
:members:
..
autogenerated from _templates/autosummary/class.rst
note it does not have :inherited-members:
.. role:: hidden
:class: hidden-section
.. currentmodule:: {{ module }}
{{ name | underline}}
.. autoclass:: {{ name }}
:members:
:special-members: __call__
..
autogenerated from _templates/callable.rst
note it does not have :inherited-members:
.. role:: hidden
:class: hidden-section
.. currentmodule:: {{ module }}
{{ name | underline}}
.. autoclass:: {{ name }}
:members: transform
..
autogenerated from _templates/callable.rst
note it does not have :inherited-members:
# MMPretrain 中的约定
## 模型命名规则
MMPretrain 按照以下风格进行模型命名,代码库的贡献者需要遵循相同的命名规则。模型名总体分为五个部分:算法信息,模块信息,预训练信息,训练信息和数据信息。逻辑上属于不同部分的单词之间用下划线 `'_'` 连接,同一部分有多个单词用短横线 `'-'` 连接。
```text
{algorithm info}_{module info}_{pretrain info}_{training info}_{data info}
```
- `algorithm info`(可选):算法信息,表示用以训练该模型的主要算法,如 MAE、BEiT 等
- `module info`:模块信息,主要包含模型的主干网络名称,如 resnet、vit 等
- `pretrain info`(可选):预训练信息,比如预训练模型是在 ImageNet-21k 数据集上训练的等
- `training info`:训练信息,训练策略设置,包括 batch size,schedule 以及数据增强等;
- `data info`:数据信息,数据集名称、模态、输入尺寸等,如 imagenet, cifar 等;
### 算法信息
指用以训练该模型的算法名称,例如:
- `simclr`
- `mocov2`
- `eva-mae-style`
使用监督图像分类任务训练的模型可以省略这个字段。
### 模块信息
指模型的结构信息,一般主要包含模型的主干网络结构,`neck``head` 信息一般被省略。例如:
- `resnet50`
- `vit-base-p16`
- `swin-base`
### 预训练信息
如果该模型是在预训练模型基础上,通过微调获得的,我们需要记录预训练模型的一些信息。例如:
- 预训练模型的来源:`fb``openai`等。
- 训练预训练模型的方法:`clip``mae``distill` 等。
- 用于预训练的数据集:`in21k``laion2b`等(`in1k`可以省略)
- 训练时长:`300e``1600e` 等。
并非所有信息都是必要的,只需要选择用以区分不同的预训练模型的信息即可。
在此字段的末尾,使用 `-pre` 作为标识符,例如 `mae-in21k-pre`
### 训练信息
训练策略的一些设置,包括训练类型、 `batch size``lr schedule`、 数据增强以及特殊的损失函数等等,比如:
Batch size 信息:
- 格式为`{gpu x batch_per_gpu}`, 如 `8xb32`
训练类型(主要见于 transformer 网络,如 `ViT` 算法,这类算法通常分为预训练和微调两种模式):
- `ft` : Finetune config,用于微调的配置文件
- `pt` : Pretrain config,用于预训练的配置文件
训练策略信息,训练策略以复现配置文件为基础,此基础不必标注训练策略。但如果在此基础上进行改进,则需注明训练策略,按照应用点位顺序排列,如:`{pipeline aug}-{train aug}-{loss trick}-{scheduler}-{epochs}`
- `coslr-200e` : 使用 cosine scheduler, 训练 200 个 epoch
- `autoaug-mixup-lbs-coslr-50e` : 使用了 `autoaug``mixup``label smooth``cosine scheduler`, 训练了 50 个轮次
如果模型是从官方仓库等第三方仓库转换过来的,训练信息可以省略,使用 `3rdparty` 作为标识符。
### 数据信息
- `in1k` : `ImageNet1k` 数据集,默认使用 `224x224` 大小的图片
- `in21k` : `ImageNet21k` 数据集,有些地方也称为 `ImageNet22k` 数据集,默认使用 `224x224` 大小的图片
- `in1k-384px` : 表示训练的输出图片大小为 `384x384`
- `cifar100`
### 模型命名案例
```text
vit-base-p32_clip-openai-pre_3rdparty_in1k
```
- `vit-base-p32`: 模块信息
- `clip-openai-pre`:预训练信息
- `clip`:预训练方法是 clip
- `openai`:预训练模型来自 OpenAI
- `pre`:预训练标识符
- `3rdparty`:模型是从第三方仓库转换而来的
- `in1k`:数据集信息。该模型是从 ImageNet-1k 数据集训练而来的,输入大小为 `224x224`
```text
beit_beit-base-p16_8xb256-amp-coslr-300e_in1k
```
- `beit`: 算法信息
- `beit-base`:模块信息,由于主干网络来自 BEiT 中提出的修改版 ViT,主干网络名称也是 `beit`
- `8xb256-amp-coslr-300e`:训练信息
- `8xb256`:使用 8 个 GPU,每个 GPU 的批量大小为 256
- `amp`:使用自动混合精度训练
- `coslr`:使用余弦退火学习率调度器
- `300e`:训练 300 个 epoch
- `in1k`:数据集信息。该模型是从 ImageNet-1k 数据集训练而来的,输入大小为 `224x224`
## 配置文件命名规则
配置文件的命名与模型名称几乎相同,有几点不同:
- 训练信息是必要的,不能是 `3rdparty`
- 如果配置文件只包含主干网络设置,既没有头部设置也没有数据集设置,我们将其命名为`{module info}_headless.py`。这种配置文件通常用于大型数据集上的第三方预训练模型。
### 权重命名规则
权重的命名主要包括模型名称,日期和哈希值。
```text
{model_name}_{date}-{hash}.pth
```
# 添加新数据集
用户可以编写一个继承自 [BasesDataset](https://mmpretrain.readthedocs.io/zh_CN/latest/_modules/mmpretrain/datasets/base_dataset.html#BaseDataset) 的新数据集类,并重载 `load_data_list(self)` 方法,类似 [CIFAR10](https://github.com/open-mmlab/mmpretrain/blob/main/mmpretrain/datasets/cifar.py)[ImageNet](https://github.com/open-mmlab/mmpretrain/blob/main/mmpretrain/datasets/imagenet.py)
通常,此方法返回一个包含所有样本的列表,其中的每个样本都是一个字典。字典中包含了必要的数据信息,例如 `img``gt_label`
假设我们将要实现一个 `Filelist` 数据集,该数据集将使用文件列表进行训练和测试。注释列表的格式如下:
```text
000001.jpg 0
000002.jpg 1
...
```
## 1. 创建数据集类
我们可以在 `mmpretrain/datasets/filelist.py` 中创建一个新的数据集类以加载数据。
```python
from mmpretrain.registry import DATASETS
from .base_dataset import BaseDataset
@DATASETS.register_module()
class Filelist(BaseDataset):
def load_data_list(self):
assert isinstance(self.ann_file, str)
data_list = []
with open(self.ann_file) as f:
samples = [x.strip().split(' ') for x in f.readlines()]
for filename, gt_label in samples:
img_path = add_prefix(filename, self.img_prefix)
info = {'img_path': img_path, 'gt_label': int(gt_label)}
data_list.append(info)
return data_list
```
## 2. 添加到库
将新的数据集类加入到 `mmpretrain/datasets/__init__.py` 中:
```python
from .base_dataset import BaseDataset
...
from .filelist import Filelist
__all__ = [
'BaseDataset', ... ,'Filelist'
]
```
### 3. 修改相关配置文件
然后在配置文件中,为了使用 `Filelist`,用户可以按以下方式修改配置
```python
train_dataloader = dict(
...
dataset=dict(
type='Filelist',
ann_file='image_list.txt',
pipeline=train_pipeline,
)
)
```
所有继承 [`BaseDataset`](https://github.com/open-mmlab/mmpretrain/blob/main/mmpretrain/datasets/base_dataset.py) 的数据集类都具有**懒加载**以及**节省内存**的特性,可以参考相关文档 {external+mmengine:doc}`BaseDataset <advanced_tutorials/basedataset>`
```{note}
如果数据样本时获取的字典中,只包含了 'img_path' 不包含 'img', 则在 pipeline 中必须包含 'LoadImgFromFile'。
```
# 自定义评估指标
## 使用 MMPretrain 中的指标
在 MMPretrain 中,我们为单标签分类和多标签分类提供了多种指标:
**单标签分类**:
- [`Accuracy`](mmpretrain.evaluation.Accuracy)
- [`SingleLabelMetric`](mmpretrain.evaluation.SingleLabelMetric),包括精度、召回率、f1-score 和支持度。
**多标签分类**:
- [`AveragePrecision`](mmpretrain.evaluation.AveragePrecision), 或 AP (mAP)。
- [`MultiLabelMetric`](mmpretrain.evaluation.MultiLabelMetric),包括精度、召回率、f1-score 和支持度。
要在验证和测试期间使用这些指标,我们需要修改配置文件中的 `val_evaluator``test_evaluator` 字段。
以下为几个例子:
1. 在验证和测试期间计算 top-1 和 top-5 准确率。
```python
val_evaluator = dict(type='Accuracy', topk=(1, 5))
test_evaluator = val_evaluator
```
2. 在验证和测试期间计算 top-1 准确率、top-5 准确度、精确度和召回率。
```python
val_evaluator = [
dict(type='Accuracy', topk=(1, 5)),
dict(type='SingleLabelMetric', items=['precision', 'recall']),
]
test_evaluator = val_evaluator
```
3. 计算 mAP(平均平均精度)、CP(类别平均精度)、CR(类别平均召回率)、CF(类别平均 F1 分数)、OP(总体平均精度)、OR(总体平均召回率)和 OF1(总体平均 F1 分数)。
```python
val_evaluator = [
dict(type='AveragePrecision'),
dict(type='MultiLabelMetric', average='macro'), # class-wise mean
dict(type='MultiLabelMetric', average='micro'), # overall mean
]
test_evaluator = val_evaluator
```
## 添加新的指标
MMPretrain 支持为追求更高定制化的用户实现定制化的评估指标。
您需要在 `mmpretrain/evaluation/metrics` 下创建一个新文件,并在该文件中实现新的指标,例如,在 `mmpretrain/evaluation/metrics/my_metric.py` 中。并创建一个自定义的评估指标类 `MyMetric` 继承 [MMEngine 中的 BaseMetric](mmengine.evaluator.BaseMetric)
需要分别覆盖数据格式处理方法`process`和度量计算方法`compute_metrics`。 将其添加到“METRICS”注册表以实施任何自定义评估指标。
```python
from mmengine.evaluator import BaseMetric
from mmpretrain.registry import METRICS
@METRICS.register_module()
class MyMetric(BaseMetric):
def process(self, data_batch: Sequence[Dict], data_samples: Sequence[Dict]):
""" The processed results should be stored in ``self.results``, which will
be used to computed the metrics when all batches have been processed.
`data_batch` stores the batch data from dataloader,
and `data_samples` stores the batch outputs from model.
"""
...
def compute_metrics(self, results: List):
""" Compute the metrics from processed results and returns the evaluation results.
"""
...
```
然后,将其导入 `mmpretrain/evaluation/metrics/__init__.py` 以将其添加到 `mmpretrain.evaluation` 包中。
```python
# In mmpretrain/evaluation/metrics/__init__.py
...
from .my_metric import MyMetric
__all__ = [..., 'MyMetric']
```
最后,在配置文件的 `val_evaluator``test_evaluator` 字段中使用 `MyMetric`
```python
val_evaluator = dict(type='MyMetric', ...)
test_evaluator = val_evaluator
```
```{note}
更多的细节可以参考 {external+mmengine:doc}`MMEngine 文档: Evaluation <design/evaluation>`.
```
# 自定义模型
在我们的设计中,我们定义一个完整的模型为顶层模块,根据功能的不同,基本几种不同类型的模型组件组成。
- 模型:顶层模块定义了具体的任务类型,例如 `ImageClassifier` 用在图像分类任务中, `MAE` 用在自监督学习中, `ImageToImageRetriever` 用在图像检索中。
- 主干网络:通常是一个特征提取网络,涵盖了模型之间绝大多数的差异,例如 `ResNet``MobileNet`
- 颈部:用于连接主干网络和头部的组件,例如 `GlobalAveragePooling`
- 头部:用于执行特定任务的组件,例如 `ClsHead``ContrastiveHead`
- 损失函数:在头部用于计算损失函数的组件,例如 `CrossEntropyLoss``LabelSmoothLoss`
- 目标生成器: 用于自监督学习任务的组件,例如 `VQKD``HOGGenerator`
## 添加新的顶层模型
通常来说,对于图像分类和图像检索任务来说,模型顶层模型流程基本一致。但是不同的自监督学习算法却用不同的计算流程,像 `MAE``BEiT` 就大不相同。 所以在这个部分,我们将简单介绍如何添加一个新的自监督学习算法。
### 添加新的自监督学习算法
1. 创建新文件 `mmpretrain/models/selfsup/new_algorithm.py` 以及实现 `NewAlgorithm`
```python
from mmpretrain.registry import MODELS
from .base import BaseSelfSupvisor
@MODELS.register_module()
class NewAlgorithm(BaseSelfSupvisor):
def __init__(self, backbone, neck=None, head=None, init_cfg=None):
super().__init__(init_cfg)
pass
# ``extract_feat`` function is defined in BaseSelfSupvisor, you could
# overwrite it if needed
def extract_feat(self, inputs, **kwargs):
pass
# the core function to compute the loss
def loss(self, inputs, data_samples, **kwargs):
pass
```
2.`mmpretrain/models/selfsup/__init__.py` 中导入对应的新算法
```python
...
from .new_algorithm import NewAlgorithm
__all__ = [
...,
'NewAlgorithm',
...
]
```
3. 在配置文件中使用新算法
```python
model = dict(
type='NewAlgorithm',
backbone=...,
neck=...,
head=...,
...
)
```
## 添加新的主干网络
这里,我们以 `ResNet_CIFAR` 为例,展示了如何开发一个新的主干网络组件。
`ResNet_CIFAR` 针对 CIFAR 32x32 的图像输入,远小于大多数模型使用的ImageNet默认的224x224输入配置,所以我们将骨干网络中 `kernel_size=7,stride=2`
的设置替换为 `kernel_size=3, stride=1`,并移除了 stem 层之后的
`MaxPooling`,以避免传递过小的特征图到残差块中。
最简单的方式就是继承自 `ResNet` 并只修改 stem 层。
1. 创建一个新文件 `mmpretrain/models/backbones/resnet_cifar.py`
```python
import torch.nn as nn
from mmpretrain.registry import MODELS
from .resnet import ResNet
@MODELS.register_module()
class ResNet_CIFAR(ResNet):
"""ResNet backbone for CIFAR.
(对这个主干网络的简短描述)
Args:
depth(int): Network depth, from {18, 34, 50, 101, 152}.
...
(参数文档)
"""
def __init__(self, depth, deep_stem=False, **kwargs):
# 调用基类 ResNet 的初始化函数
super(ResNet_CIFAR, self).__init__(depth, deep_stem=deep_stem **kwargs)
# 其他特殊的初始化流程
assert not self.deep_stem, 'ResNet_CIFAR do not support deep_stem'
def _make_stem_layer(self, in_channels, base_channels):
# 重载基类的方法,以实现对网络结构的修改
self.conv1 = build_conv_layer(
self.conv_cfg,
in_channels,
base_channels,
kernel_size=3,
stride=1,
padding=1,
bias=False)
self.norm1_name, norm1 = build_norm_layer(
self.norm_cfg, base_channels, postfix=1)
self.add_module(self.norm1_name, norm1)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
# 如果需要的话,可以自定义forward方法
x = self.conv1(x)
x = self.norm1(x)
x = self.relu(x)
outs = []
for i, layer_name in enumerate(self.res_layers):
res_layer = getattr(self, layer_name)
x = res_layer(x)
if i in self.out_indices:
outs.append(x)
# 输出值需要是一个包含不同层多尺度输出的元组
# 如果不需要多尺度特征,可以直接在最终输出上包一层元组
return tuple(outs)
def init_weights(self):
# 如果需要的话,可以自定义权重初始化的方法
super().init_weights()
# 如果有预训练模型,则不需要进行权重初始化
if self.init_cfg is not None and self.init_cfg['type'] == 'Pretrained':
return
# 通常来说,我们建议用`init_cfg`去列举不同层权重初始化方法
# 包括卷积层,线性层,归一化层等等
# 如果有特殊需要,可以在这里进行额外的初始化操作
...
```
```{note}
在 OpenMMLab 2.0 的设计中,将原有的`BACKBONES`、`NECKS`、`HEADS`、`LOSSES`等注册名统一为`MODELS`.
```
2.`mmpretrain/models/backbones/__init__.py` 中导入新模块
```python
...
from .resnet_cifar import ResNet_CIFAR
__all__ = [
..., 'ResNet_CIFAR'
]
```
3. 在配置文件中使用新的主干网络
```python
model = dict(
...
backbone=dict(
type='ResNet_CIFAR',
depth=18,
other_arg=xxx),
...
```
### 为自监督学习添加新的主干网络
对于一部分自监督学习算法,主干网络做了一定修改,例如 `MAE``BEiT` 等。 这些主干网络需要处理 `mask` 相关的逻辑,以此从可见的图像块中提取对应的特征信息。
[MAEViT](mmpretrain.models.selfsup.MAEViT) 作为例子,我们需要重写 `forward` 函数,进行基于 `mask` 的计算。我们实现了 `init_weights` 进行特定权重的初始化和 `random_masking` 函数来生成 `MAE` 预训练所需要的 `mask`
```python
class MAEViT(VisionTransformer):
"""Vision Transformer for MAE pre-training"""
def __init__(mask_ratio, **kwargs) -> None:
super().__init__(**kwargs)
# position embedding is not learnable during pretraining
self.pos_embed.requires_grad = False
self.mask_ratio = mask_ratio
self.num_patches = self.patch_resolution[0] * self.patch_resolution[1]
def init_weights(self) -> None:
"""Initialize position embedding, patch embedding and cls token."""
super().init_weights()
# define what if needed
pass
def random_masking(
self,
x: torch.Tensor,
mask_ratio: float = 0.75
) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""Generate the mask for MAE Pre-training."""
pass
def forward(
self,
x: torch.Tensor,
mask: Optional[bool] = True
) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""Generate features for masked images.
The function supports two kind of forward behaviors. If the ``mask`` is
``True``, the function will generate mask to masking some patches
randomly and get the hidden features for visible patches, which means
the function will be executed as masked imagemodeling pre-training;
if the ``mask`` is ``None`` or ``False``, the forward function will
call ``super().forward()``, which extract features from images without
mask.
"""
if mask is None or False:
return super().forward(x)
else:
B = x.shape[0]
x = self.patch_embed(x)[0]
# add pos embed w/o cls token
x = x + self.pos_embed[:, 1:, :]
# masking: length -> length * mask_ratio
x, mask, ids_restore = self.random_masking(x, self.mask_ratio)
# append cls token
cls_token = self.cls_token + self.pos_embed[:, :1, :]
cls_tokens = cls_token.expand(B, -1, -1)
x = torch.cat((cls_tokens, x), dim=1)
for _, layer in enumerate(self.layers):
x = layer(x)
# Use final norm
x = self.norm1(x)
return (x, mask, ids_restore)
```
## 添加新的颈部组件
这里我们以 `GlobalAveragePooling` 为例。这是一个非常简单的颈部组件,没有任何参数。
要添加新的颈部组件,我们主要需要实现 `forward` 函数,该函数对主干网络的输出进行
一些操作并将结果传递到头部。
1. 创建一个新文件 `mmpretrain/models/necks/gap.py`
```python
import torch.nn as nn
from mmpretrain.registry import MODELS
@MODELS.register_module()
class GlobalAveragePooling(nn.Module):
def __init__(self):
self.gap = nn.AdaptiveAvgPool2d((1, 1))
def forward(self, inputs):
# 简单起见,我们默认输入是一个张量
outs = self.gap(inputs)
outs = outs.view(inputs.size(0), -1)
return outs
```
2.`mmpretrain/models/necks/__init__.py` 中导入新模块
```python
...
from .gap import GlobalAveragePooling
__all__ = [
..., 'GlobalAveragePooling'
]
```
3. 修改配置文件以使用新的颈部组件
```python
model = dict(
neck=dict(type='GlobalAveragePooling'),
)
```
## 添加新的头部组件
### 基于分类头
在此,我们以一个简化的 `VisionTransformerClsHead` 为例,说明如何开发新的头部组件。
要添加一个新的头部组件,基本上我们需要实现 `pre_logits` 函数用于进入最后的分类头之前需要的处理,
以及 `forward` 函数。
1. 创建一个文件 `mmpretrain/models/heads/vit_head.py`.
```python
import torch.nn as nn
from mmpretrain.registry import MODELS
from .cls_head import ClsHead
@MODELS.register_module()
class LinearClsHead(ClsHead):
def __init__(self, num_classes, in_channels, hidden_dim, **kwargs):
super().__init__(**kwargs)
self.in_channels = in_channels
self.num_classes = num_classes
self.hidden_dim = hidden_dim
self.fc1 = nn.Linear(in_channels, hidden_dim)
self.act = nn.Tanh()
self.fc2 = nn.Linear(hidden_dim, num_classes)
def pre_logits(self, feats):
# 骨干网络的输出通常包含多尺度信息的元组
# 对于分类任务来说,我们只需要关注最后的输出
feat = feats[-1]
# VisionTransformer的最终输出是一个包含patch tokens和cls tokens的元组
# 这里我们只需要cls tokens
_, cls_token = feat
# 完成除了最后的线性分类头以外的操作
return self.act(self.fc1(cls_token))
def forward(self, feats):
pre_logits = self.pre_logits(feats)
# 完成最后的分类头
cls_score = self.fc(pre_logits)
return cls_score
```
2.`mmpretrain/models/heads/__init__.py` 中导入这个模块
```python
...
from .vit_head import VisionTransformerClsHead
__all__ = [
..., 'VisionTransformerClsHead'
]
```
3. 修改配置文件以使用新的头部组件。
```python
model = dict(
head=dict(
type='VisionTransformerClsHead',
...,
))
```
### 基于 BaseModule 类
这是一个基于 MMEngine 中的 `BaseModule` 进行开发例子,`MAEPretrainHead`,主要是为了 `MAE` 掩码学习。我们需要实现 `loss` 函数来计算损失吗,不过其它的函数均为可选项。
```python
# Copyright (c) OpenMMLab. All rights reserved.
import torch
from mmengine.model import BaseModule
from mmpretrain.registry import MODELS
@MODELS.register_module()
class MAEPretrainHead(BaseModule):
"""Head for MAE Pre-training."""
def __init__(self,
loss: dict,
norm_pix: bool = False,
patch_size: int = 16) -> None:
super().__init__()
self.norm_pix = norm_pix
self.patch_size = patch_size
self.loss_module = MODELS.build(loss)
def patchify(self, imgs: torch.Tensor) -> torch.Tensor:
"""Split images into non-overlapped patches."""
p = self.patch_size
assert imgs.shape[2] == imgs.shape[3] and imgs.shape[2] % p == 0
h = w = imgs.shape[2] // p
x = imgs.reshape(shape=(imgs.shape[0], 3, h, p, w, p))
x = torch.einsum('nchpwq->nhwpqc', x)
x = x.reshape(shape=(imgs.shape[0], h * w, p**2 * 3))
return x
def construct_target(self, target: torch.Tensor) -> torch.Tensor:
"""Construct the reconstruction target."""
target = self.patchify(target)
if self.norm_pix:
# normalize the target image
mean = target.mean(dim=-1, keepdim=True)
var = target.var(dim=-1, keepdim=True)
target = (target - mean) / (var + 1.e-6)**.5
return target
def loss(self, pred: torch.Tensor, target: torch.Tensor,
mask: torch.Tensor) -> torch.Tensor:
"""Generate loss."""
target = self.construct_target(target)
loss = self.loss_module(pred, target, mask)
return loss
```
完成实现后,之后的步骤和 [基于分类头](#基于分类头) 中的步骤 2 和步骤 3 一致。
## 添加新的损失函数
要添加新的损失函数,我们主要需要在损失函数模块中 `forward` 函数。这里需要注意的是,损失模块也应该注册到`MODELS`中。另外,利用装饰器 `weighted_loss` 可以方便的实现对每个元素的损失进行加权平均。
假设我们要模拟从另一个分类模型生成的概率分布,需要添加 `L1loss` 来实现该目的。
1. 创建一个新文件 `mmpretrain/models/losses/l1_loss.py`
```python
import torch
import torch.nn as nn
from mmpretrain.registry import MODELS
from .utils import weighted_loss
@weighted_loss
def l1_loss(pred, target):
assert pred.size() == target.size() and target.numel() > 0
loss = torch.abs(pred - target)
return loss
@MODELS.register_module()
class L1Loss(nn.Module):
def __init__(self, reduction='mean', loss_weight=1.0):
super(L1Loss, self).__init__()
self.reduction = reduction
self.loss_weight = loss_weight
def forward(self,
pred,
target,
weight=None,
avg_factor=None,
reduction_override=None):
assert reduction_override in (None, 'none', 'mean', 'sum')
reduction = (
reduction_override if reduction_override else self.reduction)
loss = self.loss_weight * l1_loss(
pred, target, weight, reduction=reduction, avg_factor=avg_factor)
return loss
```
2. 在文件 `mmpretrain/models/losses/__init__.py` 中导入这个模块
```python
...
from .l1_loss import L1Loss
__all__ = [
..., 'L1Loss'
]
```
3. 修改配置文件中的 `loss` 字段以使用新的损失函数
```python
model = dict(
head=dict(
loss=dict(type='L1Loss', loss_weight=1.0),
))
```
最后我们可以在配置文件中结合所有新增的模型组件来使用新的模型。由于`ResNet_CIFAR` 不是一个基于ViT的骨干网络,这里我们不用`VisionTransformerClsHead`的配置。
```python
model = dict(
type='ImageClassifier',
backbone=dict(
type='ResNet_CIFAR',
depth=18,
num_stages=4,
out_indices=(3, ),
style='pytorch'),
neck=dict(type='GlobalAveragePooling'),
head=dict(
type='LinearClsHead',
num_classes=10,
in_channels=512,
loss=dict(type='L1Loss', loss_weight=1.0),
topk=(1, 5),
))
```
```{tip}
为了方便,相同的模型组件可以直接从已有的config文件里继承,更多细节可以参考[学习配置文件](../user_guides/config.md)。
```
# 自定义数据处理流程
## 数据流的设计
[新数据集教程](./datasets.md)中,我们知道数据集类使用 `load_data_list` 方法来初始化整个数据集,我们将每个样本的信息保存到一个 dict 中。
通常,为了节省内存,我们只加载 `load_data_list` 中的图片路径和标签,使用时加载完整的图片内容。此外,我们可能希望在训练时选择样本时进行一些随机数据扩充。几乎所有的数据加载、预处理和格式化操作都可以通过**数据管道**在 MMPretrain 中进行配置。
数据管道意味着在从数据集中索引样本时如何处理样本字典,它由一系列数据变换组成。每个数据变换都将一个字典作为输入,对其进行处理,并为下一个数据变换输出一个字典。
这是 ImageNet 上 ResNet-50 训练的数据管道示例。
```python
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='RandomResizedCrop', scale=224),
dict(type='RandomFlip', prob=0.5, direction='horizontal'),
dict(type='PackInputs'),
]
```
MMPretrain 中所有可用的数据变换都可以在 [数据变换文档](mmpretrain.datasets.transforms) 中找到。
## 修改训练/测试管道
MMPretrain 中的数据管道非常灵活。您几乎可以从配置文件中控制数据预处理的每一步,但另一方面,面对如此多的选项,您可能会感到困惑。
这是图像分类任务的常见做法和指南。
### 读取
在数据管道的开始,我们通常需要从文件路径加载图像数据。
[`LoadImageFromFile`](mmcv.transforms.LoadImageFromFile) 通常用于执行此任务。
```python
train_pipeline = [
dict(type='LoadImageFromFile'),
...
]
```
如果您想从具有特殊格式或特殊位置的文件中加载数据,您可以 [实施新的加载变换](#添加新的数据变换) 并将其添加到数据管道的开头。
### 增强和其它处理
在训练过程中,我们通常需要做数据增强来避免过拟合。在测试过程中,我们还需要做一些数据处理,比如调整大小和裁剪。这些数据变换将放置在加载过程之后。
这是一个简单的数据扩充方案示例。它会将输入图像随机调整大小并裁剪到指定比例,并随机水平翻转图像。
```python
train_pipeline = [
...
dict(type='RandomResizedCrop', scale=224),
dict(type='RandomFlip', prob=0.5, direction='horizontal'),
...
]
```
这是 [Swin-Transformer](../papers/swin_transformer.md) 训练中使用的大量数据增强配方示例。 为了与官方实施保持一致,它指定 `pillow` 作为调整大小后端,`bicubic` 作为调整大小算法。 此外,它添加了 [`RandAugment`](mmpretrain.datasets.transforms.RandAugment)[`RandomErasing`](mmpretrain.datasets.transforms.RandomErasing) 作为额外的数据增强方法。
此配置指定了数据扩充的每个细节,您只需将其复制到您自己的配置文件中即可应用 Swin-Transformer 的数据扩充。
```python
bgr_mean = [103.53, 116.28, 123.675]
bgr_std = [57.375, 57.12, 58.395]
train_pipeline = [
...
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=9,
magnitude_std=0.5,
hparams=dict(
pad_val=[round(x) for x in bgr_mean], interpolation='bicubic')),
dict(
type='RandomErasing',
erase_prob=0.25,
mode='rand',
min_area_ratio=0.02,
max_area_ratio=1 / 3,
fill_color=bgr_mean,
fill_std=bgr_std),
...
]
```
```{note}
通常,数据管道中的数据增强部分仅处理图像方面的变换,而不处理图像归一化或混合/剪切混合等变换。 因为我们可以对 batch data 做 image normalization 和 mixup/cutmix 来加速。要配置图像归一化和 mixup/cutmix,请使用 [数据预处理器](mmpretrain.models.utils.data_preprocessor)。
```
### 格式化
格式化是从数据信息字典中收集训练数据,并将这些数据转换为模型友好的格式。
在大多数情况下,您可以简单地使用 [`PackInputs`](mmpretrain.datasets.transforms.PackInputs),它将 NumPy 数组格式的图像转换为 PyTorch 张量,并将 ground truth 类别信息和其他元信息打包为 [`DataSample`](mmpretrain.structures.DataSample)
```python
train_pipeline = [
...
dict(type='PackInputs'),
]
```
## 添加新的数据变换
1. 在任何文件中写入一个新的数据转换,例如 `my_transform.py`,并将其放在文件夹 `mmpretrain/datasets/transforms/` 中。 数据变换类需要继承 [`mmcv.transforms.BaseTransform`](mmcv.transforms.BaseTransform) 类并覆盖以字典作为输入并返回字典的 `transform` 方法。
```python
from mmcv.transforms import BaseTransform
from mmpretrain.registry import TRANSFORMS
@TRANSFORMS.register_module()
class MyTransform(BaseTransform):
def transform(self, results):
# Modify the data information dict `results`.
return results
```
2.`mmpretrain/datasets/transforms/__init__.py` 中导入新的变换
```python
...
from .my_transform import MyTransform
__all__ = [
..., 'MyTransform'
]
```
3. 在配置文件中使用
```python
train_pipeline = [
...
dict(type='MyTransform'),
...
]
```
## 数据管道可视化
数据流水线设计完成后,可以使用 [可视化工具](../useful_tools/dataset_visualization.md) 查看效果。
# 自定义运行参数
运行参数配置包括许多有用的功能,如权重文件保存、日志配置等等,在本教程中,我们将介绍如何配置这些功能。
## 保存权重文件
权重文件保存功能是一个在训练阶段默认注册的钩子, 你可以通过配置文件中的 `default_hooks.checkpoint` 字段配置它。
```{note}
钩子机制在 OpenMMLab 开源算法库中应用非常广泛。通过钩子,你可以在不修改运行器的主要执行逻辑的情况下插入许多功能。
可以通过{external+mmengine:doc}`相关文章 <tutorials/hook>`进一步理解钩子。
```
**默认配置:**
```python
default_hooks = dict(
...
checkpoint = dict(type='CheckpointHook', interval=1)
...
)
```
下面是一些[权重文件钩子(CheckpointHook)](mmengine.hooks.CheckpointHook)的常用可配置参数。
- **`interval`** (int): 文件保存周期。如果使用-1,它将永远不会保存权重。
- **`by_epoch`** (bool): 选择 **`interval`** 是基于epoch还是基于iteration, 默认为 `True`.
- **`out_dir`** (str): 保存权重文件的根目录。如果不指定,检查点将被保存在工作目录中。如果指定,检查点将被保存在 **`out_dir`** 的子文件夹中。
- **`max_keep_ckpts`** (int): 要保留的权重文件数量。在某些情况下,为了节省磁盘空间,我们希望只保留最近的几个权重文件。默认为 -1,也就是无限制。
- **`save_best`** (str, List[str]): 如果指定,它将保存具有最佳评估结果的权重。
通常情况下,你可以直接使用`save_best="auto"`来自动选择评估指标。
而如果你想要更高级的配置,请参考[权重文件钩子(CheckpointHook)](tutorials/hook.md#checkpointhook)
## 权重加载 / 断点训练
在配置文件中,你可以加载指定模型权重或者断点继续训练,如下所示:
```python
# 从指定权重文件加载
load_from = "Your checkpoint path"
# 是否从加载的断点继续训练
resume = False
```
`load_from` 字段可以是本地路径,也可以是HTTP路径。你可以从检查点恢复训练,方法是指定 `resume=True`
```{tip}
你也可以通过指定 `load_from=None` 和 `resume=True` 启用从最新的断点自动恢复。
Runner执行器将自动从工作目录中找到最新的权重文件。
```
如果你用我们的 `tools/train.py` 脚本来训练模型,你只需使用 `--resume` 参数来恢复训练,就不用手动修改配置文件了。如下所示:
```bash
# 自动从最新的断点恢复
python tools/train.py configs/resnet/resnet50_8xb32_in1k.py --resume
# 从指定的断点恢复
python tools/train.py configs/resnet/resnet50_8xb32_in1k.py --resume checkpoints/resnet.pth
```
## 随机性(Randomness)配置
为了让实验尽可能是可复现的, 我们在 `randomness` 字段中提供了一些控制随机性的选项。
默认情况下,我们不会在配置文件中指定随机数种子,在每次实验中,程序会生成一个不同的随机数种子。
**默认配置:**
```python
randomness = dict(seed=None, deterministic=False)
```
为了使实验更具可复现性,你可以指定一个种子并设置 `deterministic=True`
`deterministic` 选项的使用效果可以在[这里](https://pytorch.org/docs/stable/notes/randomness.html#cuda-convolution-benchmarking)找到。
## 日志配置
日志的配置与多个字段有关。
`log_level`字段中,你可以指定全局日志级别。参见 {external+python:ref}`Logging Levels<levels>` 以获得日志级别列表。
```python
log_level = 'INFO'
```
`default_hooks.logger` 字段中,你可以指定训练和测试期间的日志间隔。
而所有可用的参数可以在[日志钩子文档](tutorials/hook.md#loggerhook)中找到。
```python
default_hooks = dict(
...
# 每100次迭代就打印一次日志
logger=dict(type='LoggerHook', interval=100),
...
)
```
`log_processor` 字段中,你可以指定日志信息的平滑方法。
通常,我们使用一个长度为10的窗口来平滑日志中的值,并输出所有信息的平均值。
如果你想特别指定某些信息的平滑方法,请参阅{external+mmengine:doc}`日志处理器文档 <advanced_tutorials/logging>`
```python
# 默认设置,它将通过一个10长度的窗口平滑训练日志中的值
log_processor = dict(window_size=10)
```
`visualizer` 字段中,你可以指定多个后端来保存日志信息,如TensorBoard和WandB。
更多的细节可以在[可视化工具](#visualizer)找到。
## 自定义钩子
上述许多功能是由钩子实现的,你也可以通过修改 `custom_hooks` 字段来插入其他的自定义钩子。
下面是 MMEngine 和 MMPretrain 中的一些钩子,你可以直接使用,例如:
- [EMAHook](mmpretrain.engine.hooks.EMAHook)
- [SyncBuffersHook](mmengine.hooks.SyncBuffersHook)
- [EmptyCacheHook](mmengine.hooks.EmptyCacheHook)
- [ClassNumCheckHook](mmpretrain.engine.hooks.ClassNumCheckHook)
- ......
例如,EMA(Exponential Moving Average)在模型训练中被广泛使用,你可以以下方式启用它:
```python
custom_hooks = [
dict(type='EMAHook', momentum=4e-5, priority='ABOVE_NORMAL'),
]
```
## 验证可视化
验证可视化钩子是一个验证过程中默认注册的钩子。
你可以在 `default_hooks.visualization` 字段中来配置它。
默认情况下,我们禁用这个钩子,你可以通过指定 `enable=True` 来启用它。而更多的参数可以在
[可视化钩子文档](mmpretrain.engine.hooks.VisualizationHook)中找到。
```python
default_hooks = dict(
...
visualization=dict(type='VisualizationHook', enable=False),
...
)
```
这个钩子将在验证数据集中选择一部分图像,在每次验证过程中记录并可视化它们的预测结果。
你可以用它来观察训练期间模型在实际图像上的性能变化。
此外,如果你的验证数据集中的图像很小(\<100, 如Cifra数据集),
你可以指定 `rescale_factor` 来缩放它们,如 `rescale_factor=2.`, 将可视化的图像放大两倍。
## Visualizer
`Visualizer` 用于记录训练和测试过程中的各种信息,包括日志、图像和标量。
默认情况下,记录的信息将被保存在工作目录下的 `vis_data` 文件夹中。
**默认配置:**
```python
visualizer = dict(
type='UniversalVisualizer',
vis_backends=[
dict(type='LocalVisBackend'),
]
)
```
通常,最有用的功能是将日志和标量如 `loss` 保存到不同的后端。
例如,要把它们保存到 TensorBoard,只需像下面这样设置:
```python
visualizer = dict(
type='UniversalVisualizer',
vis_backends=[
dict(type='LocalVisBackend'),
dict(type='TensorboardVisBackend'),
]
)
```
或者像下面这样把它们保存到 WandB:
```python
visualizer = dict(
type='UniversalVisualizer',
vis_backends=[
dict(type='LocalVisBackend'),
dict(type='WandbVisBackend'),
]
)
```
## 环境配置
`env_cfg` 字段中,你可以配置一些底层的参数,如 cuDNN、多进程和分布式通信。
**在修改这些参数之前,请确保你理解这些参数的含义。**
```python
env_cfg = dict(
# 是否启用cudnn基准测试
cudnn_benchmark=False,
# 设置多进程参数
mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),
# 设置分布式参数
dist_cfg=dict(backend='nccl'),
)
```
# 自定义训练优化策略
在我们的算法库中,已经提供了通用数据集(如ImageNet,CIFAR)的[默认训练策略配置](https://github.com/open-mmlab/mmpretrain/blob/main/configs/_base_/schedules)。如果想要在这些数据集上继续提升模型性能,或者在不同数据集和方法上进行新的尝试,我们通常需要修改这些默认的策略。
在本教程中,我们将介绍如何在运行自定义训练时,通过修改配置文件进行构造优化器、参数化精细配置、梯度裁剪、梯度累计以及定制动量调整策略等。同时也会通过模板简单介绍如何自定义开发优化器和构造器。
## 配置训练优化策略
我们通过 `optim_wrapper` 来配置主要的优化策略,包括优化器的选择,混合精度训练的选择,参数化精细配置,梯度裁剪以及梯度累计。接下来将分别介绍这些内容。
### 构造 PyTorch 内置优化器
MMPretrain 支持 PyTorch 实现的所有优化器,仅需在配置文件中,指定优化器封装需要的 `optimizer` 字段。
如果要使用 [`SGD`](torch.optim.SGD),则修改如下。这里要注意所有优化相关的配置都需要封装在 `optim_wrapper` 配置里。
```python
optim_wrapper = dict(
type='OptimWrapper',
optimizer=dict(type='SGD', lr=0.0003, weight_decay=0.0001)
)
```
```{note}
配置文件中的 'type' 不是构造时的参数,而是 PyTorch 内置优化器的类名。
更多优化器选择可以参考{external+torch:ref}`PyTorch 支持的优化器列表<optim:algorithms>`。
```
要修改模型的学习率,只需要在优化器的配置中修改 `lr` 即可。
要配置其他参数,可直接根据 [PyTorch API 文档](torch.optim) 进行。
例如,如果想使用 [`Adam`](torch.optim.Adam) 并设置参数为 `torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)`
则需要进行如下修改:
```python
optim_wrapper = dict(
type='OptimWrapper',
optimizer = dict(
type='Adam',
lr=0.001,
betas=(0.9, 0.999),
eps=1e-08,
weight_decay=0,
amsgrad=False),
)
```
````{note}
考虑到对于单精度训练来说,优化器封装的默认类型就是 `OptimWrapper`,我们在这里可以直接省略,因此配置文件可以进一步简化为:
```python
optim_wrapper = dict(
optimizer=dict(
type='Adam',
lr=0.001,
betas=(0.9, 0.999),
eps=1e-08,
weight_decay=0,
amsgrad=False))
```
````
### 混合精度训练
如果我们想要使用混合精度训练(Automactic Mixed Precision),我们只需简单地将 `optim_wrapper` 的类型改为 `AmpOptimWrapper`
```python
optim_wrapper = dict(type='AmpOptimWrapper', optimizer=...)
```
另外,为了方便,我们同时在启动训练脚本 `tools/train.py` 中提供了 `--amp` 参数作为开启混合精度训练的开关,更多细节可以参考[训练教程](../user_guides/train.md)
### 参数化精细配置
在一些模型中,不同的优化策略需要适应特定的参数,例如不在 BatchNorm 层使用权重衰减,或者在不同层使用不同的学习率等等。
我们需要用到 `optim_wrapper` 中的 `paramwise_cfg` 参数来进行精细化配置。
- **为不同类型的参数设置超参乘子**
例如,我们可以在 `paramwise_cfg` 配置中设置 `norm_decay_mult=0.` 来改变归一化层权重和偏移的衰减为0。
```python
optim_wrapper = dict(
optimizer=dict(type='SGD', lr=0.8, weight_decay=1e-4),
paramwise_cfg=dict(norm_decay_mult=0.))
```
支持更多类型的参数配置,参考以下列表:
- `bias_lr_mult`:偏置的学习率系数(不包括正则化层的偏置以及可变形卷积的 offset),默认值为 1
- `bias_decay_mult`:偏置的权值衰减系数(不包括正则化层的偏置以及可变形卷积的 offset),默认值为 1
- `norm_decay_mult`:正则化层权重和偏置的权值衰减系数,默认值为 1
- `flat_decay_mult`: 一维参数的权值衰减系数,默认值为 1
- `dwconv_decay_mult`:Depth-wise 卷积的权值衰减系数,默认值为 1
- `bypass_duplicate`:是否跳过重复的参数,默认为 `False`
- `dcn_offset_lr_mult`:可变形卷积(Deformable Convolution)的学习率系数,默认值为 1
- **为特定参数设置超参乘子**
MMPretrain 通过 `paramwise_cfg``custom_keys` 参数来配置特定参数的超参乘子。
例如,我们可以通过以下配置来设置所有 `backbone.layer0` 层的学习率和权重衰减为0, `backbone` 的其余层和优化器保持一致,另外 `head` 层的学习率为0.001.
```python
optim_wrapper = dict(
optimizer=dict(type='SGD', lr=0.01, weight_decay=0.0001),
paramwise_cfg=dict(
custom_keys={
'backbone.layer0': dict(lr_mult=0, decay_mult=0),
'backbone': dict(lr_mult=1),
'head': dict(lr_mult=0.1)
}))
```
### 梯度裁剪
在训练过程中,损失函数可能接近于一些异常陡峭的区域,从而导致梯度爆炸。而梯度裁剪可以帮助稳定训练过程,更多介绍可以参见[该页面](https://paperswithcode.com/method/gradient-clipping)
目前我们支持在 `optim_wrapper` 字段中添加 `clip_grad` 参数来进行梯度裁剪,更详细的参数可参考 [PyTorch 文档](torch.nn.utils.clip_grad_norm_)
用例如下:
```python
optim_wrapper = dict(
optimizer=dict(type='SGD', lr=0.01, weight_decay=0.0001),
# norm_type: 使用的范数类型,此处使用范数2。
clip_grad=dict(max_norm=35, norm_type=2))
```
### 梯度累计
计算资源缺乏缺乏时,每个训练批次的大小(batch size)只能设置为较小的值,这可能会影响模型的性能。
可以使用梯度累计来规避这一问题。我们支持在 `optim_wrapper` 字段中添加 `accumulative_counts` 参数来进行梯度累计。
用例如下:
```python
train_dataloader = dict(batch_size=64)
optim_wrapper = dict(
optimizer=dict(type='SGD', lr=0.01, weight_decay=0.0001),
accumulative_counts=4)
```
表示训练时,每 4 个 iter 执行一次反向传播。由于此时单张 GPU 上的批次大小为 64,也就等价于单张 GPU 上一次迭代的批次大小为 256,也即:
```python
train_dataloader = dict(batch_size=256)
optim_wrapper = dict(
optimizer=dict(type='SGD', lr=0.01, weight_decay=0.0001))
```
## 配置参数优化策略
在训练过程中,优化参数例如学习率、动量,通常不会是固定不变,而是随着训练进程的变化而调整。PyTorch 支持一些学习率调整的调度器,但是不足以完成复杂的策略。在 MMPretrain 中,我们提供 `param_scheduler` 来更好地控制不同优化参数的策略。
### 配置学习率调整策略
深度学习研究中,广泛应用学习率衰减来提高网络的性能。我们支持大多数 PyTorch 学习率调度器, 其中包括 `ExponentialLR`, `LinearLR`, `StepLR`, `MultiStepLR` 等等。
- **单个学习率策略**
多数情况下,我们使用单一学习率策略,这里 `param_scheduler` 会是一个字典。比如在默认的 ResNet 网络训练中,我们使用阶梯式的学习率衰减策略 [`MultiStepLR`](mmengine.optim.MultiStepLR),配置文件为:
```python
param_scheduler = dict(
type='MultiStepLR',
by_epoch=True,
milestones=[100, 150],
gamma=0.1)
```
或者我们想使用 [`CosineAnnealingLR`](mmengine.optim.CosineAnnealingLR) 来进行学习率衰减:
```python
param_scheduler = dict(
type='CosineAnnealingLR',
by_epoch=True,
T_max=num_epochs)
```
- **多个学习率策略**
然而在一些其他情况下,为了提高模型的精度,通常会使用多种学习率策略。例如,在训练的早期阶段,网络容易不稳定,而学习率的预热就是为了减少这种不稳定性。
整个学习过程中,学习率将会通过预热从一个很小的值逐步提高到预定值,再会通过其他的策略进一步调整。
在 MMPretrain 中,我们同样使用 `param_scheduler` ,将多种学习策略写成列表就可以完成上述预热策略的组合。
例如:
1. 在前50次迭代中逐**迭代次数****线性**预热
```python
param_scheduler = [
# 逐迭代次数,线性预热
dict(type='LinearLR',
start_factor=0.001,
by_epoch=False, # 逐迭代次数
end=50), # 只预热50次迭代次数
# 主要的学习率策略
dict(type='MultiStepLR',
by_epoch=True,
milestones=[8, 11],
gamma=0.1)
]
```
2. 在前10轮迭代中逐**迭代次数****线性**预热
```python
param_scheduler = [
# 在前10轮迭代中,逐迭代次数,线性预热
dict(type='LinearLR',
start_factor=0.001,
by_epoch=True,
end=10,
convert_to_iter_based=True, # 逐迭代次数更新学习率.
),
# 在 10 轮次后,通过余弦退火衰减
dict(type='CosineAnnealingLR', by_epoch=True, begin=10)
]
```
注意这里增加了 `begin``end` 参数,这两个参数指定了调度器的**生效区间**。生效区间通常只在多个调度器组合时才需要去设置,使用单个调度器时可以忽略。当指定了 `begin``end` 参数时,表示该调度器只在 [begin, end) 区间内生效,其单位是由 `by_epoch` 参数决定。在组合不同调度器时,各调度器的 `by_epoch` 参数不必相同。如果没有指定的情况下,`begin` 为 0, `end` 为最大迭代轮次或者最大迭代次数。
如果相邻两个调度器的生效区间没有紧邻,而是有一段区间没有被覆盖,那么这段区间的学习率维持不变。而如果两个调度器的生效区间发生了重叠,则对多组调度器叠加使用,学习率的调整会按照调度器配置文件中的顺序触发(行为与 PyTorch 中 [`ChainedScheduler`](torch.optim.lr_scheduler.ChainedScheduler) 一致)。
```{tip}
为了避免学习率曲线与预期不符, 配置完成后,可以使用 MMPretrain 提供的 [学习率可视化工具](../useful_tools/scheduler_visualization.md) 画出对应学习率调整曲线。
```
### 配置动量调整策略
MMPretrain 支持动量调度器根据学习率修改优化器的动量,从而使损失函数收敛更快。用法和学习率调度器一致。
我们支持的动量策略和详细的使用细节可以参考[这里](https://github.com/open-mmlab/mmengine/blob/main/mmengine/optim/scheduler/momentum_scheduler.py)。我们只将调度器中的 `LR` 替换为了 `Momentum`,动量策略可以直接追加 `param_scheduler` 列表中。
这里是一个用例:
```python
param_scheduler = [
# 学习率策略
dict(type='LinearLR', ...),
# 动量策略
dict(type='LinearMomentum',
start_factor=0.001,
by_epoch=False,
begin=0,
end=1000)
]
```
## 新增优化器或者优化器构造器
```{note}
本部分将修改 MMPretrain 源码或者向 MMPretrain 框架添加代码,初学者可跳过。
```
### 新增优化器
在学术研究和工业实践中,可能需要使用 MMPretrain 未实现的优化方法,可以通过以下方法添加。
1. 定义一个新的优化器
一个自定义的优化器可根据如下规则进行定制:
假设我们想添加一个名为 `MyOptimzer` 的优化器,其拥有参数 `a`, `b``c`
可以创建一个名为 `mmpretrain/engine/optimizer` 的文件夹,并在目录下的一个文件,如 `mmpretrain/engine/optimizer/my_optimizer.py` 中实现该自定义优化器:
```python
from mmpretrain.registry import OPTIMIZERS
from torch.optim import Optimizer
@OPTIMIZERS.register_module()
class MyOptimizer(Optimizer):
def __init__(self, a, b, c):
...
def step(self, closure=None):
...
```
2. 注册优化器
要注册上面定义的上述模块,首先需要将此模块导入到主命名空间中。有两种方法可以实现它。
修改 `mmpretrain/engine/optimizers/__init__.py`,将其导入至 `mmpretrain.engine` 包。
```python
# 在 mmpretrain/engine/optimizers/__init__.py 中
...
from .my_optimizer import MyOptimizer # MyOptimizer 是我们自定义的优化器的名字
__all__ = [..., 'MyOptimizer']
```
在运行过程中,我们会自动导入 `mmpretrain.engine` 包并同时注册 `MyOptimizer`
3. 在配置文件中指定优化器
之后,用户便可在配置文件的 `optim_wrapper.optimizer` 域中使用 `MyOptimizer`
```python
optim_wrapper = dict(
optimizer=dict(type='MyOptimizer', a=a_value, b=b_value, c=c_value))
```
### 新增优化器构造器
某些模型可能具有一些特定于参数的设置以进行优化,例如为所有 BatchNorm 层设置不同的权重衰减。
尽管我们已经可以使用 [`optim_wrapper.paramwise_cfg` 字段](#参数化精细配置)来配置特定参数的优化设置,但可能仍然无法覆盖你的需求。
当然你可以在此基础上进行修改。我们默认使用 [`DefaultOptimWrapperConstructor`](mmengine.optim.DefaultOptimWrapperConstructor) 来构造优化器。在构造过程中,通过 `paramwise_cfg` 来精细化配置不同设置。这个默认构造器可以作为新优化器构造器实现的模板。
我们可以新增一个优化器构造器来覆盖这些行为。
```python
# 在 mmpretrain/engine/optimizers/my_optim_constructor.py 中
from mmengine.optim import DefaultOptimWrapperConstructor
from mmpretrain.registry import OPTIM_WRAPPER_CONSTRUCTORS
@OPTIM_WRAPPER_CONSTRUCTORS.register_module()
class MyOptimWrapperConstructor:
def __init__(self, optim_wrapper_cfg, paramwise_cfg=None):
...
def __call__(self, model):
...
```
这是一个已实现的 [OptimWrapperConstructor](mmpretrain.engine.optimizers.LearningRateDecayOptimWrapperConstructor) 具体例子。
接下来类似 [新增优化器教程](#新增优化器) 来导入并使用新的优化器构造器。
1. 修改 `mmpretrain/engine/optimizers/__init__.py`,将其导入至 `mmpretrain.engine` 包。
```python
# 在 mmpretrain/engine/optimizers/__init__.py 中
...
from .my_optim_constructor import MyOptimWrapperConstructor
__all__ = [..., 'MyOptimWrapperConstructor']
```
2. 在配置文件的 `optim_wrapper.constructor` 字段中使用 `MyOptimWrapperConstructor`
```python
optim_wrapper = dict(
constructor=dict(type='MyOptimWrapperConstructor'),
optimizer=...,
paramwise_cfg=...,
)
```
../en/api
\ No newline at end of file
# flake8: noqa
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import subprocess
import sys
import pytorch_sphinx_theme
from sphinx.builders.html import StandaloneHTMLBuilder
sys.path.insert(0, os.path.abspath('../../'))
# -- Project information -----------------------------------------------------
project = 'MMPretrain'
copyright = '2020, OpenMMLab'
author = 'MMPretrain Authors'
# The full version, including alpha/beta/rc tags
version_file = '../../mmpretrain/version.py'
def get_version():
with open(version_file, 'r') as f:
exec(compile(f.read(), version_file, 'exec'))
return locals()['__version__']
release = get_version()
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'sphinx.ext.viewcode',
'myst_parser',
'sphinx_copybutton',
'sphinx_tabs.tabs',
'notfound.extension',
'sphinxcontrib.jquery',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
source_suffix = {
'.rst': 'restructuredtext',
'.md': 'markdown',
}
language = 'zh_CN'
# The master toctree document.
root_doc = 'index'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'pytorch_sphinx_theme'
html_theme_path = [pytorch_sphinx_theme.get_html_theme_path()]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# yapf: disable
html_theme_options = {
'menu': [
{
'name': 'GitHub',
'url': 'https://github.com/open-mmlab/mmpretrain'
},
{
'name': 'Colab 教程',
'children': [
{'name': '用命令行工具训练和推理',
'url': 'https://colab.research.google.com/github/mzr1996/mmpretrain-tutorial/blob/master/1.x/MMPretrain_tools.ipynb'},
{'name': '用 Python API 训练和推理',
'url': 'https://colab.research.google.com/github/mzr1996/mmpretrain-tutorial/blob/master/1.x/MMPretrain_python.ipynb'},
]
},
{
'name': 'Version',
'children': [
{'name': 'MMPretrain 0.x',
'url': 'https://mmpretrain.readthedocs.io/zh_CN/0.x/',
'description': '0.x branch'},
{'name': 'MMPretrain 1.x',
'url': 'https://mmpretrain.readthedocs.io/zh_CN/latest/',
'description': 'Main branch'},
],
}
],
# Specify the language of shared menu
'menu_lang': 'cn',
# Disable the default edit on GitHub
'default_edit_on_github': False,
}
# yapf: enable
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'https://cdn.datatables.net/v/bs4/dt-1.12.1/datatables.min.css',
'css/readthedocs.css'
]
html_js_files = [
'https://cdn.datatables.net/v/bs4/dt-1.12.1/datatables.min.js',
'js/custom.js'
]
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'mmpretraindoc'
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(root_doc, 'mmpretrain.tex', 'MMPretrain Documentation', author, 'manual'),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(root_doc, 'mmpretrain', 'MMPretrain Documentation', [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(root_doc, 'mmpretrain', 'MMPretrain Documentation', author, 'mmpretrain',
'OpenMMLab pre-training toolbox and benchmark.', 'Miscellaneous'),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# set priority when building html
StandaloneHTMLBuilder.supported_image_types = [
'image/svg+xml', 'image/gif', 'image/png', 'image/jpeg'
]
# -- Extension configuration -------------------------------------------------
# Ignore >>> when copying code
copybutton_prompt_text = r'>>> |\.\.\. '
copybutton_prompt_is_regexp = True
# Auto-generated header anchors
myst_heading_anchors = 3
# Enable "colon_fence" extension of myst.
myst_enable_extensions = ['colon_fence', 'dollarmath']
# Configuration for intersphinx
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
'numpy': ('https://numpy.org/doc/stable', None),
'torch': ('https://pytorch.org/docs/stable/', None),
'mmcv': ('https://mmcv.readthedocs.io/zh_CN/2.x/', None),
'mmengine': ('https://mmengine.readthedocs.io/zh_CN/latest/', None),
'transformers':
('https://huggingface.co/docs/transformers/main/zh/', None),
}
napoleon_custom_sections = [
# Custom sections for data elements.
('Meta fields', 'params_style'),
('Data fields', 'params_style'),
]
# Disable docstring inheritance
autodoc_inherit_docstrings = False
# Mock some imports during generate API docs.
autodoc_mock_imports = ['rich', 'attr', 'einops', 'mat4py']
# Disable displaying type annotations, these can be very verbose
autodoc_typehints = 'none'
# The not found page
notfound_template = '404.html'
def builder_inited_handler(app):
if subprocess.run(['./stat.py']).returncode != 0:
raise RuntimeError('Failed to run the script `stat.py`.')
def setup(app):
app.add_config_value('no_underscore_emphasis', False, 'env')
app.connect('builder-inited', builder_inited_handler)
# NPU (华为昇腾)
## 使用方法
首先,请参考[链接](https://mmcv.readthedocs.io/zh_CN/latest/get_started/build.html#npu-mmcv-full)安装带有 NPU 支持的 MMCV 和[链接](https://mmengine.readthedocs.io/en/latest/get_started/installation.html#build-from-source)安装 MMEngine。
使用如下命令,可以利用 8 个 NPU 在机器上训练模型(以 ResNet 为例):
```shell
bash tools/dist_train.sh configs/cspnet/resnet50_8xb32_in1k.py 8
```
或者,使用如下命令,在一个 NPU 上训练模型(以 ResNet 为例):
```shell
python tools/train.py configs/cspnet/resnet50_8xb32_in1k.py
```
## 经过验证的模型
| Model | Top-1 (%) | Top-5 (%) | Config | Download |
| :---------------------------------------------------------: | :-------: | :-------: | :----------------------------------------------------------: | :-------------------------------------------------------------: |
| [ResNet-50](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/resnet/README.md) | 76.40 | 93.21 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/resnet/resnet50_8xb32_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/resnet50_8xb32_in1k.log) |
| [ResNetXt-32x4d-50](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/resnext/README.md) | 77.48 | 93.75 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/resnext/resnext50-32x4d_8xb32_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/resnext50-32x4d_8xb32_in1k.log) |
| [HRNet-W18](https://github.com/open-mmlab/mmclassification/blob/master/configs/hrnet/README.md) | 77.06 | 93.57 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/hrnet/hrnet-w18_4xb32_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/hrnet-w18_4xb32_in1k.log) |
| [ResNetV1D-152](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/resnet/README.md) | 79.41 | 94.48 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/resnet/resnetv1d152_8xb32_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/resnetv1d152_8xb32_in1k.log) |
| [SE-ResNet-50](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/seresnet/README.md) | 77.65 | 93.74 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/seresnet/seresnet50_8xb32_in1k.py) | [model](<>) \|[log](https://download.openmmlab.com/mmclassification/v1/device/npu/seresnet50_8xb32_in1k.log) |
| [ShuffleNetV2 1.0x](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/shufflenet_v2/README.md) | 69.52 | 88.79 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/shufflenet_v2/shufflenet-v2-1x_16xb64_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/shufflenet-v2-1x_16xb64_in1k.log) |
| [MobileNetV2](https://github.com/open-mmlab/mmclassification/tree/1.x/configs/mobilenet_v2) | 71.74 | 90.28 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/mobilenet_v2/mobilenet-v2_8xb32_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/mobilenet-v2_8xb32_in1k.log) |
| [MobileNetV3-Small](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/mobilenet_v3/README.md) | 67.09 | 87.17 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/mobilenet_v3/mobilenet-v3-small_8xb128_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/mobilenet-v3-small.log) |
| [\*CSPResNeXt50](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/cspnet/README.md) | 77.25 | 93.46 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/cspnet/cspresnext50_8xb32_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/cspresnext50_8xb32_in1k.log) |
| [\*EfficientNet-B4](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/efficientnet/README.md) | 75.73 | 92.9100 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/efficientnet/efficientnet-b4_8xb32_in1k.py) | [model](<>) \|[log](https://download.openmmlab.com/mmclassification/v1/device/npu/efficientnet-b4_8xb32_in1k.log) |
| [\*\*DenseNet121](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/densenet/README.md) | 72.53 | 90.85 | [config](https://github.com/open-mmlab/mmclassification/blob/1.x/configs/densenet/densenet121_4xb256_in1k.py) | [model](<>) \| [log](https://download.openmmlab.com/mmclassification/v1/device/npu/densenet121_4xb256_in1k.log) |
**注意:**
- 如果没有特别标记,NPU 上的结果与使用 FP32 的 GPU 上的结果结果相同。
- (\*) 这些模型的训练结果低于相应模型中自述文件上的结果,主要是因为自述文件上的结果直接是 timm 训练得出的权重,而这边的结果是根据 mmcls 的配置重新训练得到的结果。GPU 上的配置训练结果与 NPU 的结果相同。
- (\*\*)这个模型的精度略低,因为 config 是 4 张卡的配置,我们使用 8 张卡来运行,用户可以调整超参数以获得最佳精度结果。
**以上所有模型权重及训练日志均由华为昇腾团队提供**
[html writers]
table_style: colwidths-auto
# 依赖环境
在本节中,我们将演示如何准备 PyTorch 相关的依赖环境。
MMPretrain 适用于 Linux、Windows 和 macOS。它需要 Python 3.7+、CUDA 10.2+ 和 PyTorch 1.8+。
```{note}
如果你对配置 PyTorch 环境已经很熟悉,并且已经完成了配置,可以直接进入[下一节](#安装)。
否则的话,请依照以下步骤完成配置。
```
**第 1 步**[官网](https://docs.conda.io/en/latest/miniconda.html)下载并安装 Miniconda。
**第 2 步** 创建一个 conda 虚拟环境并激活它。
```shell
conda create --name openmmlab python=3.8 -y
conda activate openmmlab
```
**第 3 步** 按照[官方指南](https://pytorch.org/get-started/locally/)安装 PyTorch。例如:
在 GPU 平台:
```shell
conda install pytorch torchvision -c pytorch
```
```{warning}
以上命令会自动安装最新版的 PyTorch 与对应的 cudatoolkit,请检查它们是否与你的环境匹配。
```
在 CPU 平台:
```shell
conda install pytorch torchvision cpuonly -c pytorch
```
# 安装
我们推荐用户按照我们的最佳实践来安装 MMPretrain。但除此之外,如果你想根据
你的习惯完成安装流程,也可以参见[自定义安装](#自定义安装)一节来获取更多信息。
## 最佳实践
根据具体需求,我们支持两种安装模式:
- [从源码安装(推荐)](#从源码安装):希望基于 MMPretrain 框架开发自己的预训练任务,需要添加新的功能,比如新的模型或是数据集,或者使用我们提供的各种工具。
- [作为 Python 包安装](#作为-python-包安装):只是希望调用 MMPretrain 的 API 接口,或者在自己的项目中导入 MMPretrain 中的模块。
### 从源码安装
这种情况下,从源码按如下方式安装 mmpretrain:
```shell
git clone https://github.com/open-mmlab/mmpretrain.git
cd mmpretrain
pip install -U openmim && mim install -e .
```
```{note}
`"-e"` 表示以可编辑形式安装,这样可以在不重新安装的情况下,让本地修改直接生效
```
### 作为 Python 包安装
直接使用 mim 安装即可。
```shell
pip install -U openmim && mim install "mmpretrain>=1.0.0rc8"
```
```{note}
`mim` 是一个轻量级的命令行工具,可以根据 PyTorch 和 CUDA 版本为 OpenMMLab 算法库配置合适的环境。同时它也提供了一些对于深度学习实验很有帮助的功能。
```
## 安装多模态支持 (可选)
MMPretrain 中的多模态模型需要额外的依赖项,要安装这些依赖项,请在安装过程中添加 `[multimodal]` 参数,如下所示:
```shell
# 从源码安装
mim install -e ".[multimodal]"
# 作为 Python 包安装
mim install "mmpretrain[multimodal]>=1.0.0rc8"
```
## 验证安装
为了验证 MMPretrain 的安装是否正确,我们提供了一些示例代码来执行模型推理。
如果你是**从源码安装**的 mmpretrain,那么直接运行以下命令进行验证:
```shell
python demo/image_demo.py demo/demo.JPEG resnet18_8xb32_in1k --device cpu
```
你可以看到命令行中输出了结果字典,包括 `pred_label``pred_score``pred_class` 三个字段。
如果你是**作为 Python 包安装**,那么可以打开你的 Python 解释器,并粘贴如下代码:
```python
from mmpretrain import get_model, inference_model
model = get_model('resnet18_8xb32_in1k', device='cpu') # 或者 device='cuda:0'
inference_model(model, 'demo/demo.JPEG')
```
你会看到输出一个字典,包含预测的标签、得分及类别名。
```{note}
以上示例中,`resnet18_8xb32_in1k` 是模型名称。你可以使用 [`mmpretrain.list_models`](mmpretrain.apis.list_models) 接口来
浏览所有的模型,或者在[模型汇总](./modelzoo_statistics.md)页面进行查找。
```
## 自定义安装
### CUDA 版本
安装 PyTorch 时,需要指定 CUDA 版本。如果您不清楚选择哪个,请遵循我们的建议:
- 对于 Ampere 架构的 NVIDIA GPU,例如 GeForce 30 series 以及 NVIDIA A100,CUDA 11 是必需的。
- 对于更早的 NVIDIA GPU,CUDA 11 是向前兼容的,但 CUDA 10.2 能够提供更好的兼容性,也更加轻量。
请确保你的 GPU 驱动版本满足最低的版本需求,参阅[这张表](https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-major-component-versions__table-cuda-toolkit-driver-versions)
```{note}
如果按照我们的最佳实践进行安装,CUDA 运行时库就足够了,因为我们提供相关 CUDA 代码的预编译,你不需要进行本地编译。
但如果你希望从源码进行 MMCV 的编译,或是进行其他 CUDA 算子的开发,那么就必须安装完整的 CUDA 工具链,参见
[NVIDIA 官网](https://developer.nvidia.com/cuda-downloads),另外还需要确保该 CUDA 工具链的版本与 PyTorch 安装时
的配置相匹配(如用 `conda install` 安装 PyTorch 时指定的 cudatoolkit 版本)。
```
### 在 CPU 环境中安装
MMPretrain 可以仅在 CPU 环境中安装,在 CPU 模式下,你可以完成训练、测试和模型推理等所有操作。
### 在 Google Colab 中安装
参考 [Colab 教程](https://colab.research.google.com/github/mzr1996/mmclassification-tutorial/blob/master/1.x/MMClassification_tools.ipynb) 安装即可。
### 通过 Docker 使用 MMPretrain
MMPretrain 提供 [Dockerfile](https://github.com/open-mmlab/mmpretrain/blob/main/docker/Dockerfile)
用于构建镜像。请确保你的 [Docker 版本](https://docs.docker.com/engine/install/) >=19.03。
```shell
# 构建默认的 PyTorch 1.12.1,CUDA 11.3 版本镜像
# 如果你希望使用其他版本,请修改 Dockerfile
docker build -t mmpretrain docker/
```
用以下命令运行 Docker 镜像:
```shell
docker run --gpus all --shm-size=8g -it -v {DATA_DIR}:/mmpretrain/data mmpretrain
```
## 故障解决
如果你在安装过程中遇到了什么问题,请先查阅[常见问题](./notes/faq.md)。如果没有找到解决方法,可以在 GitHub
[提出 issue](https://github.com/open-mmlab/mmpretrain/issues/new/choose)
欢迎来到 MMPretrain 中文教程!
==========================================
MMPretrain 是一个全新升级的预训练开源算法框架,旨在提供各种强大的预训练主干网络,
并支持了不同的预训练策略。MMPretrain 源自著名的开源项目
`MMClassification <https://github.com/open-mmlab/mmclassification/tree/1.x>`_
和 `MMSelfSup <https://github.com/open-mmlab/mmselfsup>`_,并开发了许多令人兴奋的新功能。
目前,预训练阶段对于视觉识别至关重要,凭借丰富而强大的预训练模型,我们能够改进各种下游视觉任务。
我们的代码库旨在成为一个易于使用和用户友好的代码库库,并简化学术研究活动和工程任务。
我们在以下不同部分中详细介绍了 MMPretrain 的特性和设计。
MMPretrain 上手路线
-------------------------------
为了用户能够快速上手,我们推荐以下流程:
- 对于想要使用 MMPretrain 的用户,我们推荐先阅读 开始你的第一步_ 部分来设置环境。
- 对于一些基础使用,我们建议用户阅读 教程_ 来学习如何使用算法库来获得预训练模型以及在下游任务进行评测。
- 若您想进行算法的自定义,我们提供了 进阶教程_ 来阐述了代码修改的方法和规则。
- 如果您想找到所期望的预训练模型,您可以浏览 模型库_,其中包含了模型库的总结,以及各类主干网络和预训练算法的介绍。
- 我们同样提供了 分析工具_ 和 可视化_ 来辅助模型分析。
- 另外,如果您还有其它问题,欢迎查阅 其他说明_,也许可以找到您想要的答案。
我们始终非常欢迎用户的 PRs 和 Issues 来完善 MMPretrain!
.. _开始你的第一步:
.. toctree::
:maxdepth: 1
:caption: 开始你的第一步
get_started.md
.. _教程:
.. toctree::
:maxdepth: 1
:caption: 教程
user_guides/config.md
user_guides/dataset_prepare.md
user_guides/inference.md
user_guides/train.md
user_guides/test.md
user_guides/downstream.md
.. _进阶教程:
.. toctree::
:maxdepth: 1
:caption: 进阶教程
advanced_guides/datasets.md
advanced_guides/pipeline.md
advanced_guides/modules.md
advanced_guides/schedule.md
advanced_guides/runtime.md
advanced_guides/evaluation.md
advanced_guides/convention.md
.. _模型库:
.. toctree::
:maxdepth: 1
:caption: 模型库
:glob:
modelzoo_statistics.md
papers/*
.. _可视化:
.. toctree::
:maxdepth: 1
:caption: 可视化
useful_tools/dataset_visualization.md
useful_tools/scheduler_visualization.md
useful_tools/cam_visualization.md
useful_tools/t-sne_visualization.md
.. _分析工具:
.. toctree::
:maxdepth: 1
:caption: 分析工具
useful_tools/print_config.md
useful_tools/verify_dataset.md
useful_tools/log_result_analysis.md
useful_tools/complexity_analysis.md
useful_tools/confusion_matrix.md
useful_tools/shape_bias.md
.. toctree::
:maxdepth: 1
:caption: 部署
useful_tools/model_serving.md
.. toctree::
:maxdepth: 1
:caption: 迁移指南
migration.md
.. toctree::
:maxdepth: 1
:caption: API 参考文档
mmpretrain.apis <api/apis>
mmpretrain.engine <api/engine>
mmpretrain.datasets <api/datasets>
数据处理 <api/data_process>
mmpretrain.models <api/models>
mmpretrain.structures <api/structures>
mmpretrain.visualization <api/visualization>
mmpretrain.evaluation <api/evaluation>
mmpretrain.utils <api/utils>
.. _其他说明:
.. toctree::
:maxdepth: 1
:caption: 其他说明
notes/contribution_guide.md
notes/projects.md
notes/changelog.md
notes/faq.md
notes/pretrain_custom_dataset.md
notes/finetune_custom_dataset.md
.. toctree::
:maxdepth: 1
:caption: 设备支持
device/npu.md
.. toctree::
:caption: 切换语言
English <https://mmpretrain.readthedocs.io/en/latest/>
简体中文 <https://mmpretrain.readthedocs.io/zh_CN/latest/>
索引与表格
==================
* :ref:`genindex`
* :ref:`search`
This source diff could not be displayed because it is too large. You can view the blob instead.
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