Commit 6f3c5f1c authored by limm's avatar limm
Browse files

support v1.4.0

parent 6f674c7e
## Frequently Asked Questions
We list some common troubles faced by many users and their corresponding solutions here.
Feel free to enrich the list if you find any frequent issues and have ways to help others to solve them.
- Compatibility issue between MMCV and MMDetection; "ConvWS is already registered in conv layer"
Please install the correct version of MMCV for the version of your MMDetection following the instruction above.
- "No module named 'mmcv.ops'"; "No module named 'mmcv._ext'".
1. Uninstall existing mmcv in the environment using `pip uninstall mmcv`.
2. Install mmcv-full following the instruction above.
- "invalid device function" or "no kernel image is available for execution".
1. Check the CUDA compute capability of you GPU.
2. Run `python mmdet/utils/collect_env.py` to check whether PyTorch, torchvision,
and MMCV are built for the correct GPU architecture.
You may need to set `TORCH_CUDA_ARCH_LIST` to reinstall MMCV.
The compatibility issue could happen when using old GPUS, e.g., Tesla K80 (3.7) on colab.
3. Check whether the running environment is the same as that when mmcv/mmdet is compiled.
For example, you may compile mmcv using CUDA 10.0 bug run it on CUDA9.0 environments.
- "undefined symbol" or "cannot open xxx.so".
1. If those symbols are CUDA/C++ symbols (e.g., libcudart.so or GLIBCXX), check
whether the CUDA/GCC runtimes are the same as those used for compiling mmcv.
2. If those symbols are Pytorch symbols (e.g., symbols containing caffe, aten, and TH), check whether
the Pytorch version is the same as that used for compiling mmcv.
3. Run `python mmdet/utils/collect_env.py` to check whether PyTorch, torchvision,
and MMCV are built by and running on the same environment.
- "RuntimeError: CUDA error: invalid configuration argument".
This error may be due to your poor GPU. Try to decrease the value of [THREADS_PER_BLOCK](https://github.com/open-mmlab/mmcv/blob/cac22f8cf5a904477e3b5461b1cc36856c2793da/mmcv/ops/csrc/common_cuda_helper.hpp#L10)
and recompile mmcv.
- "RuntimeError: nms is not compiled with GPU support".
This error is because your CUDA environment is not installed correctly.
You may try to re-install your CUDA environment and then delete the build/ folder before re-compile mmcv.
## Build MMCV from source
### Build on Linux or macOS
After cloning the repo with
```bash
git clone https://github.com/open-mmlab/mmcv.git
cd mmcv
```
You can either
- install the lite version
```bash
pip install -e .
```
- install the full version
```bash
MMCV_WITH_OPS=1 pip install -e .
```
If you are on macOS, add the following environment variables before the installing command.
```bash
CC=clang CXX=clang++ CFLAGS='-stdlib=libc++'
```
e.g.,
```bash
CC=clang CXX=clang++ CFLAGS='-stdlib=libc++' MMCV_WITH_OPS=1 pip install -e .
```
```{note}
If you would like to use `opencv-python-headless` instead of `opencv-python`,
e.g., in a minimum container environment or servers without GUI,
you can first install it before installing MMCV to skip the installation of `opencv-python`.
```
### Build on Windows
Building MMCV on Windows is a bit more complicated than that on Linux.
The following instructions show how to get this accomplished.
#### Prerequisite
The following software is required for building MMCV on windows.
Install them first.
- [Git](https://git-scm.com/download/win)
- During installation, tick **add git to Path**.
- [Visual Studio Community 2019](https://visualstudio.microsoft.com)
- A compiler for C++ and CUDA codes.
- [Miniconda](https://docs.conda.io/en/latest/miniconda.html)
- Official distributions of Python should work too.
- [CUDA 10.2](https://developer.nvidia.com/cuda-10.2-download-archive)
- Not required for building CPU version.
- Customize the installation if necessary. As a recommendation, skip the driver installation if a newer version is already installed.
```{note}
You should know how to set up environment variables, especially `Path`, on Windows. The following instruction relies heavily on this skill.
```
#### Setup Python Environment
1. Launch Anaconda prompt from Windows Start menu
Do not use raw `cmd.exe` s instruction is based on PowerShell syntax.
1. Create a new conda environment
```shell
conda create --name mmcv python=3.7 # 3.6, 3.7, 3.8 should work too as tested
conda activate mmcv # make sure to activate environment before any operation
```
1. Install PyTorch. Choose a version based on your need.
```shell
conda install pytorch torchvision cudatoolkit=10.2 -c pytorch
```
We only tested PyTorch version >= 1.6.0.
1. Prepare MMCV source code
```shell
git clone https://github.com/open-mmlab/mmcv.git
cd mmcv
```
1. Install required Python packages
```shell
pip3 install -r requirements.txt
```
#### Build and install MMCV
MMCV can be built in three ways:
1. Lite version (without ops)
In this way, no custom ops are compiled and mmcv is a pure python package.
1. Full version (CPU ops)
Module `ops` will be compiled as a pytorch extension, but only x86 code will be compiled. The compiled ops can be executed on CPU only.
1. Full version (CUDA ops)
Both x86 and CUDA codes of `ops` module will be compiled. The compiled version can be run on both CPU and CUDA-enabled GPU (if implemented).
##### Common steps
1. Set up MSVC compiler
Set Environment variable, add `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\Hostx86\x64` to `PATH`, so that `cl.exe` will be available in prompt, as shown below.
```none
(base) PS C:\Users\xxx> cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29111 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ / link linkoption... ]
```
For compatibility, we use the x86-hosted and x64-targeted compiler. note `Hostx86\x64` in the path.
You may want to change the system language to English because pytorch will parse text output from `cl.exe` to check its version. However only utf-8 is recognized. Navigate to Control Panel -> Region -> Administrative -> Language for Non-Unicode programs and change it to English.
##### Option 1: Build MMCV (lite version)
After finishing above common steps, launch Anaconda shell from Start menu and issue the following commands:
```shell
# activate environment
conda activate mmcv
# change directory
cd mmcv
# install
python setup.py develop
# check
pip list
```
##### Option 2: Build MMCV (full version with CPU)
1. Finish above common steps
1. Set up environment variables
```shell
$env:MMCV_WITH_OPS = 1
$env:MAX_JOBS = 8 # based on your available number of CPU cores and amount of memory
```
1. Following build steps of the lite version
```shell
# activate environment
conda activate mmcv
# change directory
cd mmcv
# build
python setup.py build_ext # if success, cl will be launched to compile ops
# install
python setup.py develop
# check
pip list
```
##### Option 3: Build MMCV (full version with CUDA)
1. Finish above common steps
1. Make sure `CUDA_PATH` or `CUDA_HOME` is already set in `envs` via `ls env:`, desired output is shown as below:
```none
(base) PS C:\Users\WRH> ls env:
Name Value
---- -----
<... omit some lines ...>
CUDA_PATH C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2
CUDA_PATH_V10_1 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1
CUDA_PATH_V10_2 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2
<... omit some lines ...>
```
This should already be done by CUDA installer. If not, or you have multiple version of CUDA toolkit installed, set it with
```shell
$env:CUDA_HOME = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2"
# OR
$env:CUDA_HOME = $env:CUDA_PATH_V10_2 # if CUDA_PATH_V10_2 is in envs:
```
1. Set CUDA target arch
```shell
# Suppose you are using GTX 1080, which is of capability 6.1
$env:TORCH_CUDA_ARCH_LIST="6.1"
# OR build all supported arch, will be slow
$env:TORCH_CUDA_ARCH_LIST="3.5 3.7 5.0 5.2 6.0 6.1 7.0 7.5"
```
```{note}
Check your the compute capability of your GPU from [here](https://developer.nvidia.com/cuda-gpus).
```
1. Launch compiling the same way as CPU
```shell
$env:MMCV_WITH_OPS = 1
$env:MAX_JOBS = 8 # based on available number of CPU cores and amount of memory
# activate environment
conda activate mmcv
# change directory
cd mmcv
# build
python setup.py build_ext # if success, cl will be launched to compile ops
# install
python setup.py develop
# check
pip list
```
```{note}
If you are compiling against PyTorch 1.6.0, you might meet some errors from PyTorch as described in [this issue](https://github.com/pytorch/pytorch/issues/42467). Follow [this pull request](https://github.com/pytorch/pytorch/pull/43380/files) to modify the source code in your local PyTorch installation.
```
If you meet issues when running or compiling mmcv, we list some common issues in [Frequently Asked Question](../faq.html).
## Installation
There are two versions of MMCV:
- **mmcv-full**: comprehensive, with full features and various CUDA ops out of box. It takes longer time to build.
- **mmcv**: lite, without CUDA ops but all other features, similar to mmcv<1.0.0. It is useful when you do not need those CUDA ops.
```{warning}
Do not install both versions in the same environment, otherwise you may encounter errors like `ModuleNotFound`. You need to uninstall one before installing the other. `Installing the full version is highly recommended if CUDA is avaliable`.
```
a. Install the full version.
Before installing mmcv-full, make sure that PyTorch has been successfully installed following the [official guide](https://pytorch.org/).
We provide pre-built mmcv packages (recommended) with different PyTorch and CUDA versions to simplify the building. In addition, you can run [check_installation.py](.dev_scripts/check_installation.py) to check the installation of mmcv-full after running the installation commands.
i. Install the latest version.
The rule for installing the latest ``mmcv-full`` is as follows:
```shell
pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/{cu_version}/{torch_version}/index.html
```
Please replace ``{cu_version}`` and ``{torch_version}`` in the url to your desired one. For example,
to install the latest ``mmcv-full`` with ``CUDA 11.1`` and ``PyTorch 1.9.0``, use the following command:
```shell
pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.9.0/index.html
```
For more details, please refer the the following tables and delete ``=={mmcv_version}``.
ii. Install a specified version.
The rule for installing a specified ``mmcv-full`` is as follows:
```shell
pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/{cu_version}/{torch_version}/index.html
```
First of all, please refer to the Releases and replace ``{mmcv_version}`` a specified one. e.g. ``1.3.9``.
Then replace ``{cu_version}`` and ``{torch_version}`` in the url to your desired versions. For example,
to install ``mmcv-full==1.3.9`` with ``CUDA 11.1`` and ``PyTorch 1.9.0``, use the following command:
```shell
pip install mmcv-full==1.3.9 -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.9.0/index.html
```
```{note}
mmcv-full is only compiled on PyTorch 1.x.0 because the compatibility
usually holds between 1.x.0 and 1.x.1. If your PyTorch version is 1.x.1, you
can install mmcv-full compiled with PyTorch 1.x.0 and it usually works well.
For example, if your PyTorch version is 1.8.1 and CUDA version is 11.1, you
can use the following command to install mmcv-full.
`pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.8.0/index.html`
```
For more details, please refer the the following tables.
<table class="docutils">
<tbody>
<tr>
<th width="80"> CUDA </th>
<th valign="bottom" align="left" style="min-width: 100px">torch 1.10</th>
<th valign="bottom" align="left" style="min-width: 100px">torch 1.9</th>
<th valign="bottom" align="left" style="min-width: 100px">torch 1.8</th>
<th valign="bottom" align="left" style="min-width: 100px">torch 1.7</th>
<th valign="bottom" align="left" style="min-width: 100px">torch 1.6</th>
<th valign="bottom" align="left" style="min-width: 100px">torch 1.5</th>
</tr>
<tr>
<td align="left">11.3</td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html</code></pre> </details> </td>
<td align="left"></td>
<td align="left"></code></pre> </details> </td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"> </td>
</tr>
<tr>
<td align="left">11.1</td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.10.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.9.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.8.0/index.html</code></pre> </details> </td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"> </td>
</tr>
<tr>
<td align="left">11.0</td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu110/torch1.7.0/index.html</code></pre> </details> </td>
<td align="left"> </td>
<td align="left"> </td>
</tr>
<tr>
<td align="left">10.2</td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.10.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.9.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.8.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.7.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.6.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code>pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.5.0/index.html</code></pre> </details> </td>
</tr>
<tr>
<td align="left">10.1</td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu101/torch1.8.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu101/torch1.7.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu101/torch1.6.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu101/torch1.5.0/index.html</code></pre> </details> </td>
</tr>
<tr>
<td align="left">9.2</td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu92/torch1.7.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu92/torch1.6.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cu92/torch1.5.0/index.html</code></pre> </details> </td>
</tr>
<tr>
<td align="left">cpu</td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.10.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.9.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.8.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.7.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.6.0/index.html</code></pre> </details> </td>
<td align="left"><details><summary> install </summary><pre><code> pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dist/cpu/torch1.5.0/index.html</code></pre> </details> </td>
</tr>
</tbody>
</table>
```{note}
The pre-built packages provided above do not include all versions of mmcv-full, you can click on the corresponding links to see the supported versions. For example, if you click [cu102-torch1.8.0](https://download.openmmlab.com/mmcv/dist/cu102/torch1.8.0/index.html), you can see that `cu102-torch1.8.0` only provides 1.3.0 and above versions of mmcv-full. In addition, We no longer provide `mmcv-full` pre-built packages compiled with `PyTorch 1.3 & 1.4` since v1.3.17. You can find previous versions that compiled with PyTorch 1.3 & 1.4 [here](./docs/get_started/previous_versions.md). The compatibility is still ensured in our CI, but we will discard the support of PyTorch 1.3 & 1.4 next year.
```
Another way is to compile locally by running
```python
pip install mmcv-full
```
Note that the local compiling may take up to 10 mins.
b. Install the lite version.
```python
pip install mmcv
```
c. Install full version with custom operators for onnxruntime
- Check [here](https://mmcv.readthedocs.io/en/latest/deployment/onnxruntime_custom_ops.html) for detailed instruction.
If you would like to build MMCV from source, please refer to the [guide](https://mmcv.readthedocs.io/en/latest/get_started/build.html).
## Introduction ## Introduction
MMCV is a foundational library for computer vision research and provides the following functionalities. MMCV is a foundational library for computer vision research and supports many
research projects as below:
- [Image/Video processing](../understand_mmcv/data_process.md)
- [Image and annotation visualization](../understand_mmcv/visualization.md)
- [Image transformation](../understand_mmcv/data_transform.md)
- [Various CNN architectures](../understand_mmcv/cnn.md)
- [High-quality implementation of common CUDA ops](../understand_mmcv/ops.md)
It supports the following systems:
- Linux
- Windows
- macOS
It supports many research projects as below:
- [MMClassification](https://github.com/open-mmlab/mmclassification): OpenMMLab image classification toolbox and benchmark. - [MMClassification](https://github.com/open-mmlab/mmclassification): OpenMMLab image classification toolbox and benchmark.
- [MMDetection](https://github.com/open-mmlab/mmdetection): OpenMMLab detection toolbox and benchmark. - [MMDetection](https://github.com/open-mmlab/mmdetection): OpenMMLab detection toolbox and benchmark.
- [MMDetection3D](https://github.com/open-mmlab/mmdetection3d): OpenMMLab's next-generation platform for general 3D object detection. - [MMDetection3D](https://github.com/open-mmlab/mmdetection3d): OpenMMLab's next-generation platform for general 3D object detection.
- [MMRotate](https://github.com/open-mmlab/mmrotate): OpenMMLab rotated object detection toolbox and benchmark.
- [MMYOLO](https://github.com/open-mmlab/mmyolo): OpenMMLab YOLO series toolbox and benchmark.
- [MMSegmentation](https://github.com/open-mmlab/mmsegmentation): OpenMMLab semantic segmentation toolbox and benchmark. - [MMSegmentation](https://github.com/open-mmlab/mmsegmentation): OpenMMLab semantic segmentation toolbox and benchmark.
- [MMOCR](https://github.com/open-mmlab/mmocr): OpenMMLab text detection, recognition, and understanding toolbox.
- [MMPose](https://github.com/open-mmlab/mmpose): OpenMMLab pose estimation toolbox and benchmark.
- [MMHuman3D](https://github.com/open-mmlab/mmhuman3d): OpenMMLab 3D human parametric model toolbox and benchmark.
- [MMSelfSup](https://github.com/open-mmlab/mmselfsup): OpenMMLab self-supervised learning toolbox and benchmark.
- [MMRazor](https://github.com/open-mmlab/mmrazor): OpenMMLab model compression toolbox and benchmark.
- [MMFewShot](https://github.com/open-mmlab/mmfewshot): OpenMMLab fewshot learning toolbox and benchmark.
- [MMAction2](https://github.com/open-mmlab/mmaction2): OpenMMLab's next-generation action understanding toolbox and benchmark. - [MMAction2](https://github.com/open-mmlab/mmaction2): OpenMMLab's next-generation action understanding toolbox and benchmark.
- [MMTracking](https://github.com/open-mmlab/mmtracking): OpenMMLab video perception toolbox and benchmark. - [MMTracking](https://github.com/open-mmlab/mmtracking): OpenMMLab video perception toolbox and benchmark.
- [MMFlow](https://github.com/open-mmlab/mmflow): OpenMMLab optical flow toolbox and benchmark. - [MMPose](https://github.com/open-mmlab/mmpose): OpenMMLab pose estimation toolbox and benchmark.
- [MMEditing](https://github.com/open-mmlab/mmediting): OpenMMLab image and video editing toolbox. - [MMEditing](https://github.com/open-mmlab/mmediting): OpenMMLab image and video editing toolbox.
- [MMOCR](https://github.com/open-mmlab/mmocr): OpenMMLab text detection, recognition and understanding toolbox.
- [MMGeneration](https://github.com/open-mmlab/mmgeneration): OpenMMLab image and video generative models toolbox. - [MMGeneration](https://github.com/open-mmlab/mmgeneration): OpenMMLab image and video generative models toolbox.
- [MMDeploy](https://github.com/open-mmlab/mmdeploy): OpenMMLab model deployment framework.
It provides the following functionalities.
- Universal IO APIs
- Image/Video processing
- Image and annotation visualization
- Useful utilities (progress bar, timer, ...)
- PyTorch runner with hooking mechanism
- Various CNN architectures
- High-quality implementation of common CUDA ops
```{note}
MMCV requires Python 3.6+.
```
...@@ -4,7 +4,7 @@ We no longer provide `mmcv-full` packages compiled under lower versions of `PyTo ...@@ -4,7 +4,7 @@ We no longer provide `mmcv-full` packages compiled under lower versions of `PyTo
### PyTorch 1.4 ### PyTorch 1.4
| 1.0.0 \<= mmcv_version \<= 1.2.1 | 1.0.0 <= mmcv_version <= 1.2.1
#### CUDA 10.1 #### CUDA 10.1
...@@ -26,7 +26,7 @@ pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dis ...@@ -26,7 +26,7 @@ pip install mmcv-full=={mmcv_version} -f https://download.openmmlab.com/mmcv/dis
### PyTorch v1.3 ### PyTorch v1.3
| 1.0.0 \<= mmcv_version \<= 1.3.16 | 1.0.0 <= mmcv_version <= 1.3.16
#### CUDA 10.1 #### CUDA 10.1
......
...@@ -15,23 +15,27 @@ You can switch between Chinese and English documents in the lower-left corner of ...@@ -15,23 +15,27 @@ You can switch between Chinese and English documents in the lower-left corner of
:maxdepth: 2 :maxdepth: 2
:caption: Understand MMCV :caption: Understand MMCV
understand_mmcv/config.md
understand_mmcv/registry.md
understand_mmcv/runner.md
understand_mmcv/io.md
understand_mmcv/data_process.md understand_mmcv/data_process.md
understand_mmcv/data_transform.md
understand_mmcv/visualization.md understand_mmcv/visualization.md
understand_mmcv/cnn.md understand_mmcv/cnn.md
understand_mmcv/ops.md understand_mmcv/ops.md
understand_mmcv/utils.md
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Deployment :caption: Deployment
deployment/onnx.md
deployment/onnxruntime_op.md
deployment/onnxruntime_custom_ops.md
deployment/tensorrt_plugin.md
deployment/tensorrt_custom_ops.md
deployment/mmcv_ops_definition.md deployment/mmcv_ops_definition.md
.. toctree::
:caption: Switch Language
switch_language.md
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
:caption: Compatibility :caption: Compatibility
...@@ -39,6 +43,8 @@ You can switch between Chinese and English documents in the lower-left corner of ...@@ -39,6 +43,8 @@ You can switch between Chinese and English documents in the lower-left corner of
compatibility.md compatibility.md
.. toctree:: .. toctree::
:maxdepth: 2
:caption: FAQ
faq.md faq.md
...@@ -50,17 +56,10 @@ You can switch between Chinese and English documents in the lower-left corner of ...@@ -50,17 +56,10 @@ You can switch between Chinese and English documents in the lower-left corner of
community/pr.md community/pr.md
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 2
:caption: API Reference :caption: API Reference
mmcv.image <api/image> api.rst
mmcv.video <api/video>
mmcv.visualization <api/visualization>
mmcv.cnn <api/cnn>
mmcv.ops <api/ops>
mmcv.transforms <api/transforms>
mmcv.arraymisc <api/arraymisc>
mmcv.utils <api/utils>
Indices and tables Indices and tables
================== ==================
......
## CNN
We provide some building bricks for CNNs, including layer building, module bundles and weight initialization.
### Layer building
We may need to try different layers of the same type when running experiments,
but do not want to modify the code from time to time.
Here we provide some layer building methods to construct layers from a dict,
which can be written in configs or specified via command line arguments.
#### Usage
A simplest example is
```python
cfg = dict(type='Conv3d')
layer = build_conv_layer(cfg, in_channels=3, out_channels=8, kernel_size=3)
```
- `build_conv_layer`: Supported types are Conv1d, Conv2d, Conv3d, Conv (alias for Conv2d).
- `build_norm_layer`: Supported types are BN1d, BN2d, BN3d, BN (alias for BN2d), SyncBN, GN, LN, IN1d, IN2d, IN3d, IN (alias for IN2d).
- `build_activation_layer`: Supported types are ReLU, LeakyReLU, PReLU, RReLU, ReLU6, ELU, Sigmoid, Tanh, GELU.
- `build_upsample_layer`: Supported types are nearest, bilinear, deconv, pixel_shuffle.
- `build_padding_layer`: Supported types are zero, reflect, replicate.
#### Extension
We also allow extending the building methods with custom layers and operators.
1. Write and register your own module.
```python
from mmcv.cnn import UPSAMPLE_LAYERS
@UPSAMPLE_LAYERS.register_module()
class MyUpsample:
def __init__(self, scale_factor):
pass
def forward(self, x):
pass
```
2. Import `MyUpsample` somewhere (e.g., in `__init__.py`) and then use it.
```python
cfg = dict(type='MyUpsample', scale_factor=2)
layer = build_upsample_layer(cfg)
```
### Module bundles
We also provide common module bundles to facilitate the network construction.
`ConvModule` is a bundle of convolution, normalization and activation layers,
please refer to the [api](api.html#mmcv.cnn.ConvModule) for details.
```python
# conv + bn + relu
conv = ConvModule(3, 8, 2, norm_cfg=dict(type='BN'))
# conv + gn + relu
conv = ConvModule(3, 8, 2, norm_cfg=dict(type='GN', num_groups=2))
# conv + relu
conv = ConvModule(3, 8, 2)
# conv
conv = ConvModule(3, 8, 2, act_cfg=None)
# conv + leaky relu
conv = ConvModule(3, 8, 3, padding=1, act_cfg=dict(type='LeakyReLU'))
# bn + conv + relu
conv = ConvModule(
3, 8, 2, norm_cfg=dict(type='BN'), order=('norm', 'conv', 'act'))
```
### Weight initialization
> Implementation details are available at [mmcv/cnn/utils/weight_init.py](../../mmcv/cnn/utils/weight_init.py)
During training, a proper initialization strategy is beneficial to speed up the
training or obtain a higher performance. In MMCV, we provide some commonly used
methods for initializing modules like `nn.Conv2d`. Of course, we also provide
high-level APIs for initializing models containing one or more
modules.
#### Initialization functions
Initialize a `nn.Module` such as `nn.Conv2d`, `nn.Linear` in a functional way.
We provide the following initialization methods.
- constant_init
Initialize module parameters with constant values.
```python
>>> import torch.nn as nn
>>> from mmcv.cnn import constant_init
>>> conv1 = nn.Conv2d(3, 3, 1)
>>> # constant_init(module, val, bias=0)
>>> constant_init(conv1, 1, 0)
>>> conv1.weight
```
- xavier_init
Initialize module parameters with values according to the method
described in [Understanding the difficulty of training deep feedforward neural networks - Glorot, X. & Bengio, Y. (2010)](http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf)
```python
>>> import torch.nn as nn
>>> from mmcv.cnn import xavier_init
>>> conv1 = nn.Conv2d(3, 3, 1)
>>> # xavier_init(module, gain=1, bias=0, distribution='normal')
>>> xavier_init(conv1, distribution='normal')
```
- normal_init
Initialize module parameters with the values drawn from a normal distribution.
```python
>>> import torch.nn as nn
>>> from mmcv.cnn import normal_init
>>> conv1 = nn.Conv2d(3, 3, 1)
>>> # normal_init(module, mean=0, std=1, bias=0)
>>> normal_init(conv1, std=0.01, bias=0)
```
- uniform_init
Initialize module parameters with values drawn from a uniform distribution.
```python
>>> import torch.nn as nn
>>> from mmcv.cnn import uniform_init
>>> conv1 = nn.Conv2d(3, 3, 1)
>>> # uniform_init(module, a=0, b=1, bias=0)
>>> uniform_init(conv1, a=0, b=1)
```
- kaiming_init
Initialize module parameters with the values according to the method
described in [Delving deep into rectifiers: Surpassing human-level
performance on ImageNet classification - He, K. et al. (2015)](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)
```python
>>> import torch.nn as nn
>>> from mmcv.cnn import kaiming_init
>>> conv1 = nn.Conv2d(3, 3, 1)
>>> # kaiming_init(module, a=0, mode='fan_out', nonlinearity='relu', bias=0, distribution='normal')
>>> kaiming_init(conv1)
```
- caffe2_xavier_init
The xavier initialization is implemented in caffe2, which corresponds to `kaiming_uniform_` in PyTorch.
```python
>>> import torch.nn as nn
>>> from mmcv.cnn import caffe2_xavier_init
>>> conv1 = nn.Conv2d(3, 3, 1)
>>> # caffe2_xavier_init(module, bias=0)
>>> caffe2_xavier_init(conv1)
```
- bias_init_with_prob
Initialize conv/fc bias value according to a given probability, as proposed in [Focal Loss for Dense Object Detection](https://arxiv.org/pdf/1708.02002.pdf).
```python
>>> from mmcv.cnn import bias_init_with_prob
>>> # bias_init_with_prob is proposed in Focal Loss
>>> bias = bias_init_with_prob(0.01)
>>> bias
-4.59511985013459
```
#### Initializers and configs
On the basis of the initialization methods, we define the corresponding initialization classes and register them to `INITIALIZERS`, so we can
use the configuration to initialize the model.
We provide the following initialization classes.
- ConstantInit
- XavierInit
- NormalInit
- UniformInit
- KaimingInit
- Caffe2XavierInit
- PretrainedInit
Let us introduce the usage of `initialize` in detail.
1. Initialize model by `layer` key
If we only define `layer`, it just initialize the layer in `layer` key.
NOTE: Value of `layer` key is the class name with attributes weights and bias of Pytorch, so `MultiheadAttention layer` is not supported.
- Define `layer` key for initializing module with same configuration.
```python
import torch.nn as nn
from mmcv.cnn import initialize
class FooNet(nn.Module):
def __init__(self):
super().__init__()
self.feat = nn.Conv1d(3, 1, 3)
self.reg = nn.Conv2d(3, 3, 3)
self.cls = nn.Linear(1, 2)
model = FooNet()
init_cfg = dict(type='Constant', layer=['Conv1d', 'Conv2d', 'Linear'], val=1)
# initialize whole module with same configuration
initialize(model, init_cfg)
# model.feat.weight
# Parameter containing:
# tensor([[[1., 1., 1.],
# [1., 1., 1.],
# [1., 1., 1.]]], requires_grad=True)
```
- Define `layer` key for initializing layer with different configurations.
```python
import torch.nn as nn
from mmcv.cnn.utils import initialize
class FooNet(nn.Module):
def __init__(self):
super().__init__()
self.feat = nn.Conv1d(3, 1, 3)
self.reg = nn.Conv2d(3, 3, 3)
self.cls = nn.Linear(1,2)
model = FooNet()
init_cfg = [dict(type='Constant', layer='Conv1d', val=1),
dict(type='Constant', layer='Conv2d', val=2),
dict(type='Constant', layer='Linear', val=3)]
# nn.Conv1d will be initialized with dict(type='Constant', val=1)
# nn.Conv2d will be initialized with dict(type='Constant', val=2)
# nn.Linear will be initialized with dict(type='Constant', val=3)
initialize(model, init_cfg)
# model.reg.weight
# Parameter containing:
# tensor([[[[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]],
# ...,
# [[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]]]], requires_grad=True)
```
2. Initialize model by `override` key
- When initializing some specific part with its attribute name, we can use `override` key, and the value in `override` will ignore the value in init_cfg.
```python
import torch.nn as nn
from mmcv.cnn import initialize
class FooNet(nn.Module):
def __init__(self):
super().__init__()
self.feat = nn.Conv1d(3, 1, 3)
self.reg = nn.Conv2d(3, 3, 3)
self.cls = nn.Sequential(nn.Conv1d(3, 1, 3), nn.Linear(1,2))
# if we would like to initialize model's weights as 1 and bias as 2
# but weight in `cls` as 3 and bias 4, we can use override key
model = FooNet()
init_cfg = dict(type='Constant', layer=['Conv1d','Conv2d'], val=1, bias=2,
override=dict(type='Constant', name='reg', val=3, bias=4))
# self.feat and self.cls will be initialized with dict(type='Constant', val=1, bias=2)
# The module called 'reg' will be initialized with dict(type='Constant', val=3, bias=4)
initialize(model, init_cfg)
# model.reg.weight
# Parameter containing:
# tensor([[[[3., 3., 3.],
# [3., 3., 3.],
# [3., 3., 3.]],
# ...,
# [[3., 3., 3.],
# [3., 3., 3.],
# [3., 3., 3.]]]], requires_grad=True)
```
- If `layer` is None in init_cfg, only sub-module with the name in override will be initialized, and type and other args in override can be omitted.
```python
model = FooNet()
init_cfg = dict(type='Constant', val=1, bias=2, override=dict(name='reg'))
# self.feat and self.cls will be initialized by Pytorch
# The module called 'reg' will be initialized with dict(type='Constant', val=1, bias=2)
initialize(model, init_cfg)
# model.reg.weight
# Parameter containing:
# tensor([[[[1., 1., 1.],
# [1., 1., 1.],
# [1., 1., 1.]],
# ...,
# [[1., 1., 1.],
# [1., 1., 1.],
# [1., 1., 1.]]]], requires_grad=True)
```
- If we don't define `layer` key or `override` key, it will not initialize anything.
- Invalid usage
```python
# It is invalid that override don't have name key
init_cfg = dict(type='Constant', layer=['Conv1d','Conv2d'],
val=1, bias=2,
override=dict(type='Constant', val=3, bias=4))
# It is also invalid that override has name and other args except type
init_cfg = dict(type='Constant', layer=['Conv1d','Conv2d'],
val=1, bias=2,
override=dict(name='reg', val=3, bias=4))
```
3. Initialize model with the pretrained model
```python
import torch.nn as nn
import torchvision.models as models
from mmcv.cnn import initialize
# initialize model with pretrained model
model = models.resnet50()
# model.conv1.weight
# Parameter containing:
# tensor([[[[-6.7435e-03, -2.3531e-02, -9.0143e-03, ..., -2.1245e-03,
# -1.8077e-03, 3.0338e-03],
# [-1.2603e-02, -2.7831e-02, 2.3187e-02, ..., -1.5793e-02,
# 1.1655e-02, 4.5889e-03],
# [-3.7916e-02, 1.2014e-02, 1.3815e-02, ..., -4.2651e-03,
# 1.7314e-02, -9.9998e-03],
# ...,
init_cfg = dict(type='Pretrained',
checkpoint='torchvision://resnet50')
initialize(model, init_cfg)
# model.conv1.weight
# Parameter containing:
# tensor([[[[ 1.3335e-02, 1.4664e-02, -1.5351e-02, ..., -4.0896e-02,
# -4.3034e-02, -7.0755e-02],
# [ 4.1205e-03, 5.8477e-03, 1.4948e-02, ..., 2.2060e-03,
# -2.0912e-02, -3.8517e-02],
# [ 2.2331e-02, 2.3595e-02, 1.6120e-02, ..., 1.0281e-01,
# 6.2641e-02, 5.1977e-02],
# ...,
# initialize weights of a sub-module with the specific part of a pretrained model by using 'prefix'
model = models.resnet50()
url = 'http://download.openmmlab.com/mmdetection/v2.0/retinanet/'\
'retinanet_r50_fpn_1x_coco/'\
'retinanet_r50_fpn_1x_coco_20200130-c2398f9e.pth'
init_cfg = dict(type='Pretrained',
checkpoint=url, prefix='backbone.')
initialize(model, init_cfg)
```
4. Initialize model inherited from BaseModule, Sequential, ModuleList
`BaseModule` is inherited from `torch.nn.Module`, and the only different between them is that `BaseModule` implements `init_weight`.
`Sequential` is inherited from `BaseModule` and `torch.nn.Sequential`.
`ModuleList` is inherited from `BaseModule` and `torch.nn.ModuleList`.
`````python
import torch.nn as nn
from mmcv.runner import BaseModule, Sequential, ModuleList
class FooConv1d(BaseModule):
def __init__(self, init_cfg=None):
super().__init__(init_cfg)
self.conv1d = nn.Conv1d(4, 1, 4)
def forward(self, x):
return self.conv1d(x)
class FooConv2d(BaseModule):
def __init__(self, init_cfg=None):
super().__init__(init_cfg)
self.conv2d = nn.Conv2d(3, 1, 3)
def forward(self, x):
return self.conv2d(x)
# BaseModule
init_cfg = dict(type='Constant', layer='Conv1d', val=0., bias=1.)
model = FooConv1d(init_cfg)
model.init_weights()
# model.conv1d.weight
# Parameter containing:
# tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]], requires_grad=True)
# Sequential
init_cfg1 = dict(type='Constant', layer='Conv1d', val=0., bias=1.)
init_cfg2 = dict(type='Constant', layer='Conv2d', val=2., bias=3.)
model1 = FooConv1d(init_cfg1)
model2 = FooConv2d(init_cfg2)
seq_model = Sequential(model1, model2)
seq_model.init_weights()
# seq_model[0].conv1d.weight
# Parameter containing:
# tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]], requires_grad=True)
# seq_model[1].conv2d.weight
# Parameter containing:
# tensor([[[[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]],
# ...,
# [[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]]]], requires_grad=True)
# inner init_cfg has higher priority
model1 = FooConv1d(init_cfg1)
model2 = FooConv2d(init_cfg2)
init_cfg = dict(type='Constant', layer=['Conv1d', 'Conv2d'], val=4., bias=5.)
seq_model = Sequential(model1, model2, init_cfg=init_cfg)
seq_model.init_weights()
# seq_model[0].conv1d.weight
# Parameter containing:
# tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]], requires_grad=True)
# seq_model[1].conv2d.weight
# Parameter containing:
# tensor([[[[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]],
# ...,
# [[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]]]], requires_grad=True)
# ModuleList
model1 = FooConv1d(init_cfg1)
model2 = FooConv2d(init_cfg2)
modellist = ModuleList([model1, model2])
modellist.init_weights()
# modellist[0].conv1d.weight
# Parameter containing:
# tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]], requires_grad=True)
# modellist[1].conv2d.weight
# Parameter containing:
# tensor([[[[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]],
# ...,
# [[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]]]], requires_grad=True)
# inner init_cfg has higher priority
model1 = FooConv1d(init_cfg1)
model2 = FooConv2d(init_cfg2)
init_cfg = dict(type='Constant', layer=['Conv1d', 'Conv2d'], val=4., bias=5.)
modellist = ModuleList([model1, model2], init_cfg=init_cfg)
modellist.init_weights()
# modellist[0].conv1d.weight
# Parameter containing:
# tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]], requires_grad=True)
# modellist[1].conv2d.weight
# Parameter containing:
# tensor([[[[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]],
# ...,
# [[2., 2., 2.],
# [2., 2., 2.],
# [2., 2., 2.]]]], requires_grad=True)
`````
### Model Zoo
Besides torchvision pre-trained models, we also provide pre-trained models of following CNN:
- VGG Caffe
- ResNet Caffe
- ResNeXt
- ResNet with Group Normalization
- ResNet with Group Normalization and Weight Standardization
- HRNetV2
- Res2Net
- RegNet
#### Model URLs in JSON
The model zoo links in MMCV are managed by JSON files.
The json file consists of key-value pair of model name and its url or path.
An example json file could be like:
```json
{
"model_a": "https://example.com/models/model_a_9e5bac.pth",
"model_b": "pretrain/model_b_ab3ef2c.pth"
}
```
The default links of the pre-trained models hosted on OpenMMLab AWS could be found [here](https://github.com/open-mmlab/mmcv/blob/master/mmcv/model_zoo/open_mmlab.json).
You may override default links by putting `open-mmlab.json` under `MMCV_HOME`. If `MMCV_HOME` is not find in the environment, `~/.cache/mmcv` will be used by default. You may `export MMCV_HOME=/your/path` to use your own path.
The external json files will be merged into default one. If the same key presents in both external json and default json, the external one will be used.
#### Load Checkpoint
The following types are supported for `filename` argument of `mmcv.load_checkpoint()`.
- filepath: The filepath of the checkpoint.
- `http://xxx` and `https://xxx`: The link to download the checkpoint. The `SHA256` postfix should be contained in the filename.
- `torchvision://xxx`: The model links in `torchvision.models`.Please refer to [torchvision](https://pytorch.org/docs/stable/torchvision/models.html) for details.
- `open-mmlab://xxx`: The model links or filepath provided in default and additional json files.
## Config
`Config` class is used for manipulating config and config files. It supports
loading configs from multiple file formats including **python**, **json** and **yaml**.
It provides dict-like apis to get and set values.
Here is an example of the config file `test.py`.
```python
a = 1
b = dict(b1=[0, 1, 2], b2=None)
c = (1, 2)
d = 'string'
```
To load and use configs
```python
>>> cfg = Config.fromfile('test.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=None),
... c=(1, 2),
... d='string')
```
For all format configs, some predefined variables are supported. It will convert the variable in `{{ var }}` with its real value.
Currently, it supports four predefined variables:
`{{ fileDirname }}` - the current opened file's dirname, e.g. /home/your-username/your-project/folder
`{{ fileBasename }}` - the current opened file's basename, e.g. file.ext
`{{ fileBasenameNoExtension }}` - the current opened file's basename with no file extension, e.g. file
`{{ fileExtname }}` - the current opened file's extension, e.g. .ext
These variable names are referred from [VS Code](https://code.visualstudio.com/docs/editor/variables-reference).
Here is one examples of config with predefined variables.
`config_a.py`
```python
a = 1
b = './work_dir/{{ fileBasenameNoExtension }}'
c = '{{ fileExtname }}'
```
```python
>>> cfg = Config.fromfile('./config_a.py')
>>> print(cfg)
>>> dict(a=1,
... b='./work_dir/config_a',
... c='.py')
```
For all format configs, inheritance is supported. To reuse fields in other config files,
specify `_base_='./config_a.py'` or a list of configs `_base_=['./config_a.py', './config_b.py']`.
Here are 4 examples of config inheritance.
`config_a.py`
```python
a = 1
b = dict(b1=[0, 1, 2], b2=None)
```
### Inherit from base config without overlapped keys
`config_b.py`
```python
_base_ = './config_a.py'
c = (1, 2)
d = 'string'
```
```python
>>> cfg = Config.fromfile('./config_b.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=None),
... c=(1, 2),
... d='string')
```
New fields in `config_b.py` are combined with old fields in `config_a.py`
### Inherit from base config with overlapped keys
`config_c.py`
```python
_base_ = './config_a.py'
b = dict(b2=1)
c = (1, 2)
```
```python
>>> cfg = Config.fromfile('./config_c.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=1),
... c=(1, 2))
```
`b.b2=None` in `config_a` is replaced with `b.b2=1` in `config_c.py`.
### Inherit from base config with ignored fields
`config_d.py`
```python
_base_ = './config_a.py'
b = dict(_delete_=True, b2=None, b3=0.1)
c = (1, 2)
```
```python
>>> cfg = Config.fromfile('./config_d.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b2=None, b3=0.1),
... c=(1, 2))
```
You may also set `_delete_=True` to ignore some fields in base configs. All old keys `b1, b2, b3` in `b` are replaced with new keys `b2, b3`.
### Inherit from multiple base configs (the base configs should not contain the same keys)
`config_e.py`
```python
c = (1, 2)
d = 'string'
```
`config_f.py`
```python
_base_ = ['./config_a.py', './config_e.py']
```
```python
>>> cfg = Config.fromfile('./config_f.py')
>>> print(cfg)
>>> dict(a=1,
... b=dict(b1=[0, 1, 2], b2=None),
... c=(1, 2),
... d='string')
```
### Reference variables from base
You can reference variables defined in base using the following grammar.
`base.py`
```python
item1 = 'a'
item2 = dict(item3 = 'b')
```
`config_g.py`
```python
_base_ = ['./base.py']
item = dict(a = {{ _base_.item1 }}, b = {{ _base_.item2.item3 }})
```
```python
>>> cfg = Config.fromfile('./config_g.py')
>>> print(cfg.pretty_text)
item1 = 'a'
item2 = dict(item3='b')
item = dict(a='a', b='b')
```
### Add deprecation information in configs
Deprecation information can be added in a config file, which will trigger a `UserWarning` when this config file is loaded.
`deprecated_cfg.py`
```python
_base_ = 'expected_cfg.py'
_deprecation_ = dict(
expected = 'expected_cfg.py', # optional to show expected config path in the warning information
reference = 'url to related PR' # optional to show reference link in the warning information
)
```
```python
>>> cfg = Config.fromfile('./deprecated_cfg.py')
UserWarning: The config file deprecated.py will be deprecated in the future. Please use expected_cfg.py instead. More information can be found at https://github.com/open-mmlab/mmcv/pull/1275
```
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
### Image ### Image
This module provides some image processing methods, which requires `opencv` to be installed first. This module provides some image processing methods, which requires `opencv` to be installed.
#### Read/Write/Show #### Read/Write/Show
...@@ -118,7 +118,7 @@ mmcv.imflip(img, direction='vertical') ...@@ -118,7 +118,7 @@ mmcv.imflip(img, direction='vertical')
#### Crop #### Crop
`imcrop` can crop the image with one or more regions. Each region is represented by the upper left and lower right coordinates as (x1, y1, x2, y2). `imcrop` can crop the image with one or some regions, represented as (x1, y1, x2, y2).
```python ```python
import mmcv import mmcv
...@@ -135,12 +135,12 @@ bboxes = np.array([[10, 10, 100, 120], [0, 0, 50, 50]]) ...@@ -135,12 +135,12 @@ bboxes = np.array([[10, 10, 100, 120], [0, 0, 50, 50]])
patches = mmcv.imcrop(img, bboxes) patches = mmcv.imcrop(img, bboxes)
# crop two regions, and rescale the patches by 1.2x # crop two regions, and rescale the patches by 1.2x
patches = mmcv.imcrop(img, bboxes, scale=1.2) patches = mmcv.imcrop(img, bboxes, scale_ratio=1.2)
``` ```
#### Padding #### Padding
There are two methods, `impad` and `impad_to_multiple`, to pad an image to the There are two methods `impad` and `impad_to_multiple` to pad an image to the
specific size with given values. specific size with given values.
```python ```python
...@@ -150,14 +150,14 @@ img = mmcv.imread('tests/data/color.jpg') ...@@ -150,14 +150,14 @@ img = mmcv.imread('tests/data/color.jpg')
img_ = mmcv.impad(img, shape=(1000, 1200), pad_val=0) img_ = mmcv.impad(img, shape=(1000, 1200), pad_val=0)
# pad the image to (1000, 1200) with different values for three channels. # pad the image to (1000, 1200) with different values for three channels.
img_ = mmcv.impad(img, shape=(1000, 1200), pad_val=(100, 50, 200)) img_ = mmcv.impad(img, shape=(1000, 1200), pad_val=[100, 50, 200])
# pad the image on left, right, top, bottom borders with all zeros # pad the image on left, right, top, bottom borders with all zeros
img_ = mmcv.impad(img, padding=(10, 20, 30, 40), pad_val=0) img_ = mmcv.impad(img, padding=(10, 20, 30, 40), pad_val=0)
# pad the image on left, right, top, bottom borders with different values # pad the image on left, right, top, bottom borders with different values
# for three channels. # for three channels.
img_ = mmcv.impad(img, padding=(10, 20, 30, 40), pad_val=(100, 50, 200)) img_ = mmcv.impad(img, padding=(10, 20, 30, 40), pad_val=[100, 50, 200])
# pad an image so that each edge is a multiple of some value. # pad an image so that each edge is a multiple of some value.
img_ = mmcv.impad_to_multiple(img, 32) img_ = mmcv.impad_to_multiple(img, 32)
...@@ -165,7 +165,7 @@ img_ = mmcv.impad_to_multiple(img, 32) ...@@ -165,7 +165,7 @@ img_ = mmcv.impad_to_multiple(img, 32)
### Video ### Video
This module provides the following functionalities: This module provides the following functionalities.
- A `VideoReader` class with friendly apis to read and convert videos. - A `VideoReader` class with friendly apis to read and convert videos.
- Some methods for editing (cut, concat, resize) videos. - Some methods for editing (cut, concat, resize) videos.
...@@ -232,7 +232,7 @@ mmcv.resize_video('test.mp4', 'resized2.mp4', ratio=2) ...@@ -232,7 +232,7 @@ mmcv.resize_video('test.mp4', 'resized2.mp4', ratio=2)
- IO - IO
- Visualization - Visualization
- Flow warping - Flow warpping
We provide two options to dump optical flow files: uncompressed and compressed. We provide two options to dump optical flow files: uncompressed and compressed.
The uncompressed way just dumps the floating numbers to a binary file. It is The uncompressed way just dumps the floating numbers to a binary file. It is
...@@ -265,12 +265,12 @@ mmcv.flowshow(flow) ...@@ -265,12 +265,12 @@ mmcv.flowshow(flow)
![progress](../_static/flow_visualization.png) ![progress](../_static/flow_visualization.png)
3. Flow warping 3. Flow warpping
```python ```python
img1 = mmcv.imread('img1.jpg') img1 = mmcv.imread('img1.jpg')
flow = mmcv.flowread('flow.flo') flow = mmcv.flowread('flow.flo')
warped_img2 = mmcv.flow_warp(img1, flow) warpped_img2 = mmcv.flow_warp(img1, flow)
``` ```
img1 (left) and img2 (right) img1 (left) and img2 (right)
...@@ -281,6 +281,6 @@ optical flow (img2 -> img1) ...@@ -281,6 +281,6 @@ optical flow (img2 -> img1)
![optical flow](../_static/flow_img2toimg1.png) ![optical flow](../_static/flow_img2toimg1.png)
warped image and difference with ground truth warpped image and difference with ground truth
![warped image](../_static/flow_warp_diff.png) ![warpped image](../_static/flow_warp_diff.png)
## File IO
This module provides two universal API to load and dump files of different formats.
```{note}
Since v1.3.16, the IO modules support loading (dumping) data from (to) different backends, respectively. More details are in PR [#1330](https://github.com/open-mmlab/mmcv/pull/1330).
```
### Load and dump data
`mmcv` provides a universal api for loading and dumping data, currently
supported formats are json, yaml and pickle.
#### Load from disk or dump to disk
```python
import mmcv
# load data from a file
data = mmcv.load('test.json')
data = mmcv.load('test.yaml')
data = mmcv.load('test.pkl')
# load data from a file-like object
with open('test.json', 'r') as f:
data = mmcv.load(f, file_format='json')
# dump data to a string
json_str = mmcv.dump(data, file_format='json')
# dump data to a file with a filename (infer format from file extension)
mmcv.dump(data, 'out.pkl')
# dump data to a file with a file-like object
with open('test.yaml', 'w') as f:
data = mmcv.dump(data, f, file_format='yaml')
```
#### Load from other backends or dump to other backends
```python
import mmcv
# load data from a file
data = mmcv.load('s3://bucket-name/test.json')
data = mmcv.load('s3://bucket-name/test.yaml')
data = mmcv.load('s3://bucket-name/test.pkl')
# dump data to a file with a filename (infer format from file extension)
mmcv.dump(data, 's3://bucket-name/out.pkl')
```
It is also very convenient to extend the api to support more file formats.
All you need to do is to write a file handler inherited from `BaseFileHandler`
and register it with one or several file formats.
You need to implement at least 3 methods.
```python
import mmcv
# To register multiple file formats, a list can be used as the argument.
# @mmcv.register_handler(['txt', 'log'])
@mmcv.register_handler('txt')
class TxtHandler1(mmcv.BaseFileHandler):
def load_from_fileobj(self, file):
return file.read()
def dump_to_fileobj(self, obj, file):
file.write(str(obj))
def dump_to_str(self, obj, **kwargs):
return str(obj)
```
Here is an example of `PickleHandler`.
```python
import pickle
class PickleHandler(mmcv.BaseFileHandler):
def load_from_fileobj(self, file, **kwargs):
return pickle.load(file, **kwargs)
def load_from_path(self, filepath, **kwargs):
return super(PickleHandler, self).load_from_path(
filepath, mode='rb', **kwargs)
def dump_to_str(self, obj, **kwargs):
kwargs.setdefault('protocol', 2)
return pickle.dumps(obj, **kwargs)
def dump_to_fileobj(self, obj, file, **kwargs):
kwargs.setdefault('protocol', 2)
pickle.dump(obj, file, **kwargs)
def dump_to_path(self, obj, filepath, **kwargs):
super(PickleHandler, self).dump_to_path(
obj, filepath, mode='wb', **kwargs)
```
### Load a text file as a list or dict
For example `a.txt` is a text file with 5 lines.
```
a
b
c
d
e
```
#### Load from disk
Use `list_from_file` to load the list from a.txt.
```python
>>> mmcv.list_from_file('a.txt')
['a', 'b', 'c', 'd', 'e']
>>> mmcv.list_from_file('a.txt', offset=2)
['c', 'd', 'e']
>>> mmcv.list_from_file('a.txt', max_num=2)
['a', 'b']
>>> mmcv.list_from_file('a.txt', prefix='/mnt/')
['/mnt/a', '/mnt/b', '/mnt/c', '/mnt/d', '/mnt/e']
```
For example `b.txt` is a text file with 3 lines.
```
1 cat
2 dog cow
3 panda
```
Then use `dict_from_file` to load the dict from `b.txt`.
```python
>>> mmcv.dict_from_file('b.txt')
{'1': 'cat', '2': ['dog', 'cow'], '3': 'panda'}
>>> mmcv.dict_from_file('b.txt', key_type=int)
{1: 'cat', 2: ['dog', 'cow'], 3: 'panda'}
```
#### Load from other backends
Use `list_from_file` to load the list from `s3://bucket-name/a.txt`.
```python
>>> mmcv.list_from_file('s3://bucket-name/a.txt')
['a', 'b', 'c', 'd', 'e']
>>> mmcv.list_from_file('s3://bucket-name/a.txt', offset=2)
['c', 'd', 'e']
>>> mmcv.list_from_file('s3://bucket-name/a.txt', max_num=2)
['a', 'b']
>>> mmcv.list_from_file('s3://bucket-name/a.txt', prefix='/mnt/')
['/mnt/a', '/mnt/b', '/mnt/c', '/mnt/d', '/mnt/e']
```
Use `dict_from_file` to load the dict from `s3://bucket-name/b.txt`.
```python
>>> mmcv.dict_from_file('s3://bucket-name/b.txt')
{'1': 'cat', '2': ['dog', 'cow'], '3': 'panda'}
>>> mmcv.dict_from_file('s3://bucket-name/b.txt', key_type=int)
{1: 'cat', 2: ['dog', 'cow'], 3: 'panda'}
```
### Load and dump checkpoints
#### Load checkpoints from disk or save to disk
We can read the checkpoints from disk or save to disk in the following way.
```python
import torch
filepath1 = '/path/of/your/checkpoint1.pth'
filepath2 = '/path/of/your/checkpoint2.pth'
# read from filepath1
checkpoint = torch.load(filepath1)
# save to filepath2
torch.save(checkpoint, filepath2)
```
MMCV provides many backends. `HardDiskBackend` is one of them and we can use it to read or save checkpoints.
```python
import io
from mmcv.fileio.file_client import HardDiskBackend
disk_backend = HardDiskBackend()
with io.BytesIO(disk_backend.get(filepath1)) as buffer:
checkpoint = torch.load(buffer)
with io.BytesIO() as buffer:
torch.save(checkpoint, f)
disk_backend.put(f.getvalue(), filepath2)
```
If we want to implement an interface which automatically select the corresponding
backend based on the file path, we can use the `FileClient`.
For example, we want to implement two methods for reading checkpoints as well as saving checkpoints,
which need to support different types of file paths, either disk paths, network paths or other paths.
```python
from mmcv.fileio.file_client import FileClient
def load_checkpoint(path):
file_client = FileClient.infer(uri=path)
with io.BytesIO(file_client.get(path)) as buffer:
checkpoint = torch.load(buffer)
return checkpoint
def save_checkpoint(checkpoint, path):
with io.BytesIO() as buffer:
torch.save(checkpoint, buffer)
file_client.put(buffer.getvalue(), path)
file_client = FileClient.infer_client(uri=filepath1)
checkpoint = load_checkpoint(filepath1)
save_checkpoint(checkpoint, filepath2)
```
#### Load checkpoints from the Internet
```{note}
Currently, it only supports reading checkpoints from the Internet, and does not support saving checkpoints to the Internet.
```
```python
import io
import torch
from mmcv.fileio.file_client import HTTPBackend, FileClient
filepath = 'http://path/of/your/checkpoint.pth'
checkpoint = torch.utils.model_zoo.load_url(filepath)
http_backend = HTTPBackend()
with io.BytesIO(http_backend.get(filepath)) as buffer:
checkpoint = torch.load(buffer)
file_client = FileClient.infer_client(uri=filepath)
with io.BytesIO(file_client.get(filepath)) as buffer:
checkpoint = torch.load(buffer)
```
## CUDA ops
We implement common CUDA ops used in detection, segmentation, etc.
- AssignScoreWithK
- BallQuery
- BBoxOverlaps
- CARAFE
- CrissCrossAttention
- ContextBlock
- CornerPool
- Deformable Convolution v1/v2
- Deformable RoIPool
- DynamicScatter
- GatherPoints
- FurthestPointSample
- FurthestPointSampleWithDist
- GeneralizedAttention
- GroupPoints
- KNN
- MaskedConv
- NMS
- PSAMask
- RoIPointPool3d
- RoIPool
- RoIAlign
- RoIAwarePool3d
- SimpleRoIAlign
- SigmoidFocalLoss
- SoftmaxFocalLoss
- SoftNMS
- Synchronized BatchNorm
- Voxelization
- ThreeInterpolate
- ThreeNN
- Weight standardization
- Correlation
## Registry
MMCV implements [registry](https://github.com/open-mmlab/mmcv/blob/master/mmcv/utils/registry.py) to manage different modules that share similar functionalities, e.g., backbones, head, and necks, in detectors.
Most projects in OpenMMLab use registry to manage modules of datasets and models, such as [MMDetection](https://github.com/open-mmlab/mmdetection), [MMDetection3D](https://github.com/open-mmlab/mmdetection3d), [MMClassification](https://github.com/open-mmlab/mmclassification), [MMEditing](https://github.com/open-mmlab/mmediting), etc.
### What is registry
In MMCV, registry can be regarded as a mapping that maps a class to a string.
These classes contained by a single registry usually have similar APIs but implement different algorithms or support different datasets.
With the registry, users can find and instantiate the class through its corresponding string, and use the instantiated module as they want.
One typical example is the config systems in most OpenMMLab projects, which use the registry to create hooks, runners, models, and datasets, through configs.
The API reference could be found [here](https://mmcv.readthedocs.io/en/latest/api.html?highlight=registry#mmcv.utils.Registry).
To manage your modules in the codebase by `Registry`, there are three steps as below.
1. Create a build method (optional, in most cases you can just use the default one).
2. Create a registry.
3. Use this registry to manage the modules.
`build_func` argument of `Registry` is to customize how to instantiate the class instance, the default one is `build_from_cfg` implemented [here](https://mmcv.readthedocs.io/en/latest/api.html?highlight=registry#mmcv.utils.build_from_cfg).
### A Simple Example
Here we show a simple example of using registry to manage modules in a package.
You can find more practical examples in OpenMMLab projects.
Assuming we want to implement a series of Dataset Converter for converting different formats of data to the expected data format.
We create a directory as a package named `converters`.
In the package, we first create a file to implement builders, named `converters/builder.py`, as below
```python
from mmcv.utils import Registry
# create a registry for converters
CONVERTERS = Registry('converter')
```
Then we can implement different converters in the package. For example, implement `Converter1` in `converters/converter1.py`
```python
from .builder import CONVERTERS
# use the registry to manage the module
@CONVERTERS.register_module()
class Converter1(object):
def __init__(self, a, b):
self.a = a
self.b = b
```
The key step to use registry for managing the modules is to register the implemented module into the registry `CONVERTERS` through
`@CONVERTERS.register_module()` when you are creating the module. By this way, a mapping between a string and the class is built and maintained by `CONVERTERS` as below
```python
'Converter1' -> <class 'Converter1'>
```
If the module is successfully registered, you can use this converter through configs as
```python
converter_cfg = dict(type='Converter1', a=a_value, b=b_value)
converter = CONVERTERS.build(converter_cfg)
```
### Customize Build Function
Suppose we would like to customize how `converters` are built, we could implement a customized `build_func` and pass it into the registry.
```python
from mmcv.utils import Registry
# create a build function
def build_converter(cfg, registry, *args, **kwargs):
cfg_ = cfg.copy()
converter_type = cfg_.pop('type')
if converter_type not in registry:
raise KeyError(f'Unrecognized converter type {converter_type}')
else:
converter_cls = registry.get(converter_type)
converter = converter_cls(*args, **kwargs, **cfg_)
return converter
# create a registry for converters and pass ``build_converter`` function
CONVERTERS = Registry('converter', build_func=build_converter)
```
```{note}
In this example, we demonstrate how to use the `build_func` argument to customize the way to build a class instance.
The functionality is similar to the default `build_from_cfg`. In most cases, default one would be sufficient.
`build_model_from_cfg` is also implemented to build PyTorch module in `nn.Sequentail`, you may directly use them instead of implementing by yourself.
```
### Hierarchy Registry
You could also build modules from more than one OpenMMLab frameworks, e.g. you could use all backbones in [MMClassification](https://github.com/open-mmlab/mmclassification) for object detectors in [MMDetection](https://github.com/open-mmlab/mmdetection), you may also combine an object detection model in [MMDetection](https://github.com/open-mmlab/mmdetection) and semantic segmentation model in [MMSegmentation](https://github.com/open-mmlab/mmsegmentation).
All `MODELS` registries of downstream codebases are children registries of MMCV's `MODELS` registry.
Basically, there are two ways to build a module from child or sibling registries.
1. Build from children registries.
For example:
In MMDetection we define:
```python
from mmcv.utils import Registry
from mmcv.cnn import MODELS as MMCV_MODELS
MODELS = Registry('model', parent=MMCV_MODELS)
@MODELS.register_module()
class NetA(nn.Module):
def forward(self, x):
return x
```
In MMClassification we define:
```python
from mmcv.utils import Registry
from mmcv.cnn import MODELS as MMCV_MODELS
MODELS = Registry('model', parent=MMCV_MODELS)
@MODELS.register_module()
class NetB(nn.Module):
def forward(self, x):
return x + 1
```
We could build two net in either MMDetection or MMClassification by:
```python
from mmdet.models import MODELS
net_a = MODELS.build(cfg=dict(type='NetA'))
net_b = MODELS.build(cfg=dict(type='mmcls.NetB'))
```
or
```python
from mmcls.models import MODELS
net_a = MODELS.build(cfg=dict(type='mmdet.NetA'))
net_b = MODELS.build(cfg=dict(type='NetB'))
```
2. Build from parent registry.
The shared `MODELS` registry in MMCV is the parent registry for all downstream codebases (root registry):
```python
from mmcv.cnn import MODELS as MMCV_MODELS
net_a = MMCV_MODELS.build(cfg=dict(type='mmdet.NetA'))
net_b = MMCV_MODELS.build(cfg=dict(type='mmcls.NetB'))
```
## Runner
The runner class is designed to manage the training. It eases the training process with less code demanded from users while staying flexible and configurable. The main features are as listed:
- Support `EpochBasedRunner` and `IterBasedRunner` for different scenarios. Implementing customized runners is also allowed to meet customized needs.
- Support customized workflow to allow switching between different modes while training. Currently, supported modes are train and val.
- Enable extensibility through various hooks, including hooks defined in MMCV and customized ones.
### EpochBasedRunner
As its name indicates, workflow in `EpochBasedRunner` should be set based on epochs. For example, [('train', 2), ('val', 1)] means running 2 epochs for training and 1 epoch for validation, iteratively. And each epoch may contain multiple iterations. Currently, MMDetection uses `EpochBasedRunner` by default.
Let's take a look at its core logic:
```python
# the condition to stop training
while curr_epoch < max_epochs:
# traverse the workflow.
# e.g. workflow = [('train', 2), ('val', 1)]
for i, flow in enumerate(workflow):
# mode(e.g. train) determines which function to run
mode, epochs = flow
# epoch_runner will be either self.train() or self.val()
epoch_runner = getattr(self, mode)
# execute the corresponding function
for _ in range(epochs):
epoch_runner(data_loaders[i], **kwargs)
```
Currently, we support 2 modes: train and val. Let's take a train function for example and have a look at its core logic:
```python
# Currently, epoch_runner could be either train or val
def train(self, data_loader, **kwargs):
# traverse the dataset and get batch data for 1 epoch
for i, data_batch in enumerate(data_loader):
# it will execute all before_train_iter function in the hooks registered. You may want to watch out for the order.
self.call_hook('before_train_iter')
# set train_mode as False in val function
self.run_iter(data_batch, train_mode=True, **kwargs)
self.call_hook('after_train_iter')
self.call_hook('after_train_epoch')
```
### IterBasedRunner
Different from `EpochBasedRunner`, workflow in `IterBasedRunner` should be set based on iterations. For example, [('train', 2), ('val', 1)] means running 2 iters for training and 1 iter for validation, iteratively. Currently, MMSegmentation uses `IterBasedRunner` by default.
Let's take a look at its core logic:
```python
# Although we set workflow by iters here, we might also need info on the epochs in some using cases. That can be provided by IterLoader.
iter_loaders = [IterLoader(x) for x in data_loaders]
# the condition to stop training
while curr_iter < max_iters:
# traverse the workflow.
# e.g. workflow = [('train', 2), ('val', 1)]
for i, flow in enumerate(workflow):
# mode(e.g. train) determines which function to run
mode, iters = flow
# iter_runner will be either self.train() or self.val()
iter_runner = getattr(self, mode)
# execute the corresponding function
for _ in range(iters):
iter_runner(iter_loaders[i], **kwargs)
```
Currently, we support 2 modes: train and val. Let's take a val function for example and have a look at its core logic:
```python
# Currently, iter_runner could be either train or val
def val(self, data_loader, **kwargs):
# get batch data for 1 iter
data_batch = next(data_loader)
# it will execute all before_val_iter function in the hooks registered. You may want to watch out for the order.
self.call_hook('before_val_iter')
outputs = self.model.val_step(data_batch, self.optimizer, **kwargs)
self.outputs = outputs
self.call_hook('after_val_iter')
```
Other than the basic functionalities explained above, `EpochBasedRunner` and `IterBasedRunner` provide methods such as `resume`, `save_checkpoint` and `register_hook`. In case you are not familiar with the term Hook mentioned earlier, we will also provide a tutorial about it.(coming soon...) Essentially, a hook is functionality to alter or augment the code behaviors through predefined api. It allows users to have their own code called under certain circumstances. It makes code extensible in a non-intrusive manner.
### A Simple Example
We will walk you through the usage of runner with a classification task. The following code only contains essential steps for demonstration purposes. The following steps are necessary for any training tasks.
**(1) Initialize dataloader, model, optimizer, etc.**
```python
# initialize model
model=...
# initialize optimizer, typically, we set: cfg.optimizer = dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001)
optimizer = build_optimizer(model, cfg.optimizer)
# initialize the dataloader corresponding to the workflow(train/val)
data_loaders = [
build_dataloader(
ds,
cfg.data.samples_per_gpu,
cfg.data.workers_per_gpu,
...) for ds in dataset
]
```
**(2) Initialize runner**
```python
runner = build_runner(
# cfg.runner is typically set as:
# runner = dict(type='EpochBasedRunner', max_epochs=200)
cfg.runner,
default_args=dict(
model=model,
batch_processor=None,
optimizer=optimizer,
logger=logger))
```
**(3) Register training hooks and customized hooks.**
```python
# register default hooks necessary for training
runner.register_training_hooks(
# configs of learning rate, it is typically set as:
# lr_config = dict(policy='step', step=[100, 150])
cfg.lr_config,
# configuration of optimizer, e.g. grad_clip
optimizer_config,
# configuration of saving checkpoints, it is typically set as:
# checkpoint_config = dict(interval=1), saving checkpoints every epochs
cfg.checkpoint_config,
# configuration of logs
cfg.log_config,
...)
# register customized hooks
# say we want to enable ema, then we could set custom_hooks=[dict(type='EMAHook')]
if cfg.get('custom_hooks', None):
custom_hooks = cfg.custom_hooks
for hook_cfg in cfg.custom_hooks:
hook_cfg = hook_cfg.copy()
priority = hook_cfg.pop('priority', 'NORMAL')
hook = build_from_cfg(hook_cfg, HOOKS)
runner.register_hook(hook, priority=priority)
```
Then, we can use `resume` or `load_checkpoint` to load existing weights.
**(4) Start training**
```python
# workflow is typically set as: workflow = [('train', 1)]
# here the training begins.
runner.run(data_loaders, cfg.workflow)
```
Let's take `EpochBasedRunner` for example and go a little bit into details about setting workflow:
- Say we only want to put train in the workflow, then we can set: workflow = [('train', 1)]. The runner will only execute train iteratively in this case.
- Say we want to put both train and val in the workflow, then we can set: workflow = [('train', 3), ('val',1)]. The runner will first execute train for 3 epochs and then switch to val mode and execute val for 1 epoch. The workflow will be repeated until the current epoch hit the max_epochs.
- Workflow is highly flexible. Therefore, you can set workflow = [('val', 1), ('train',1)] if you would like the runner to validate first and train after.
The code we demonstrated above is already in `train.py` in MM repositories. Simply modify the corresponding keys in the configuration files and the script will execute the expected workflow automatically.
## Utils
### ProgressBar
If you want to apply a method to a list of items and track the progress, `track_progress`
is a good choice. It will display a progress bar to tell the progress and ETA.
```python
import mmcv
def func(item):
# do something
pass
tasks = [item_1, item_2, ..., item_n]
mmcv.track_progress(func, tasks)
```
The output is like the following.
![progress](../_static/progress.*)
There is another method `track_parallel_progress`, which wraps multiprocessing and
progress visualization.
```python
mmcv.track_parallel_progress(func, tasks, 8) # 8 workers
```
![progress](../_static/parallel_progress.*)
If you want to iterate or enumerate a list of items and track the progress, `track_iter_progress`
is a good choice. It will display a progress bar to tell the progress and ETA.
```python
import mmcv
tasks = [item_1, item_2, ..., item_n]
for task in mmcv.track_iter_progress(tasks):
# do something like print
print(task)
for i, task in enumerate(mmcv.track_iter_progress(tasks)):
# do something like print
print(i)
print(task)
```
### Timer
It is convenient to compute the runtime of a code block with `Timer`.
```python
import time
with mmcv.Timer():
# simulate some code block
time.sleep(1)
```
or try with `since_start()` and `since_last_check()`. This former can
return the runtime since the timer starts and the latter will return the time
since the last time checked.
```python
timer = mmcv.Timer()
# code block 1 here
print(timer.since_start())
# code block 2 here
print(timer.since_last_check())
print(timer.since_start())
```
{
"Linux": [
{
"cuda": "11.7",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "11.6",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "11.6",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.5",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.3",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.3",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.3",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.1",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.1",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.1",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.0",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.1",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.1",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.1",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "9.2",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "9.2",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "cpu",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
}
],
"Windows": [
{
"cuda": "11.7",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "11.6",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "11.6",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.5",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.3",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.3",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.3",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.1",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.1",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "11.1",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.2",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "10.2",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.1",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "10.1",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "10.1",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "cpu",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
},
{
"cuda": "cpu",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2",
"2.0.0rc1"
]
}
],
"macOS": [
{
"cuda": "cpu",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "mps",
"torch": "1.13.x",
"mmcv": [
"2.0.0rc3"
]
},
{
"cuda": "cpu",
"torch": "1.12.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
},
{
"cuda": "cpu",
"torch": "1.11.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
},
{
"cuda": "cpu",
"torch": "1.10.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
},
{
"cuda": "cpu",
"torch": "1.9.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
},
{
"cuda": "cpu",
"torch": "1.8.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
},
{
"cuda": "cpu",
"torch": "1.7.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
},
{
"cuda": "cpu",
"torch": "1.6.x",
"mmcv": [
"2.0.0rc3",
"2.0.0rc2"
]
}
]
}
.. role:: hidden
:class: hidden-section
.. currentmodule:: {{ module }}
{{ name | underline}}
.. autoclass:: {{ name }}
:members:
..
autogenerated from source/_templates/classtemplate.rst
note it does not have :inherited-members:
.. role:: hidden
:class: hidden-section
mmcv.arraymisc
===================================
.. contents:: mmcv.arraymisc
:depth: 2
:local:
:backlinks: top
.. currentmodule:: mmcv.arraymisc
.. autosummary::
:toctree: generated
:nosignatures:
quantize
dequantize
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