Skip to content

Commit

Permalink
[FEATURE] Mobilenet Series Search Space (open-mmlab#82)
Browse files Browse the repository at this point in the history
* add mbv2 block and identity

* add mbv2 block and identity unittests

* expand_factor -> expand_ratio

* add searchable mobilenet v2

* fix lints

* add spos subnet retraining config

* fix mmcls slurm search

* add proxyless_gpu setting for mbv2

* use bn default

* add angelnas spos config

* update spos readme

* fix SELayer's useage

* add docstring

* rename mbv2 to mb

* add some unittest of mb

* rename mb to mobilenet

* add some rename-mb in configs

* update README of spos

* add rename-mb in unittest

* update test_mmcls

Co-authored-by: wutongshenqiu <690364065@qq.com>
Co-authored-by: humu789 <humu@pjlab.org.cn>
  • Loading branch information
3 people authored Mar 7, 2022
1 parent 7aa3ade commit 647acc3
Show file tree
Hide file tree
Showing 13 changed files with 799 additions and 10 deletions.
24 changes: 16 additions & 8 deletions configs/nas/spos/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPOS

> [Single Path One-Shot Neural Architecture Search with Uniform Sampling](https://arxiv.org/abs/1904.00420)
<!-- [ALGORITHM] -->
Expand All @@ -10,16 +11,18 @@ Comprehensive experiments verify that our approach is flexible and effective. It

![pipeline](/docs/en/imgs/model_zoo/spos/pipeline.jpg)



## Introduction

### Supernet pre-training on ImageNet

```bash
python ./tools/mmcls/train_mmcls.py \
configs/nas/spos/spos_supernet_shufflenetv2_8xb128_in1k.py \
--work-dir $WORK_DIR
```

### Search for subnet on the trained supernet

```bash
python ./tools/mmcls/search_mmcls.py \
configs/nas/spos/spos_evolution_search_shufflenetv2_8xb2048_in1k.py \
Expand All @@ -28,6 +31,7 @@ python ./tools/mmcls/search_mmcls.py \
```

### Subnet retraining on ImageNet

```bash
python ./tools/mmcls/train_mmcls.py \
configs/nas/spos/spos_subnet_shufflenetv2_8xb128_in1k.py \
Expand All @@ -36,14 +40,18 @@ python ./tools/mmcls/train_mmcls.py \
```

## Results and models
|Dataset| Supernet | Subnet | Params(M) | Flops(G) | Top-1 (%) | Top-5 (%) | Config | Download | Remarks |
|:---------------------:|:---------------------:|:------:|:---------:|:--------:|:---------:|:---------:|:------:|:---------|:---------:|
|ImageNet| ShuffleNetV2 |[mutable](https://openmmlab-share.oss-cn-hangzhou.aliyuncs.com/mmrazor/v0.1/nas/spos/spos_shufflenetv2_subnet_8xb128_in1k/spos_shufflenetv2_subnet_8xb128_in1k_flops_0.33M_acc_73.87_20211222-454627be_mutable_cfg.yaml?versionId=CAEQHxiBgICw5b6I7xciIGY5MjVmNWFhY2U5MjQzN2M4NDViYzI2YWRmYWE1YzQx)| 3.35 | 0.33 | 73.87 | 91.6 |[config](./spos_subnet_shufflenetv2_8xb128_in1k.py)|[model](https://openmmlab-share.oss-cn-hangzhou.aliyuncs.com/mmrazor/v0.1/nas/spos/spos_shufflenetv2_subnet_8xb128_in1k/spos_shufflenetv2_subnet_8xb128_in1k_flops_0.33M_acc_73.87_20211222-1f0a0b4d.pth?versionId=CAEQHxiBgIDK5b6I7xciIDM1YjIwZjQxN2UyMDRjYjA5YTM5NTBlMGNhMTdkNjI2) &#124; [log](https://openmmlab-share.oss-cn-hangzhou.aliyuncs.com/mmrazor/v0.1/nas/spos/spos_shufflenetv2_subnet_8xb128_in1k/spos_shufflenetv2_subnet_8xb128_in1k_flops_0.33M_acc_73.87_20211222-1f0a0b4d.log.json?versionId=CAEQHxiBgIDr9cuL7xciIDBmOTZiZGUyYjRiMDQ5NzhhZjY0NWUxYmUzNDlmNTg5)| MMRazor searched

| Dataset | Supernet | Subnet | Params(M) | Flops(G) | Top-1 (%) | Top-5 (%) | Config | Download | Remarks |
| :------: |:----------------------:| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------: | :------: | :-------: | :-------: | :----------------------------------------------: |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------:|
| ImageNet | ShuffleNetV2 | [mutable](https://openmmlab-share.oss-cn-hangzhou.aliyuncs.com/mmrazor/v0.1/nas/spos/spos_shufflenetv2_subnet_8xb128_in1k/spos_shufflenetv2_subnet_8xb128_in1k_flops_0.33M_acc_73.87_20211222-454627be_mutable_cfg.yaml?versionId=CAEQHxiBgICw5b6I7xciIGY5MjVmNWFhY2U5MjQzN2M4NDViYzI2YWRmYWE1YzQx) | 3.35 | 0.33 | 73.87 | 91.6 | [config](./spos_subnet_shufflenetv2_8xb128_in1k.py) | [model](https://openmmlab-share.oss-cn-hangzhou.aliyuncs.com/mmrazor/v0.1/nas/spos/spos_shufflenetv2_subnet_8xb128_in1k/spos_shufflenetv2_subnet_8xb128_in1k_flops_0.33M_acc_73.87_20211222-1f0a0b4d.pth?versionId=CAEQHxiBgIDK5b6I7xciIDM1YjIwZjQxN2UyMDRjYjA5YTM5NTBlMGNhMTdkNjI2) &#124; [log](https://openmmlab-share.oss-cn-hangzhou.aliyuncs.com/mmrazor/v0.1/nas/spos/spos_shufflenetv2_subnet_8xb128_in1k/spos_shufflenetv2_subnet_8xb128_in1k_flops_0.33M_acc_73.87_20211222-1f0a0b4d.log.json?versionId=CAEQHxiBgIDr9cuL7xciIDBmOTZiZGUyYjRiMDQ5NzhhZjY0NWUxYmUzNDlmNTg5) | MMRazor searched |
| ImageNet | MobileNet-ProxylessGPU | [mutable](https://download.openmmlab.com/mmrazor/v0.1/nas/spos/spos_mobilenet_subnet/spos_angelnas_flops_0.49G_acc_75.98_20220307-54f4698f_mutable_cfg.yaml) | 5.94 | 0.49* | 75.98 | 92.77 | [config](./spos_mobilenet_for_check_ckpt_from_anglenas.py) | | [AngleNAS](https://github.com/megvii-model/AngleNAS) searched |

**Note**:
1. There are some small differences in our experiment in order to be consistent with other repos in OpenMMLab. For example,
normalize images in data preprocessing; resize by cv2 rather than PIL in training; dropout is not used in network.
2. We also retrain the subnet reported in paper with their official code, Top-1 is 73.6 and Top-5 is 91.6

1. There **might be(not all the case)** some small differences in our experiment in order to be consistent with other repos in OpenMMLab. For example,
normalize images in data preprocessing; resize by cv2 rather than PIL in training; dropout is not used in network. **Please refer to corresponding config for details.**
2. For *ShuffleNetV2*, we retrain the subnet reported in paper with their official code, Top-1 is 73.6 and Top-5 is 91.6.
2. For *AngleNAS searched MobileNet-ProxylessGPU*, we obtain params and FLOPs using [this script](/tools/misc/get_flops.py), which may be different from [AngleNAS](https://github.com/megvii-model/AngleNAS#searched-models-with-abs).

## Citation

Expand Down
66 changes: 66 additions & 0 deletions configs/nas/spos/SPOS_MOBILENET_490M_FROM_ANGELNAS.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
stage_0_block_0:
chosen:
- mb_k3e1
stage_1_block_0:
chosen:
- mb_k5e3
stage_1_block_1:
chosen:
- mb_k5e3
stage_1_block_2:
chosen:
- identity
stage_1_block_3:
chosen:
- mb_k3e3
stage_2_block_0:
chosen:
- mb_k3e3
stage_2_block_1:
chosen:
- identity
stage_2_block_2:
chosen:
- identity
stage_2_block_3:
chosen:
- mb_k3e3
stage_3_block_0:
chosen:
- mb_k7e6
stage_3_block_1:
chosen:
- identity
stage_3_block_2:
chosen:
- mb_k7e3
stage_3_block_3:
chosen:
- mb_k7e3
stage_4_block_0:
chosen:
- mb_k3e3
stage_4_block_1:
chosen:
- mb_k3e3
stage_4_block_2:
chosen:
- mb_k7e3
stage_4_block_3:
chosen:
- mb_k5e3
stage_5_block_0:
chosen:
- mb_k5e6
stage_5_block_1:
chosen:
- mb_k7e3
stage_5_block_2:
chosen:
- mb_k7e3
stage_5_block_3:
chosen:
- mb_k7e3
stage_6_block_0:
chosen:
- mb_k5e6
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
_base_ = ['./spos_supernet_mobilenet_proxyless_gpu_8xb128_in1k.py']

data = dict(
samples_per_gpu=512,
workers_per_gpu=16,
)

algorithm = dict(bn_training_mode=True)

searcher = dict(
type='EvolutionSearcher',
candidate_pool_size=50,
candidate_top_k=10,
constraints=dict(flops=465 * 1e6),
metrics='accuracy',
score_key='accuracy_top-1',
max_epoch=20,
num_mutation=25,
num_crossover=25,
mutate_prob=0.1)
27 changes: 27 additions & 0 deletions configs/nas/spos/spos_mobilenet_for_check_ckpt_from_anglenas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
_base_ = [
'./spos_subnet_mobilenet_proxyless_gpu_8xb128_in1k.py',
]

img_norm_cfg = dict(mean=[0., 0., 0.], std=[1., 1., 1.], to_rgb=False)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='RandomResizedCrop', size=224),
dict(type='ColorJitter', brightness=0.4, contrast=0.4, saturation=0.4),
dict(type='RandomFlip', flip_prob=0.5, direction='horizontal'),
dict(type='Normalize', **img_norm_cfg),
dict(type='ImageToTensor', keys=['img']),
dict(type='ToTensor', keys=['gt_label']),
dict(type='Collect', keys=['img', 'gt_label'])
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='Resize', size=(256, -1)),
dict(type='CenterCrop', crop_size=224),
dict(type='Normalize', **img_norm_cfg),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
]
data = dict(
train=dict(pipeline=train_pipeline),
val=dict(pipeline=test_pipeline),
test=dict(pipeline=test_pipeline))
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
_base_ = [
'./spos_supernet_mobilenet_proxyless_gpu_8xb128_in1k.py',
]

algorithm = dict(retraining=True)
evaluation = dict(interval=10000, metric='accuracy')
checkpoint_config = dict(interval=30000)

runner = dict(max_iters=300000)
find_unused_parameters = False
101 changes: 101 additions & 0 deletions configs/nas/spos/spos_supernet_mobilenet_proxyless_gpu_8xb128_in1k.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
_base_ = [
'../../_base_/datasets/mmcls/imagenet_bs128_colorjittor.py',
'../../_base_/schedules/mmcls/imagenet_bs1024_spos.py',
'../../_base_/mmcls_runtime.py'
]
norm_cfg = dict(type='BN')
model = dict(
type='mmcls.ImageClassifier',
backbone=dict(
type='SearchableMobileNet',
first_channels=40,
last_channels=1728,
widen_factor=1.0,
norm_cfg=norm_cfg,
arch_setting_type='proxyless_gpu'),
neck=dict(type='GlobalAveragePooling'),
head=dict(
type='LinearClsHead',
num_classes=1000,
in_channels=1728,
loss=dict(
type='LabelSmoothLoss',
num_classes=1000,
label_smooth_val=0.1,
mode='original',
loss_weight=1.0),
topk=(1, 5),
),
)

mutator = dict(
type='OneShotMutator',
placeholder_mapping=dict(
searchable_blocks=dict(
type='OneShotOP',
choices=dict(
mb_k3e3=dict(
type='MBBlock',
kernel_size=3,
expand_ratio=3,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')),
mb_k5e3=dict(
type='MBBlock',
kernel_size=5,
expand_ratio=3,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')),
mb_k7e3=dict(
type='MBBlock',
kernel_size=7,
expand_ratio=3,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')),
mb_k3e6=dict(
type='MBBlock',
kernel_size=3,
expand_ratio=6,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')),
mb_k5e6=dict(
type='MBBlock',
kernel_size=5,
expand_ratio=6,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')),
mb_k7e6=dict(
type='MBBlock',
kernel_size=7,
expand_ratio=6,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')),
identity=dict(type='Identity'))),
first_blocks=dict(
type='OneShotOP',
choices=dict(
mb_k3e1=dict(
type='MBBlock',
kernel_size=3,
expand_ratio=1,
norm_cfg=norm_cfg,
act_cfg=dict(type='ReLU6')), ))))

algorithm = dict(
type='SPOS',
architecture=dict(
type='MMClsArchitecture',
model=model,
),
mutator=mutator,
distiller=None,
retraining=False,
)

runner = dict(max_iters=150000)
evaluation = dict(interval=10000, metric='accuracy')

# checkpoint saving
checkpoint_config = dict(interval=30000)

find_unused_parameters = True
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright (c) OpenMMLab. All rights reserved.
from .darts_backbone import DartsBackbone
from .searchable_mobilenet import SearchableMobileNet
from .searchable_shufflenet_v2 import SearchableShuffleNetV2

__all__ = ['DartsBackbone', 'SearchableShuffleNetV2']
__all__ = ['DartsBackbone', 'SearchableShuffleNetV2', 'SearchableMobileNet']
Loading

0 comments on commit 647acc3

Please sign in to comment.