From c78973b97395f0a0eb022d005b513be2292110f2 Mon Sep 17 00:00:00 2001 From: PJDong <1115957667@qq.com> Date: Mon, 29 Aug 2022 22:21:22 +0800 Subject: [PATCH] [doc] add doc of installation, kd, nas, pruning --- docs/en/get_started/installation.md | 99 ++++++++++++++++++ docs/en/user_guides/kd.md | 123 ++++++++++++++++++++++ docs/en/user_guides/nas.md | 135 +++++++++++++++++++++++++ docs/en/user_guides/pruning.md | 151 ++++++++++++++++++++++++++++ 4 files changed, 508 insertions(+) diff --git a/docs/en/get_started/installation.md b/docs/en/get_started/installation.md index 25267fe2b..66e31a9ca 100644 --- a/docs/en/get_started/installation.md +++ b/docs/en/get_started/installation.md @@ -1 +1,100 @@ # Installation + +## Prepare Environment + +Create a conda virtual environment and activate it. + +```Python +conda create -n openmmlab python=3.7 -y +conda activate openmmlab +``` + +Install PyTorch and torchvision following the [official instructions](https://pytorch.org/). + +Note: Make sure that your compilation CUDA version and runtime CUDA version match. You can check the supported CUDA version for precompiled packages on the [PyTorch website](https://pytorch.org/). + +`E.g.1` If you have CUDA 10.2 installed under `/usr/local/cuda` and would like to install PyTorch 1.10, you need to install the prebuilt PyTorch with CUDA 10.2. + +```Python +conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch +``` + +`E.g.2` If you have CUDA 9.2 installed under `/usr/local/cuda` and would like to install PyTorch 1.5.1, you need to install the prebuilt PyTorch with CUDA 9.2. + +```Python +conda install pytorch==1.5.1 torchvision==0.6.1 cudatoolkit=9.2 -c pytorch +``` + +- If you build PyTorch from source instead of installing the prebuilt package, you can use more CUDA versions such as 9.0. + +## Customize Installation + +It is recommended to install MMRazor with [MIM](https://github.com/open-mmlab/mim), which automatically handles the dependencies of OpenMMLab projects, including mmcv and other python packages. + +```Python +pip install openmim +mim install git+https://github.com/open-mmlab/mmrazor.git@1.0.0rc0 +``` + +Or you can still install MMRazor manually + +1. Install mmcv-full. + +```Python +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 10.2` and `PyTorch 1.10.0`, use the following command: + +```Python +pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.10.0/index.html +``` + +See [here](https://github.com/open-mmlab/mmcv#installation) for different versions of MMCV compatible to different PyTorch and CUDA versions. + +Optionally, you can compile mmcv from source. Refer to the [guide](https://github.com/open-mmlab/mmcv#installation) for details. + +1. Install MMEngine. + +Compile MMEngine from source. + +```Python +git clone https://github.com/open-mmlab/mmengine.git +cd mmengine +pip install -v -e . +``` + +1. Install MMRazor. + +If you would like to install MMRazor in `dev` mode, run following: + +```Python +git clone https://github.com/open-mmlab/mmrazor.git +cd mmrazor +git fetch origin +git checkout -b 1.0.0rc0 origin/1.0.0rc0 +# The new version is released in branch ``1.0.0rc0`` +pip install -v -e . +# "-v" means verbose, or more output +# "-e" means installing a project in editable mode, +# thus any local modifications made to the code will take effect without reinstallation. +``` + +**Note:** + +- When MMRazor is installed on `dev` mode, any local modifications made to the code will take effect without the need to reinstall it. + +## A from-scratch Setup Script + +```Python +conda create -n openmmlab python=3.7 -y +conda activate openmmlab + +conda install pytorch torchvision cudatoolkit=10.2 -c pytorch +# install the latest mmcv +pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.10.0/index.html +# install mmrazor +git clone https://github.com/open-mmlab/mmrazor.git +cd mmrazor +pip install -v -e . +``` diff --git a/docs/en/user_guides/kd.md b/docs/en/user_guides/kd.md index be95c5f18..072732fbe 100644 --- a/docs/en/user_guides/kd.md +++ b/docs/en/user_guides/kd.md @@ -1 +1,124 @@ # Knowledge Distillation + +Here we show how to develop new KD algorithms with an example of `SingleTeacherDistill`. + +1. Register a new algorithm + +Create a new file `mmrazor/models/algorithms/distill/configurable/single_teacher_distill.py`, class `SingleTeacherDistill` inherits from class `BaseAlgorithm` + +```Python +from mmrazor.registry import MODELS +from ..base import BaseAlgorithm + +@ALGORITHMS.register_module() +class SingleTeacherDistill(BaseAlgorithm): + def __init__(self, use_gt, **kwargs): + super(Distillation, self).__init__(**kwargs) + pass + + def train_step(self, data, optimizer): + pass +``` + +2. Develop connectors (Optional) . + +Take ConvModuleConnector as an example. + +```python +from mmrazor.registry import MODELS +from .base_connector import BaseConnector + +@MODELS.register_module() +class ConvModuleConncetor(BaseConnector): + def __init__(self, in_channel, out_channel, kernel_size = 1, stride = 1): + ... + + def forward_train(self, feature): + ... +``` + +3. Develop distiller. + +Take `ConfigurableDistiller` as an example. + +```python +from .base_distiller import BaseDistiller +from mmrazor.registry import MODELS + + +@MODELS.register_module() +class ConfigurableDistiller(BaseDistiller): + def __init__(self, + student_recorders = None, + teacher_recorders = None, + distill_deliveries = None, + connectors = None, + distill_losses = None, + loss_forward_mappings = None): + ... + + def build_connectors(self, connectors): + ... + + def build_distill_losses(self, losses): + ... + + def compute_distill_losses(self): + ... +``` + +4. Develop custom loss (Optional). + +Here we take `L1Loss` as an example. Create a new file in `mmrazor/models/losses/l1_loss.py`. + +```python +from mmrazor.registry import MODELS + +@MODELS.register_module() +class L1Loss(nn.Module): + def __init__( + self, + loss_weight: float = 1.0, + size_average: Optional[bool] = None, + reduce: Optional[bool] = None, + reduction: str = 'mean', + ) -> None: + super().__init__() + ... + + def forward(self, s_feature, t_feature): + loss = F.l1_loss(s_feature, t_feature, self.size_average, self.reduce, + self.reduction) + return self.loss_weight * loss +``` + +5. Import the class + +You can either add the following line to `mmrazor/models/algorithms/__init__.py` + +```Python +from .single_teacher_distill import SingleTeacherDistill + +__all__ = [..., 'SingleTeacherDistill'] +``` + +or alternatively add + +```Python +custom_imports = dict( + imports=['mmrazor.models.algorithms.distill.configurable.single_teacher_distill'], + allow_failed_imports=False) +``` + +to the config file to avoid modifying the original code. + +6. Use the algorithm in your config file + +```Python +algorithm = dict( + type='Distill', + distiller=dict(type='SingleTeacherDistill', ...), + # you can also use your new algorithm components here + ... +) +``` diff --git a/docs/en/user_guides/nas.md b/docs/en/user_guides/nas.md index 5a6d5e15f..b8bea6d7b 100644 --- a/docs/en/user_guides/nas.md +++ b/docs/en/user_guides/nas.md @@ -1 +1,136 @@ # Neural Architecture Search + +Here we show how to develop new NAS algorithms with an example of SPOS. + +1. Register a new algorithm + +Create a new file `mmrazor/models/algorithms/nas/spos.py`, class `SPOS` inherits from class `BaseAlgorithm` + +```Python +from mmrazor.registry import MODELS +from ..base import BaseAlgorithm + +@MODELS.register_module() +class SPOS(BaseAlgorithm): + def __init__(self, **kwargs): + super(SPOS, self).__init__(**kwargs) + pass + + def loss(self, batch_inputs, data_samples): + pass +``` + +1. Develop new algorithm components (optional) + +SPOS can directly use class `OneShotModuleMutator` as core functions provider. If mutators provided in MMRazor don’t meet your needs, you can develop new algorithm components for your algorithm like `OneShotModuleMutator`, we will take `OneShotModuleMutator` as an example to introduce how to develop a new algorithm component: + +a. Create a new file `mmrazor/models/mutators/module_mutator/one_shot_module_mutator.py`, class `OneShotModuleMutator` inherits from class `ModuleMutator` + +b. Finish the functions you need in `OneShotModuleMutator`, eg: `sample_choices`, `set_choices` and so on. + +```Python +from mmrazor.registry import MODELS +from .module_mutator import ModuleMutator + + +@MODELS.register_module() +class OneShotModuleMutator(ModuleMutator): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def sample_choices(self) -> Dict[int, Any]: + pass + + def set_choices(self, choices: Dict[int, Any]) -> None: + pass + + @property + def mutable_class_type(self): + return OneShotMutableModule +``` + +c. Import the new mutator + +You can either add the following line to `mmrazor/models/mutators/__init__.py` + +```Python +from .module_mutator import OneShotModuleMutator +``` + +or alternatively add + +```Python +custom_imports = dict( + imports=['mmrazor.models.mutators.module_mutator.one_shot_module_mutator'], + allow_failed_imports=False) +``` + +to the config file to avoid modifying the original code. + +d. Use the algorithm component in your config file + +```Python +mutator=dict(type='mmrazor.OneShotModuleMutator') +``` + +For further information, please refer to [Mutator ](https://aicarrier.feishu.cn/docx/doxcnmcie75HcbqkfBGaEoemBKg)for more details. + +1. Rewrite its `loss` function. + +Develop key logic of your algorithm in function`loss`. When having special steps to optimize, you should rewrite the function `train_step`. + +```Python +@MODELS.register_module() +class SPOS(BaseAlgorithm): + def __init__(self, **kwargs): + super(SPOS, self).__init__(**kwargs) + pass + + def sample_subnet(self): + pass + + def set_subnet(self, subnet): + pass + + def loss(self, batch_inputs, data_samples): + if self.is_supernet: + random_subnet = self.sample_subnet() + self.set_subnet(random_subnet) + return self.architecture(batch_inputs, data_samples, mode='loss') + else: + return self.architecture(batch_inputs, data_samples, mode='loss') +``` + +1. Add your custom functions (optional) + +After finishing your key logic in function `loss`, if you also need other custom functions, you can add them in class `SPOS` as follows. + +1. Import the class + +You can either add the following line to `mmrazor/models/algorithms/nas/__init__.py` + +```Python +from .spos import SPOS + +__all__ = ['SPOS'] +``` + +or alternatively add + +```Python +custom_imports = dict( + imports=['mmrazor.models.algorithms.nas.spos'], + allow_failed_imports=False) +``` + +to the config file to avoid modifying the original code. + +1. Use the algorithm in your config file + +```Python +model = dict( + type='mmrazor.SPOS', + architecture=supernet, + mutator=dict(type='mmrazor.OneShotModuleMutator')) +``` diff --git a/docs/en/user_guides/pruning.md b/docs/en/user_guides/pruning.md index 8bed33b3f..0cb1c617e 100644 --- a/docs/en/user_guides/pruning.md +++ b/docs/en/user_guides/pruning.md @@ -1 +1,152 @@ # Pruning + +Here we show how to develop new Pruning algorithms with an example of AutoSlim. + +1. Register a new algorithm + +Create a new file `mmrazor/models/algorithms/prunning/autoslim.py`, class `AutoSlim` inherits from class `BaseAlgorithm`. + +```Python +from mmrazor.registry import MODELS +from .base import BaseAlgorithm + +@MODELS.register_module() +class AutoSlim(BaseAlgorithm): + def __init__(self, + mutator, + distiller, + architecture, + data_preprocessor, + init_cfg = None, + num_samples = 2) -> None: + super().__init__(**kwargs) + pass + + def train_step(self, data, optimizer): + pass +``` + +1. Develop new algorithm components (optional) + +AutoSlim can directly use class `OneShotChannelMutator` as core functions provider. If it can not meet your needs, you can develop new algorithm components for your algorithm like `OneShotChannalMutator`. We will take `OneShotChannelMutator` as an example to introduce how to develop a new algorithm component: + +a. Create a new file `mmrazor/models/mutators/channel_mutator/one_shot_channel_mutator.py`, class `OneShotChannelMutator` can inherits from `ChannelMutator`. + +b. Finish the functions you need, eg: `build_search_groups`, `set_choices` , `sample_choices` and so on + +```Python +from mmrazor.registry import MODELS +from .channel_mutator import ChannelMutator + + +@MODELS.register_module() +class OneShotChannelMutator(ChannelMutator): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def sample_choices(self): + pass + + def set_choices(self, choice_dict): + pass + + # supernet is a kind of architecture in `mmrazor/models/architectures/` + def build_search_groups(self, supernet): + pass +``` + +c. Import the module in `mmrazor/models/mutators/channel_mutator/__init__.py` + +```Python +from .one_shot_channel_mutator import OneShotChannelMutator + + __all__ = [..., 'OneShotChannelMutator'] +``` + +1. Rewrite its train_step + +Develop key logic of your algorithm in function`train_step` + +```Python +from mmrazor.registry import MODELS +from ..base import BaseAlgorithm + +@ALGORITHMS.register_module() +class AutoSlim(BaseAlgorithm): + def __init__(self, + mutator, + distiller, + architecture, + data_preprocessor, + init_cfg = None, + num_samples = 2) -> None: + super(AutoSlim, self).__init__(**kwargs) + pass + + def train_step(self, data: List[dict], + optim_wrapper: OptimWrapper) -> Dict[str, torch.Tensor]: + + def distill_step( + batch_inputs: torch.Tensor, data_samples: List[BaseDataElement] + ) -> Dict[str, torch.Tensor]: + ... + return subnet_losses + + batch_inputs, data_samples = self.data_preprocessor(data, True) + + total_losses = dict() + self.set_max_subnet() + with optim_wrapper.optim_context( + self), self.distiller.teacher_recorders: # type: ignore + max_subnet_losses = self(batch_inputs, data_samples, mode='loss') + parsed_max_subnet_losses, _ = self.parse_losses(max_subnet_losses) + optim_wrapper.update_params(parsed_max_subnet_losses) + total_losses.update(add_prefix(max_subnet_losses, 'max_subnet')) + + self.set_min_subnet() + min_subnet_losses = distill_step(batch_inputs, data_samples) + total_losses.update(add_prefix(min_subnet_losses, 'min_subnet')) + + for sample_idx in range(self.num_samples): + self.set_subnet(self.sample_subnet()) + random_subnet_losses = distill_step(batch_inputs, data_samples) + total_losses.update( + add_prefix(random_subnet_losses, + f'random_subnet_{sample_idx}')) + + return total_losses +``` + +1. Add your custom functions (optional) + +After finishing your key logic in function `train_step`, if you also need other custom functions, you can add them in class `AutoSlim`. + +1. Import the class + +You can either add the following line to `mmrazor/models/algorithms/__init__.py` + +```Python +from .pruning import AutoSlim + +__all__ = [..., 'AutoSlim'] +``` + +Or alternatively add + +```Python +custom_imports = dict( + imports=['mmrazor.models.algorithms.pruning.autoslim'], + allow_failed_imports=False) +``` + +to the config file to avoid modifying the original code. + +1. Use the algorithm in your config file + +```Python +model = dict( + type='AutoSlim', + architecture=..., + mutator=dict(type='OneShotChannelMutator', ...), + ) +```