Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add NSGANetV2 Algorithm #292

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
106 changes: 106 additions & 0 deletions configs/_base_/nas_backbones/nsga_mobilenetv3_supernet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# search space
arch_setting = dict(
kernel_size=[ # [min_kernel_size, max_kernel_size, step]
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
[3, 7, 2],
],
num_blocks=[ # [min_num_blocks, max_num_blocks, step]
[1, 1, 1],
[1, 1, 1],
[0, 1, 1],
[0, 1, 1],
[1, 1, 1],
[1, 1, 1],
[0, 1, 1],
[0, 1, 1],
[1, 1, 1],
[1, 1, 1],
[0, 1, 1],
[0, 1, 1],
[1, 1, 1],
[1, 1, 1],
[0, 1, 1],
[0, 1, 1],
[1, 1, 1],
[1, 1, 1],
[0, 1, 1],
[0, 1, 1],
],
expand_ratio=[ # [min_expand_ratio, max_expand_ratio, step]
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[3, 6, 1],
[6, 6, 1], # last layer
],
num_out_channels=[ # [min_channel, max_channel, step]
[16, 16, 1], # first layer
[24, 24, 1],
[24, 24, 1],
[24, 24, 1],
[24, 24, 1],
[40, 40, 1],
[40, 40, 1],
[40, 40, 1],
[40, 40, 1],
[80, 80, 1],
[80, 80, 1],
[80, 80, 1],
[80, 80, 1],
[112, 112, 1],
[112, 112, 1],
[112, 112, 1],
[112, 112, 1],
[160, 160, 1],
[160, 160, 1],
[160, 160, 1],
[160, 160, 1],
[1280, 1280, 1], # last layer
])

input_resizer_cfg = dict(
input_sizes=[[192, 192], [208, 208], [224, 224], [256, 256]])

nas_backbone = dict(
type='AttentiveMobileNetV3',
arch_setting=arch_setting,
out_indices=(20, ),
stride_list=[2, 1, 1, 1] * 3 + [1] * 4 + [2] + [1] * 3,
with_se_list=[False] * 4 + [True] * 4 + [False] * 4 + [True] * 8,
act_cfg_list=['ReLU'] * 9 + ['HSwish'] * 13,
conv_cfg=dict(type='OFAConv2d'),
norm_cfg=dict(type='DynamicBatchNorm2d', momentum=0.1))
49 changes: 49 additions & 0 deletions configs/_base_/settings/cifar10_bs96_nsga.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# dataset settings
dataset_type = 'mmcls.CIFAR10'
data_preprocessor = dict(
type='mmcls.ClsDataPreprocessor',
num_classes=10,
# RGB format normalization parameters
mean=[125.307, 122.961, 113.8575],
std=[51.5865, 50.847, 51.255],
# loaded images are already RGB format
to_rgb=False)

train_pipeline = [
dict(type='mmcls.RandomCrop', crop_size=32, padding=4),
dict(type='mmcls.RandomFlip', prob=0.5, direction='horizontal'),
dict(type='mmcls.Cutout', shape=16, pad_val=0, prob=1.0),
dict(type='mmcls.PackClsInputs'),
]

test_pipeline = [
dict(type='mmcls.PackClsInputs'),
]

train_dataloader = dict(
batch_size=96,
num_workers=5,
dataset=dict(
type=dataset_type,
data_prefix='data/cifar10',
test_mode=False,
pipeline=train_pipeline),
sampler=dict(type='mmcls.DefaultSampler', shuffle=True),
persistent_workers=True,
)

val_dataloader = dict(
batch_size=96,
num_workers=5,
dataset=dict(
type=dataset_type,
data_prefix='data/cifar10/',
test_mode=True,
pipeline=test_pipeline),
sampler=dict(type='mmcls.DefaultSampler', shuffle=False),
persistent_workers=True,
)
val_evaluator = dict(type='mmcls.Accuracy', topk=(1, ))

test_dataloader = val_dataloader
test_evaluator = val_evaluator
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
loss_kl=dict(
preds_S=dict(recorder='fc', from_student=True),
preds_T=dict(recorder='fc', from_student=False)))),
mutators=dict(type='mmrazor.NasMutator'))
mutator=dict(type='mmrazor.NasMutator'))

model_wrapper_cfg = dict(
type='mmrazor.BigNASDDP',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
_base_ = ['./nsganetv2_mobilenet_supernet_1xb96_cifar10.py']

model = dict(norm_training=True)

train_dataloader = dict(batch_size=256)
val_dataloader = dict(batch_size=256)
test_dataloader = val_dataloader

param_scheduler = [dict(type='ConstantLR', factor=1.0)]

train_cfg = dict(
_delete_=True,
type='mmrazor.NSGA2SearchLoop',
dataloader=_base_.val_dataloader,
evaluator=_base_.val_evaluator,
max_epochs=30,
num_candidates=50,
top_k=10,
num_mutation=25,
num_crossover=25,
mutate_prob=0.3,
constraints_range=dict(flops=(0., 330.)),
score_key='accuracy/top1',
predictor_cfg=dict(
type='mmrazor.MetricPredictor',
encoding_type='normal',
train_samples=2,
handler_cfg=dict(type='mmrazor.GaussProcessHandler')),
finetune_cfg=dict(
model=_base_.model,
train_dataloader=_base_.train_dataloader,
train_cfg=dict(by_epoch=True, max_epochs=2),
optim_wrapper=dict(
type='OptimWrapper',
optimizer=dict(
type='SGD',
lr=0.1,
momentum=0.9,
weight_decay=1e-4,
nesterov=True)),
param_scheduler=param_scheduler,
default_hooks=_base_.default_hooks,
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
_base_ = ['./nsganetv2_mobilenet_supernet_8xb128_in1k.py']

model = dict(norm_training=True)

param_scheduler = [dict(type='ConstantLR', factor=1.0)]

train_cfg = dict(
_delete_=True,
type='mmrazor.NSGA2SearchLoop',
dataloader=_base_.val_dataloader,
evaluator=_base_.val_evaluator,
max_epochs=4,
num_candidates=4,
top_k=2,
num_mutation=2,
num_crossover=2,
mutate_prob=0.1,
constraints_range=dict(flops=(0., 360.)),
score_key='accuracy/top1',
predictor_cfg=dict(
type='mmrazor.MetricPredictor',
encoding_type='normal',
train_samples=2,
handler_cfg=dict(type='mmrazor.GaussProcessHandler')),
finetune_cfg=dict(
model=_base_.model,
train_dataloader=_base_.train_dataloader,
train_cfg=dict(by_epoch=True, max_epochs=1),
optim_wrapper=dict(
type='OptimWrapper',
optimizer=dict(
type='SGD',
lr=0.025,
momentum=0.9,
weight_decay=3e-4,
nesterov=True)),
param_scheduler=param_scheduler,
default_hooks=_base_.default_hooks,
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
_base_ = [
'mmcls::_base_/default_runtime.py',
'mmcls::_base_/schedules/imagenet_bs2048.py',
'mmrazor::_base_/settings/cifar10_bs96_nsga.py',
'mmrazor::_base_/nas_backbones/nsga_mobilenetv3_supernet.py',
]

supernet = dict(
_scope_='mmrazor',
type='SearchableImageClassifier',
backbone=_base_.nas_backbone,
neck=dict(type='SqueezeMeanPoolingWithDropout', drop_ratio=0.2),
head=dict(
type='DynamicLinearClsHead',
num_classes=1000,
in_channels=1280,
loss=dict(
type='mmcls.LabelSmoothLoss',
num_classes=1000,
label_smooth_val=0.1,
mode='original',
loss_weight=1.0),
topk=(1, 5)),
input_resizer_cfg=_base_.input_resizer_cfg,
connect_head=dict(connect_with_backbone='backbone.last_mutable_channels'),
)

model = dict(
_scope_='mmrazor',
type='NSGANetV2',
architecture=supernet,
data_preprocessor=_base_.data_preprocessor,
mutator=dict(type='mmrazor.NasMutator'))

find_unused_parameters = True

default_hooks = dict(
checkpoint=dict(
type='CheckpointHook', interval=1, max_keep_ckpts=1, save_best='auto'))
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
_base_ = [
'mmcls::_base_/default_runtime.py',
'mmrazor::_base_/settings/imagenet_bs2048_bignas.py',
'mmrazor::_base_/nas_backbones/nsga_mobilenetv3_supernet.py',
]

supernet = dict(
_scope_='mmrazor',
type='SearchableImageClassifier',
backbone=_base_.nas_backbone,
neck=dict(type='SqueezeMeanPoolingWithDropout', drop_ratio=0.2),
head=dict(
type='DynamicLinearClsHead',
num_classes=1000,
in_channels=1280,
loss=dict(
type='mmcls.LabelSmoothLoss',
num_classes=1000,
label_smooth_val=0.1,
mode='original',
loss_weight=1.0),
topk=(1, 5)),
input_resizer_cfg=_base_.input_resizer_cfg,
connect_head=dict(connect_with_backbone='backbone.last_mutable_channels'),
)

model = dict(
_scope_='mmrazor',
type='NSGANetV2',
architecture=supernet,
data_preprocessor=_base_.data_preprocessor,
mutator=dict(type='mmrazor.NasMutator'))

find_unused_parameters = True

default_hooks = dict(
checkpoint=dict(
type='CheckpointHook', interval=1, max_keep_ckpts=1, save_best='auto'))
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
loss_kl=dict(
preds_S=dict(recorder='fc', from_student=True),
preds_T=dict(recorder='fc', from_student=False)))),
mutators=dict(type='mmrazor.NasMutator'))
mutator=dict(type='mmrazor.NasMutator'))

model_wrapper_cfg = dict(
type='mmrazor.BigNASDDP',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
_base_ = ['./spos_shufflenet_supernet_8xb128_in1k.py']

model = dict(norm_training=True)

train_cfg = dict(
_delete_=True,
type='mmrazor.NSGA2SearchLoop',
dataloader=_base_.val_dataloader,
evaluator=_base_.val_evaluator,
max_epochs=20,
num_candidates=50,
top_k=10,
num_mutation=25,
num_crossover=25,
mutate_prob=0.1,
constraints_range=dict(flops=(0., 360.)),
predictor_cfg=dict(
type='mmrazor.MetricPredictor',
encoding_type='normal',
train_samples=2,
handler_cfg=dict(type='mmrazor.GaussProcessHandler')),
)
10 changes: 5 additions & 5 deletions mmrazor/engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
from .optimizers import SeparateOptimWrapperConstructor
from .runner import (AutoSlimGreedySearchLoop, DartsEpochBasedTrainLoop,
DartsIterBasedTrainLoop, EvolutionSearchLoop,
GreedySamplerTrainLoop, SelfDistillValLoop,
SingleTeacherDistillValLoop, SlimmableValLoop,
SubnetValLoop)
GreedySamplerTrainLoop, NSGA2SearchLoop,
SelfDistillValLoop, SingleTeacherDistillValLoop,
SlimmableValLoop, SubnetValLoop)

__all__ = [
'SeparateOptimWrapperConstructor', 'DumpSubnetHook',
'SingleTeacherDistillValLoop', 'DartsEpochBasedTrainLoop',
'DartsIterBasedTrainLoop', 'SlimmableValLoop', 'EvolutionSearchLoop',
'GreedySamplerTrainLoop', 'EstimateResourcesHook', 'SelfDistillValLoop',
'AutoSlimGreedySearchLoop', 'SubnetValLoop'
'GreedySamplerTrainLoop', 'SubnetValLoop', 'EstimateResourcesHook',
'SelfDistillValLoop', 'NSGA2SearchLoop', 'AutoSlimGreedySearchLoop'
]
3 changes: 2 additions & 1 deletion mmrazor/engine/runner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .distill_val_loop import SelfDistillValLoop, SingleTeacherDistillValLoop
from .evolution_search_loop import EvolutionSearchLoop
from .iteprune_val_loop import ItePruneValLoop
from .nsganetv2_search_loop import NSGA2SearchLoop
from .slimmable_val_loop import SlimmableValLoop
from .subnet_sampler_loop import GreedySamplerTrainLoop
from .subnet_val_loop import SubnetValLoop
Expand All @@ -12,5 +13,5 @@
'SingleTeacherDistillValLoop', 'DartsEpochBasedTrainLoop',
'DartsIterBasedTrainLoop', 'SlimmableValLoop', 'EvolutionSearchLoop',
'GreedySamplerTrainLoop', 'SubnetValLoop', 'SelfDistillValLoop',
'ItePruneValLoop', 'AutoSlimGreedySearchLoop'
'NSGA2SearchLoop', 'ItePruneValLoop', 'AutoSlimGreedySearchLoop'
]
Loading