├── .gitignore
├── LICENSE
├── MANIFEST.in
├── NOTICE
├── README.md
├── configs
├── action_recognition
│ ├── E3D_X3DL_FLOPs.py
│ ├── E3D_X3DM_FLOPs.py
│ ├── E3D_X3DS_FLOPs.py
│ ├── README.md
│ └── models
│ │ ├── E3D_L.txt
│ │ ├── E3D_M.txt
│ │ └── E3D_S.txt
├── classification
│ ├── MBV2_FLOPs.py
│ ├── R50_FLOPs.py
│ ├── README.md
│ ├── deepmad_29M_224.py
│ ├── deepmad_29M_288.py
│ ├── deepmad_50M.py
│ ├── deepmad_89M.py
│ ├── deepmad_R18_FLOPs.py
│ ├── deepmad_R34_FLOPs.py
│ ├── deepmad_R50_FLOPs.py
│ └── models
│ │ ├── R152-like.txt
│ │ ├── R18-like.txt
│ │ ├── R50-like.txt
│ │ ├── deepmad-29M-224.txt
│ │ ├── deepmad-29M-288.txt
│ │ ├── deepmad-50M.txt
│ │ ├── deepmad-89M.txt
│ │ ├── deepmad-R18.txt
│ │ ├── deepmad-R34.txt
│ │ └── deepmad-R50.txt
├── damoyolo
│ ├── damoyolo_k1kx_small.py
│ ├── damoyolo_k1kx_tiny.py
│ └── damoyolo_kxkx_medium.py
├── detection
│ ├── R50_FLOPs.py
│ ├── R50_FLOPs_predictor.py
│ ├── README.md
│ └── models
│ │ ├── gfocal_maedet
│ │ ├── gfocal_r50_fpn_ms6x.py
│ │ ├── maedet_l_6x_lr0.02.py
│ │ ├── maedet_m_6x_lr0.02.py
│ │ └── maedet_s_6x_lr0.02.py
│ │ ├── madnas.py
│ │ ├── maedet_l.txt
│ │ ├── maedet_m.txt
│ │ └── maedet_s.txt
└── quant
│ ├── Mixed_19d2G.py
│ ├── Mixed_7d0G.py
│ ├── README.md
│ └── models
│ ├── mixed19d2G.txt
│ └── mixed7d0G.txt
├── docs
└── arch.png
├── get_started.md
├── installation.md
├── modelscope
├── __init__.py
├── fileio
│ ├── __init__.py
│ ├── file.py
│ ├── format
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── json.py
│ │ └── yaml.py
│ └── io.py
├── utils
│ ├── __init__.py
│ ├── config.py
│ ├── config_ds.py
│ ├── constant.py
│ ├── data_utils.py
│ ├── error.py
│ ├── file_utils.py
│ ├── import_utils.py
│ ├── json_utils.py
│ ├── logger.py
│ ├── megatron_utils.py
│ ├── metric.py
│ ├── model_tag.py
│ ├── plugins.py
│ ├── registry.py
│ ├── tensor_utils.py
│ ├── timer.py
│ ├── torch_utils.py
│ ├── type_assert.py
│ └── typing.py
└── version.py
├── requirements
├── nas.txt
└── tests.txt
├── setup.cfg
├── setup.py
├── tinynas
├── __init__.py
├── budgets
│ ├── README.md
│ ├── __init__.py
│ ├── base.py
│ ├── budgets.py
│ └── builder.py
├── deploy
│ ├── cnn3dnet
│ │ ├── cnn3dnet.py
│ │ ├── demo.py
│ │ └── modules
│ │ │ ├── __init__.py
│ │ │ ├── blocks_basic_3D.py
│ │ │ └── super_res3d_k1dwk1.py
│ └── cnnnet
│ │ ├── cnnnet.py
│ │ ├── demo.py
│ │ └── modules
│ │ ├── __init__.py
│ │ ├── blocks_basic.py
│ │ ├── qconv.py
│ │ ├── super_quant_res_k1dwk1.py
│ │ ├── super_res_k1dwk1.py
│ │ ├── super_res_k1dwsek1.py
│ │ ├── super_res_k1kx.py
│ │ ├── super_res_k1kxk1.py
│ │ └── super_res_kxkx.py
├── evolutions
│ ├── README.md
│ ├── __init__.py
│ └── population.py
├── latency
│ ├── __init__.py
│ ├── builder.py
│ ├── op_predictor.py
│ ├── op_profiler
│ │ ├── R50.txt
│ │ ├── README.md
│ │ ├── V100
│ │ │ ├── conv_data.out
│ │ │ ├── conv_data.out.fp16
│ │ │ ├── conv_data.out.fp16.damoyolo
│ │ │ └── conv_data.out.int8
│ │ ├── __init__.py
│ │ ├── op_profiler.jpg
│ │ ├── predictor.py
│ │ ├── python
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── config.in
│ │ │ ├── read_log.py
│ │ │ ├── sample.sh
│ │ │ └── sampler.py
│ │ ├── test_predictor.py
│ │ └── util.py
│ └── robust_gpu_predictor.py
├── models
│ ├── README.md
│ ├── __init__.py
│ ├── base.py
│ ├── blocks_cnn_2d
│ │ ├── __init__.py
│ │ ├── blocks_basic.py
│ │ ├── qconv.py
│ │ ├── super_quant_res_k1dwk1.py
│ │ ├── super_res_k1dwk1.py
│ │ ├── super_res_k1dwsek1.py
│ │ ├── super_res_k1kx.py
│ │ ├── super_res_k1kxk1.py
│ │ └── super_res_kxkx.py
│ ├── blocks_cnn_3d
│ │ ├── __init__.py
│ │ ├── blocks_basic_3D.py
│ │ └── super_res3d_k1dwk1.py
│ ├── builder.py
│ ├── cnn3dnet.py
│ └── cnnnet.py
├── scores
│ ├── README.md
│ ├── __init__.py
│ ├── builder.py
│ ├── compute_deepmad.py
│ ├── compute_ensemble.py
│ ├── compute_madnas.py
│ ├── compute_random.py
│ └── compute_stentr.py
├── searchers
│ ├── README.md
│ ├── __init__.py
│ ├── base.py
│ ├── builder.py
│ ├── searcher.py
│ └── synchonizer.py
├── spaces
│ ├── README.md
│ ├── __init__.py
│ ├── base.py
│ ├── builder.py
│ ├── mutator
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── basic_mutators.py
│ │ ├── builder.py
│ │ ├── conv3d_bn_relu_mutator.py
│ │ ├── conv_bn_relu_mutator.py
│ │ ├── super_quant_res_k1dwk1_mutator.py
│ │ ├── super_res3d_k1dwk1_mutator.py
│ │ ├── super_res_k1dwk1_mutator.py
│ │ ├── super_res_k1kx_mutator.py
│ │ └── super_res_k1kxk1_mutator.py
│ ├── random_sample.py
│ ├── space_3d_k1dwk1.py
│ ├── space_k1dwk1.py
│ ├── space_k1dwsek1.py
│ ├── space_k1kx.py
│ ├── space_k1kxk1.py
│ ├── space_kxkx.py
│ ├── space_quant_k1dwk1.py
│ └── space_utils.py
├── strategy
│ ├── README.md
│ ├── __init__.py
│ └── strategy.py
└── utils
│ ├── __init__.py
│ ├── dict_action.py
│ ├── dist_utils.py
│ ├── file_utils.py
│ ├── import_utils.py
│ ├── logger.py
│ └── misc.py
└── tools
├── dist_search.sh
├── export.py
├── local_search.sh
└── search.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | *.patch
7 | save_model/
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 | /package
30 | /temp
31 | MANIFEST
32 |
33 | # PyInstaller
34 | # Usually these files are written by a python script from a template
35 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
36 | *.manifest
37 | *.spec
38 |
39 | # Installer logs
40 | pip-log.txt
41 | pip-delete-this-directory.txt
42 |
43 | # Unit test / coverage reports
44 | htmlcov/
45 | .tox/
46 | .coverage
47 | .coverage.*
48 | .cache
49 | nosetests.xml
50 | coverage.xml
51 | *.cover
52 | .hypothesis/
53 | .pytest_cache/
54 |
55 | # Translations
56 | *.mo
57 | *.pot
58 |
59 | # Django stuff:
60 | *.log
61 | local_settings.py
62 | db.sqlite3
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # pyenv
81 | .python-version
82 |
83 | # celery beat schedule file
84 | celerybeat-schedule
85 |
86 | # SageMath parsed files
87 | *.sage.py
88 |
89 | # Environments
90 | .env
91 | .venv
92 | env/
93 | venv/
94 | ENV/
95 | env.bak/
96 | venv.bak/
97 |
98 | # Spyder project settings
99 | .spyderproject
100 | .spyproject
101 |
102 | # Rope project settings
103 | .ropeproject
104 |
105 | # mkdocs documentation
106 | /site
107 |
108 | # mypy
109 | .mypy_cache/
110 |
111 | .vscode
112 | .idea
113 |
114 | # custom
115 | *.pkl
116 | *.pkl.json
117 | *.log.json
118 | *.whl
119 | *.tar.gz
120 | *.swp
121 | *.log
122 | *.tar.gz
123 | .DS_Store
124 | replace.sh
125 | result.png
126 |
127 | # Pytorch
128 | *.pth
129 | *.pt
130 | tinynas/configs
131 | tinynas/tools
132 | tinynas/modelscope
133 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include tinynas *gz *.txt *
2 | recursive-include tinynas/configs *
3 | recursive-include tinynas/tools *.sh *.py
4 |
--------------------------------------------------------------------------------
/configs/action_recognition/E3D_X3DL_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/E3DM_FLOPs_185e8/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ video config """
10 | image_size = 312
11 | frames = 16
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'Cnn3DNet',
16 | structure_info = [
17 | {'class': 'Conv3DKXBNRELU', 'in': 3, 'out': 24, 's': 2, 'kt': 1, 'k': 3}, \
18 | {'class': 'SuperRes3DK1DWK1', 'in': 24, 'out': 24, 's': 2, 'kt': 1, 'k': 5, 'L': 1, 'btn': 48}, \
19 | {'class': 'SuperRes3DK1DWK1', 'in': 24, 'out': 48, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 96}, \
20 | {'class': 'SuperRes3DK1DWK1', 'in': 48, 'out': 96, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 192}, \
21 | {'class': 'SuperRes3DK1DWK1', 'in': 96, 'out': 96, 's': 1, 'kt': 3, 'k': 3, 'L': 1, 'btn': 192}, \
22 | {'class': 'SuperRes3DK1DWK1', 'in': 96, 'out': 192, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 384}, \
23 | {'class': 'Conv3DKXBNRELU', 'in': 192, 'out': 512, 's': 1, 'kt': 1, 'k': 1},\
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 185e8),
30 | dict(type = "layers",budget = 167),
31 | ]
32 |
33 | """ Score config """
34 | score = dict(type = 'stentr', multi_block_ratio = [0,0,0,0,1], frames=16)
35 |
36 | """ Space config """
37 | space = dict(
38 | type = 'space_3d_k1dwk1',
39 | image_size = image_size,
40 | )
41 |
42 | """ Search config """
43 | search=dict(
44 | minor_mutation = False, # whether fix the stage layer
45 | minor_iter = 100000, # which iteration to enable minor_mutation
46 | popu_size = 256,
47 | num_random_nets = 100000, # the searching iterations
48 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
49 | num_network = 1,
50 | )
51 |
52 |
--------------------------------------------------------------------------------
/configs/action_recognition/E3D_X3DM_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/E3DM_FLOPs_50e8/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ video config """
10 | image_size = 224
11 | frames = 16
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'Cnn3DNet',
16 | structure_info = [
17 | {'class': 'Conv3DKXBNRELU', 'in': 3, 'out': 24, 's': 2, 'kt': 1, 'k': 3}, \
18 | {'class': 'SuperRes3DK1DWK1', 'in': 24, 'out': 24, 's': 2, 'kt': 1, 'k': 5, 'L': 1, 'btn': 48}, \
19 | {'class': 'SuperRes3DK1DWK1', 'in': 24, 'out': 48, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 96}, \
20 | {'class': 'SuperRes3DK1DWK1', 'in': 48, 'out': 96, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 192}, \
21 | {'class': 'SuperRes3DK1DWK1', 'in': 96, 'out': 96, 's': 1, 'kt': 3, 'k': 3, 'L': 1, 'btn': 192}, \
22 | {'class': 'SuperRes3DK1DWK1', 'in': 96, 'out': 192, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 384}, \
23 | {'class': 'Conv3DKXBNRELU', 'in': 192, 'out': 512, 's': 1, 'kt': 1, 'k': 1},\
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 50e8),
30 | dict(type = "layers",budget = 83),
31 | ]
32 |
33 | """ Score config """
34 | score = dict(type = 'stentr', multi_block_ratio = [0,0,0,0,1], frames=16)
35 |
36 | """ Space config """
37 | space = dict(
38 | type = 'space_3d_k1dwk1',
39 | image_size = image_size,
40 | )
41 |
42 | """ Search config """
43 | search=dict(
44 | minor_mutation = False, # whether fix the stage layer
45 | minor_iter = 100000, # which iteration to enable minor_mutation
46 | popu_size = 256,
47 | num_random_nets = 100000, # the searching iterations
48 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
49 | num_network = 1,
50 | )
51 |
52 |
--------------------------------------------------------------------------------
/configs/action_recognition/E3D_X3DS_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/E3DS_FLOPs_20e8/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ video config """
10 | image_size = 160
11 | frames = 13
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'Cnn3DNet',
16 | structure_info = [
17 | {'class': 'Conv3DKXBNRELU', 'in': 3, 'out': 24, 's': 2, 'kt': 1, 'k': 3}, \
18 | {'class': 'SuperRes3DK1DWK1', 'in': 24, 'out': 24, 's': 2, 'kt': 1, 'k': 5, 'L': 1, 'btn': 48}, \
19 | {'class': 'SuperRes3DK1DWK1', 'in': 24, 'out': 48, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 96}, \
20 | {'class': 'SuperRes3DK1DWK1', 'in': 48, 'out': 96, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 192}, \
21 | {'class': 'SuperRes3DK1DWK1', 'in': 96, 'out': 96, 's': 1, 'kt': 3, 'k': 3, 'L': 1, 'btn': 192}, \
22 | {'class': 'SuperRes3DK1DWK1', 'in': 96, 'out': 192, 's': 2, 'kt': 3, 'k': 3, 'L': 1, 'btn': 384}, \
23 | {'class': 'Conv3DKXBNRELU', 'in': 192, 'out': 512, 's': 1, 'kt': 1, 'k': 1},\
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 20e8),
30 | dict(type = "layers",budget = 83),
31 | ]
32 |
33 | """ Score config """
34 | score = dict(type = 'stentr', multi_block_ratio = [0,0,0,0,1], frames=13)
35 |
36 | """ Space config """
37 | space = dict(
38 | type = 'space_3d_k1dwk1',
39 | image_size = image_size,
40 | )
41 |
42 | """ Search config """
43 | search=dict(
44 | minor_mutation = False, # whether fix the stage layer
45 | minor_iter = 500000, # which iteration to enable minor_mutation
46 | popu_size = 256,
47 | num_random_nets = 500000, # the searching iterations
48 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
49 | num_network = 1,
50 | )
51 |
52 |
--------------------------------------------------------------------------------
/configs/action_recognition/README.md:
--------------------------------------------------------------------------------
1 | ## Abstract
2 |
3 | * **Instruction**
4 |
5 | We search efficient E3D backbones for action recognition and E3D-S/M/L are aligned with X3D-S/M/L.
6 |
7 |
8 | * **Use the searching configs for Classification**
9 |
10 | ```shell
11 | sh tools/dist_search.sh configs/E3D_X3DS_FLOPs.py
12 | ```
13 | **`E3D_X3DS_FLOPs.py` is the config for searching X3DS-like model within the budget of FLOPs using STEntr Score.**
14 |
15 | **`E3D_X3DM_FLOPs.py` is the config for searching X3DM-like model within the budget of FLOPs using STEntr Score.**
16 |
17 | **`E3D_X3DL_FLOPs.py` is the config for searching X3DL-like model within the budget of FLOPs using STEntr Score.**
18 |
19 | * **Use searched models in your own training pipeline**
20 |
21 | **copy `tinynas/deploy/cnn3dnet` to your pipeline, then**
22 | ```python
23 | from cnn3dnet import Cnn3DNet
24 | # for classifictaion
25 | model = Cnn3DNet(num_classes=classes,
26 | structure_txt=structure_txt,
27 | out_indices=(4,),
28 | classfication=True)
29 |
30 | # if load with pretrained model
31 | model.init_weights(pretrained=pretrained_pth)
32 | ```
33 |
34 | ***
35 |
36 | ## Results on Sth-Sth V1
37 |
38 | | Backbone | size | FLOPs (G) | Top-1 | Top-5 | Structure |
39 | |:---------:|:-------:|:-------:|:-------:|:-------:|:--------:|
40 | | E3D-S | 160 | 1.9 | 47.1 | 75.6| [txt](models/E3D_S.txt) |
41 | | E3D-M | 224 | 4.7 | 49.4 | 78.1| [txt](models/E3D_M.txt) |
42 | | E3D-L | 312 | 18.3 | 51.1 | 78.7| [txt](models/E3D_L.txt) |
43 |
44 |
45 |
46 | ***
47 | ## Citation
48 |
49 | If you find this toolbox useful, please support us by citing this work as
50 |
51 | ```
52 | @inproceedings{iclr23maxste,
53 | title = {Maximizing Spatio-Temporal Entropy of Deep 3D CNNs for Efficient Video Recognition},
54 | author = {Junyan Wang and Zhenhong Sun and Yichen Qian and Dong Gong and Xiuyu Sun and Ming Lin and Maurice Pagnucco and Yang Song },
55 | journal = {International Conference on Learning Representations},
56 | year = {2023},
57 | }
58 | ```
59 |
--------------------------------------------------------------------------------
/configs/action_recognition/models/E3D_L.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[[ {'class': 'Conv3DKXBNRELU', 'in': 3, 'k': 3, 'kt': 1, 'out': 24, 's': 2},
2 | { 'L': 3,
3 | 'btn': 32,
4 | 'class': 'SuperRes3DK1DWK1',
5 | 'in': 24,
6 | 'inner_class': 'Res3DK1DWK1',
7 | 'k': 5,
8 | 'kt': 1,
9 | 'out': 24,
10 | 's': 2},
11 | { 'L': 13,
12 | 'btn': 120,
13 | 'class': 'SuperRes3DK1DWK1',
14 | 'in': 24,
15 | 'inner_class': 'Res3DK1DWK1',
16 | 'k': 3,
17 | 'kt': 3,
18 | 'out': 48,
19 | 's': 2},
20 | { 'L': 13,
21 | 'btn': 176,
22 | 'class': 'SuperRes3DK1DWK1',
23 | 'in': 48,
24 | 'inner_class': 'Res3DK1DWK1',
25 | 'k': 3,
26 | 'kt': 3,
27 | 'out': 120,
28 | 's': 2},
29 | { 'L': 13,
30 | 'btn': 176,
31 | 'class': 'SuperRes3DK1DWK1',
32 | 'in': 120,
33 | 'inner_class': 'Res3DK1DWK1',
34 | 'k': 3,
35 | 'kt': 3,
36 | 'out': 120,
37 | 's': 1},
38 | { 'L': 13,
39 | 'btn': 480,
40 | 'class': 'SuperRes3DK1DWK1',
41 | 'in': 120,
42 | 'inner_class': 'Res3DK1DWK1',
43 | 'k': 3,
44 | 'kt': 3,
45 | 'out': 192,
46 | 's': 2},
47 | {'class': 'Conv3DKXBNRELU', 'in': 192, 'k': 1, 'kt': 1, 'out': 512, 's': 1}]],
48 | 'space_arch': 'Cnn3DNet'}
--------------------------------------------------------------------------------
/configs/action_recognition/models/E3D_M.txt:
--------------------------------------------------------------------------------
1 | {'best_structures': [[
2 | {'class': 'Conv3DKXBNRELU', 'in': 3, 'k': 3, 'kt': 1, 'out': 24, 's': 2},
3 | { 'L': 3,
4 | 'btn': 32,
5 | 'class': 'SuperRes3DK1DWK1',
6 | 'in': 24,
7 | 'inner_class': 'Res3DK1DWK1',
8 | 'k': 5,
9 | 'kt': 1,
10 | 'out': 24,
11 | 's': 2},
12 | { 'L': 6,
13 | 'btn': 96,
14 | 'class': 'SuperRes3DK1DWK1',
15 | 'in': 24,
16 | 'inner_class': 'Res3DK1DWK1',
17 | 'k': 3,
18 | 'kt': 3,
19 | 'out': 64,
20 | 's': 2},
21 | { 'L': 6,
22 | 'btn': 176,
23 | 'class': 'SuperRes3DK1DWK1',
24 | 'in': 64,
25 | 'inner_class': 'Res3DK1DWK1',
26 | 'k': 3,
27 | 'kt': 3,
28 | 'out': 120,
29 | 's': 2},
30 | { 'L': 6,
31 | 'btn': 176,
32 | 'class': 'SuperRes3DK1DWK1',
33 | 'in': 120,
34 | 'inner_class': 'Res3DK1DWK1',
35 | 'k': 3,
36 | 'kt': 3,
37 | 'out': 120,
38 | 's': 1},
39 | { 'L': 6,
40 | 'btn': 464,
41 | 'class': 'SuperRes3DK1DWK1',
42 | 'in': 120,
43 | 'inner_class': 'Res3DK1DWK1',
44 | 'k': 3,
45 | 'kt': 3,
46 | 'out': 184,
47 | 's': 2},
48 | {'class': 'Conv3DKXBNRELU', 'in': 184, 'k': 1, 'kt': 1, 'out': 512, 's': 1}]],
49 | 'space_arch': 'Cnn3DNet'}
--------------------------------------------------------------------------------
/configs/action_recognition/models/E3D_S.txt:
--------------------------------------------------------------------------------
1 | {'best_structures': [[
2 | {'class': 'Conv3DKXBNRELU', 'in': 3, 'k': 3, 'kt': 1, 'out': 24, 's': 2},
3 | { 'L': 3,
4 | 'btn': 32,
5 | 'class': 'SuperRes3DK1DWK1',
6 | 'in': 24,
7 | 'inner_class': 'Res3DK1DWK1',
8 | 'k': 5,
9 | 'kt': 1,
10 | 'out': 24,
11 | 's': 2},
12 | { 'L': 6,
13 | 'btn': 96,
14 | 'class': 'SuperRes3DK1DWK1',
15 | 'in': 24,
16 | 'inner_class': 'Res3DK1DWK1',
17 | 'k': 3,
18 | 'kt': 3,
19 | 'out': 48,
20 | 's': 2},
21 | { 'L': 6,
22 | 'btn': 176,
23 | 'class': 'SuperRes3DK1DWK1',
24 | 'in': 48,
25 | 'inner_class': 'Res3DK1DWK1',
26 | 'k': 3,
27 | 'kt': 3,
28 | 'out': 120,
29 | 's': 2},
30 | { 'L': 6,
31 | 'btn': 176,
32 | 'class': 'SuperRes3DK1DWK1',
33 | 'in': 120,
34 | 'inner_class': 'Res3DK1DWK1',
35 | 'k': 3,
36 | 'kt': 3,
37 | 'out': 120,
38 | 's': 1},
39 | { 'L': 6,
40 | 'btn': 384,
41 | 'class': 'SuperRes3DK1DWK1',
42 | 'in': 120,
43 | 'inner_class': 'Res3DK1DWK1',
44 | 'k': 3,
45 | 'kt': 3,
46 | 'out': 256,
47 | 's': 2},
48 | {'class': 'Conv3DKXBNRELU', 'in': 256, 'k': 1, 'kt': 1, 'out': 512, 's': 1}]],
49 | 'space_arch': 'Cnn3DNet'}
--------------------------------------------------------------------------------
/configs/classification/MBV2_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/mbv2_flops300e6/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 224 # 224 for Imagenet, 480 for detection, 160 for mcu
11 |
12 | """ Model config """
13 | model = dict(
14 | type = 'CnnNet',
15 | structure_info =[\
16 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 16, 's': 2, 'k': 3}, \
17 | {'class': 'SuperResK1DWK1', 'in': 16, 'out': 24, 's': 2, 'k': 3, 'L': 1, 'btn': 48}, \
18 | {'class': 'SuperResK1DWK1', 'in': 24, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 96}, \
19 | {'class': 'SuperResK1DWK1', 'in': 48, 'out': 64, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
20 | {'class': 'SuperResK1DWK1', 'in': 64, 'out': 96, 's': 1, 'k': 3, 'L': 1, 'btn': 192}, \
21 | {'class': 'SuperResK1DWK1', 'in': 96, 'out': 192, 's': 2, 'k': 3, 'L': 1, 'btn': 384}, \
22 | {'class': 'ConvKXBNRELU', 'in': 192, 'out': 1280, 's': 1, 'k': 1}, \
23 | ]
24 | )
25 |
26 | """ Budget config """
27 | budgets = [
28 | dict(type = "flops", budget = 300e6),
29 | dict(type = "layers",budget = 53),
30 | ]
31 |
32 | """ Score config """
33 | score = dict(type = 'madnas', multi_block_ratio = [0,0,0,0,1])
34 |
35 | """ Space config """
36 | space = dict(
37 | type = 'space_k1dwk1',
38 | image_size = image_size,
39 | )
40 |
41 | """ Search config """
42 | search=dict(
43 | minor_mutation = False, # whether fix the stage layer
44 | minor_iter = 100000, # which iteration to enable minor_mutation
45 | popu_size = 256,
46 | num_random_nets = 100000, # the searching iterations
47 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
48 | num_network = 1,
49 | )
50 |
51 |
--------------------------------------------------------------------------------
/configs/classification/R50_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/R50_R224_FLOPs41e8/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 224 # 224 for Imagenet, 480 for detection, 160 for mcu
11 |
12 | """ Model config """
13 | model = dict(
14 | type = 'CnnNet',
15 | structure_info = [
16 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
17 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64}, \
18 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
19 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 768, 's': 2, 'k': 3, 'L': 1, 'btn': 256}, \
20 | {'class': 'SuperResK1KXK1', 'in': 768, 'out': 1024, 's': 1, 'k': 3, 'L': 1, 'btn': 256}, \
21 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, \
22 | ]
23 | )
24 |
25 | """ Budget config """
26 | budgets = [
27 | dict(type = "flops", budget = 41e8),
28 | dict(type = "layers",budget = 49),
29 | dict(type = "model_size", budget = 25.55e6)
30 | ]
31 |
32 | """ Score config """
33 | score = dict(type = 'madnas', multi_block_ratio = [0,0,0,0,1])
34 |
35 | """ Space config """
36 | space = dict(
37 | type = 'space_k1kxk1',
38 | image_size = image_size,
39 | )
40 |
41 | """ Search config """
42 | search=dict(
43 | minor_mutation = False, # whether fix the stage layer
44 | minor_iter = 100000, # which iteration to enable minor_mutation
45 | popu_size = 256,
46 | num_random_nets = 100000, # the searching iterations
47 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
48 | num_network = 1,
49 | )
50 |
51 |
--------------------------------------------------------------------------------
/configs/classification/README.md:
--------------------------------------------------------------------------------
1 | ## Abstract
2 |
3 | * **Instruction**
4 |
5 | In this folder, we provide the structure txt and parameters of the model searched by TinyNAS.
6 |
7 | * **Use the searching configs for Classification**
8 | ```shell
9 | sh tools/dist_search.sh configs/MBV2_FLOPs.py
10 | ```
11 | **`MBV2_FLOPs.py` is the config for searching MBV2-like model within the budget of FLOPs.**
12 |
13 | **`R50_FLOPs.py` is the config for searching R50-like model within the budget of FLOPs.**
14 |
15 | **`deepmad_R18_FLOPs.py` is the config for searching R18-like model within the budget of FLOPs using DeepMAD.**
16 |
17 | **`deepmad_R34_FLOPs.py` is the config for searching R34-like model within the budget of FLOPs using DeepMAD.**
18 |
19 | **`deepmad_R50_FLOPs.py` is the config for searching R50-like model within the budget of FLOPs using DeepMAD.**
20 |
21 | **`deepmad_29M_224.py` is the config for searching 29M SoTA model with 224 resolution within the budget of FLOPs using DeepMAD.**
22 |
23 | **`deepmad_29M_288.py` is the config for searching 29M SoTA model with 288 resolution within the budget of FLOPs using DeepMAD.**
24 |
25 | **`deepmad_50M.py` is the config for searching 50M SoTA model within the budget of FLOPs using DeepMAD.**
26 |
27 | **`deepmad_89M.py` is the config for searching 89M SoTA model within the budget of FLOPs using DeepMAD.**
28 |
29 |
30 | * **Use searched models in your own training pipeline**
31 |
32 | **copy `tinynas/deploy/cnnnet` to your pipeline, then**
33 | ```python
34 | from cnnnet import CnnNet
35 | # for classifictaion
36 | model = CnnNet(num_classes=classes,
37 | structure_txt=structure_txt,
38 | out_indices=(4,),
39 | classfication=True)
40 |
41 | # if load with pretrained model
42 | model.init_weights(pretrained=pretrained_pth)
43 | ```
44 | ***
45 |
46 | ## Results and Models
47 |
48 | | Backbone | size | Param (M) | FLOPs (G) | Top-1 | Structure | Download |
49 | |:---------:|:-------:|:-------:|:-------:|:-------:|:--------:|:------:|
50 | | R18-like | 224 | 10.8 | 1.7 | 78.44 | [txt](models/R18-like.txt) |[model](https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/TinyNAS/classfication/R18-like.pth.tar) |
51 | | R50-like | 224 | 21.3 | 3.6 | 80.04 | [txt](models/R50-like.txt) |[model](https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/TinyNAS/classfication/R50-like.pth.tar) |
52 | | R152-like | 224 | 53.5 | 10.5 | 81.59 | [txt](models/R152-like.txt) |[model](https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/TinyNAS/classfication/R152-like.pth.tar) |
53 |
54 |
55 | **Note**:
56 |
57 | 1. These models are trained on ImageNet dataset with 8 NVIDIA V100 GPUs.
58 | 2. Use SGD optimizer with momentum 0.9; weight decay 5e-5 for ImageNet; initial learning rate 0.1 with 480 epochs.
59 |
60 | ***
61 | ## Citation
62 |
63 | If you find this toolbox useful, please support us by citing this work as
64 | ```
65 | @inproceedings{cvpr2023deepmad,
66 | title = {DeepMAD: Mathematical Architecture Design for Deep Convolutional Neural Network},
67 | author = {Xuan Shen, Yaohua Wang, Ming Lin, Dylan Huang, Hao Tang, Xiuyu Sun, Yanzhi Wang},
68 | booktitle = {Conference on Computer Vision and Pattern Recognition 2023},
69 | year = {2023},
70 | url = {https://arxiv.org/abs/2303.02165}
71 | }
72 | ```
73 |
74 | ```
75 | @inproceedings{zennas,
76 | title = {Zen-NAS: A Zero-Shot NAS for High-Performance Deep Image Recognition},
77 | author = {Ming Lin and Pichao Wang and Zhenhong Sun and Hesen Chen and Xiuyu Sun and Qi Qian and Hao Li and Rong Jin},
78 | booktitle = {2021 IEEE/CVF International Conference on Computer Vision},
79 | year = {2021},
80 | }
81 | ```
82 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_29M_224.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad-29M-224/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 224
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1DWSEK1', 'in': 32, 'out': 72, 's': 2, 'k': 3, 'L': 1, 'btn': 432}, \
19 | {'class': 'SuperResK1DWSEK1', 'in': 72, 'out': 128, 's': 2, 'k': 3, 'L': 1, 'btn': 768}, \
20 | {'class': 'SuperResK1DWSEK1', 'in': 128, 'out': 192, 's': 2, 'k': 3, 'L': 1, 'btn': 1152}, \
21 | {'class': 'SuperResK1DWSEK1', 'in': 192, 'out': 288, 's': 2, 'k': 3, 'L': 1, 'btn': 1728}, \
22 | {'class': 'SuperResK1DWSEK1', 'in': 288, 'out': 448, 's': 1, 'k': 3, 'L': 1, 'btn': 2688}, \
23 | {'class': 'ConvKXBNRELU', 'in': 448, 'out': 1792, 's': 1, 'k': 1}, \
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 4.5e9),
30 | dict(type = "model_size", budget = 29e6),
31 | dict(type = "efficient_score", budget = 0.5)
32 | ]
33 |
34 | """ Score config """
35 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
36 |
37 | """ Space config """
38 | space = dict(
39 | type = 'space_k1dwsek1',
40 | image_size = image_size,
41 | )
42 |
43 | """ Search config """
44 | search=dict(
45 | minor_mutation = False, # whether fix the stage layer
46 | minor_iter = 100000, # which iteration to enable minor_mutation
47 | popu_size = 256,
48 | num_random_nets = 500000, # the searching iterations
49 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
50 | num_network = 1,
51 | )
52 |
53 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_29M_288.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad_29M_288/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 288
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 16, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1DWSEK1', 'in': 16, 'out': 32, 's': 2, 'k': 3, 'L': 1, 'btn': 192}, \
19 | {'class': 'SuperResK1DWSEK1', 'in': 32, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 288}, \
20 | {'class': 'SuperResK1DWSEK1', 'in': 48, 'out': 72, 's': 2, 'k': 3, 'L': 1, 'btn': 432}, \
21 | {'class': 'SuperResK1DWSEK1', 'in': 72, 'out': 108, 's': 1, 'k': 3, 'L': 1, 'btn': 648}, \
22 | {'class': 'SuperResK1DWSEK1', 'in': 108, 'out': 162, 's': 2, 'k': 3, 'L': 1, 'btn': 972}, \
23 | {'class': 'ConvKXBNRELU', 'in': 162, 'out': 1792, 's': 1, 'k': 1}, \
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 4.5e9),
30 | dict(type = "model_size", budget = 29e6),
31 | dict(type = "efficient_score", budget = 0.5)
32 | ]
33 |
34 | """ Score config """
35 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
36 |
37 | """ Space config """
38 | space = dict(
39 | type = 'space_k1dwsek1',
40 | image_size = image_size,
41 | )
42 |
43 | """ Search config """
44 | search=dict(
45 | minor_mutation = False, # whether fix the stage layer
46 | minor_iter = 100000, # which iteration to enable minor_mutation
47 | popu_size = 256,
48 | num_random_nets = 500000, # the searching iterations
49 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
50 | num_network = 1,
51 | )
52 |
53 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_50M.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad_50M/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 224
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 48, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1DWSEK1', 'in': 48, 'out':84, 's': 2, 'k': 3, 'L': 1, 'btn': 504}, \
19 | {'class': 'SuperResK1DWSEK1', 'in': 84, 'out': 144, 's': 2, 'k': 3, 'L': 1, 'btn': 864}, \
20 | {'class': 'SuperResK1DWSEK1', 'in': 144, 'out': 216, 's': 2, 'k': 3, 'L': 1, 'btn': 1296}, \
21 | {'class': 'SuperResK1DWSEK1', 'in': 216, 'out': 324, 's': 2, 'k': 3, 'L': 1, 'btn': 1944}, \
22 | {'class': 'SuperResK1DWSEK1', 'in': 324, 'out': 512, 's': 1, 'k': 3, 'L': 1, 'btn': 3072}, \
23 | {'class': 'ConvKXBNRELU', 'in': 512, 'out': 2048, 's': 1, 'k': 1}, \
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 8.7e9),
30 | dict(type = "model_size", budget = 50e6),
31 | dict(type = "efficient_score", budget = 0.5)
32 | ]
33 |
34 | """ Score config """
35 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
36 |
37 | """ Space config """
38 | space = dict(
39 | type = 'space_k1dwsek1',
40 | image_size = image_size,
41 | )
42 |
43 | """ Search config """
44 | search=dict(
45 | minor_mutation = False, # whether fix the stage layer
46 | minor_iter = 100000, # which iteration to enable minor_mutation
47 | popu_size = 256,
48 | num_random_nets = 500000, # the searching iterations
49 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
50 | num_network = 1,
51 | )
52 |
53 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_89M.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad_89M/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 224
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 64, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1DWSEK1', 'in': 64, 'out': 144, 's': 2, 'k': 3, 'L': 1, 'btn': 865}, \
19 | {'class': 'SuperResK1DWSEK1', 'in': 144, 'out': 216, 's': 2, 'k': 3, 'L': 1, 'btn': 1296}, \
20 | {'class': 'SuperResK1DWSEK1', 'in': 216, 'out': 324, 's': 2, 'k': 3, 'L': 1, 'btn': 1944}, \
21 | {'class': 'SuperResK1DWSEK1', 'in': 324, 'out': 486, 's': 2, 'k': 3, 'L': 1, 'btn': 2916}, \
22 | {'class': 'SuperResK1DWSEK1', 'in': 486, 'out': 729, 's': 1, 'k': 3, 'L': 1, 'btn': 4374}, \
23 | {'class': 'ConvKXBNRELU', 'in': 729, 'out': 2560, 's': 1, 'k': 1}, \
24 | ]
25 | )
26 |
27 | """ Budget config """
28 | budgets = [
29 | dict(type = "flops", budget = 15.4e9),
30 | dict(type = "model_size", budget = 89e6),
31 | dict(type = "efficient_score", budget = 0.5)
32 | ]
33 |
34 | """ Score config """
35 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
36 |
37 | """ Space config """
38 | space = dict(
39 | type = 'space_k1dwsek1',
40 | image_size = image_size,
41 | )
42 |
43 | """ Search config """
44 | search=dict(
45 | minor_mutation = False, # whether fix the stage layer
46 | minor_iter = 100000, # which iteration to enable minor_mutation
47 | popu_size = 256,
48 | num_random_nets = 500000, # the searching iterations
49 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
50 | num_network = 1,
51 | )
52 |
53 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_R18_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad_R18/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 224
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64}, \
19 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
20 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 768, 's': 2, 'k': 3, 'L': 1, 'btn': 256}, \
21 | {'class': 'SuperResK1KXK1', 'in': 768, 'out': 1024, 's': 1, 'k': 3, 'L': 1, 'btn': 256}, \
22 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, \
23 | ]
24 | )
25 |
26 | """ Budget config """
27 | budgets = [
28 | dict(type = "flops", budget = 1.82e9),
29 | dict(type = "model_size", budget = 11.69e6),
30 | dict(type = "efficient_score", budget = 0.3)
31 | ]
32 |
33 | """ Score config """
34 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
35 |
36 | """ Space config """
37 | space = dict(
38 | type = 'space_k1kxk1',
39 | image_size = image_size,
40 | )
41 |
42 | """ Search config """
43 | search=dict(
44 | minor_mutation = False, # whether fix the stage layer
45 | minor_iter = 100000, # which iteration to enable minor_mutation
46 | popu_size = 256,
47 | num_random_nets = 500000, # the searching iterations
48 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
49 | num_network = 1,
50 | )
51 |
52 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_R34_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad_R34/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 224
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64}, \
19 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
20 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 768, 's': 2, 'k': 3, 'L': 1, 'btn': 256}, \
21 | {'class': 'SuperResK1KXK1', 'in': 768, 'out': 1024, 's': 1, 'k': 3, 'L': 1, 'btn': 256}, \
22 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, \
23 | ]
24 | )
25 |
26 | """ Budget config """
27 | budgets = [
28 | dict(type = "flops", budget = 3.68e9),
29 | dict(type = "model_size", budget = 21.80e6),
30 | dict(type = "efficient_score", budget = 0.3)
31 | ]
32 |
33 | """ Score config """
34 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
35 |
36 | """ Space config """
37 | space = dict(
38 | type = 'space_k1kxk1',
39 | image_size = image_size,
40 | )
41 |
42 | """ Search config """
43 | search=dict(
44 | minor_mutation = False, # whether fix the stage layer
45 | minor_iter = 100000, # which iteration to enable minor_mutation
46 | popu_size = 256,
47 | num_random_nets = 500000, # the searching iterations
48 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
49 | num_network = 1,
50 | )
51 |
52 |
--------------------------------------------------------------------------------
/configs/classification/deepmad_R50_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | # The DeepMAD method is from the paper https://arxiv.org/abs/2303.02165 of Alibaba.
5 |
6 | work_dir = './save_model/deepmad_R50/'
7 | log_level = 'INFO' # INFO/DEBUG/ERROR
8 | log_freq = 1000
9 |
10 | """ image config """
11 | image_size = 224
12 |
13 | """ Model config """
14 | model = dict(
15 | type = 'CnnNet',
16 | structure_info = [
17 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
18 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64}, \
19 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
20 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 768, 's': 2, 'k': 3, 'L': 1, 'btn': 256}, \
21 | {'class': 'SuperResK1KXK1', 'in': 768, 'out': 1024, 's': 1, 'k': 3, 'L': 1, 'btn': 256}, \
22 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, \
23 | ]
24 | )
25 |
26 | """ Budget config """
27 | budgets = [
28 | dict(type = "flops", budget = 4.13e9),
29 | dict(type = "model_size", budget = 25.55e6),
30 | dict(type = "efficient_score", budget = 0.3)
31 | ]
32 |
33 | """ Score config """
34 | score = dict(type = 'deepmad', multi_block_ratio = [1,1,1,1,8], alpha1=1, alpha2=1, depth_penalty_ratio=10.)
35 |
36 | """ Space config """
37 | space = dict(
38 | type = 'space_k1kxk1',
39 | image_size = image_size,
40 | )
41 |
42 | """ Search config """
43 | search=dict(
44 | minor_mutation = False, # whether fix the stage layer
45 | minor_iter = 100000, # which iteration to enable minor_mutation
46 | popu_size = 256,
47 | num_random_nets = 500000, # the searching iterations
48 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
49 | num_network = 1,
50 | )
51 |
52 |
--------------------------------------------------------------------------------
/configs/classification/models/R152-like.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 128, 's': 2},
3 | { 'L': 4,
4 | 'btn': 88,
5 | 'class': 'SuperResK1KXK1',
6 | 'in': 128,
7 | 'k': 3,
8 | 'out': 512,
9 | 's': 2},
10 | { 'L': 8,
11 | 'btn': 176,
12 | 'class': 'SuperResK1KXK1',
13 | 'in': 512,
14 | 'k': 3,
15 | 'out': 720,
16 | 's': 2},
17 | { 'L': 13,
18 | 'btn': 256,
19 | 'class': 'SuperResK1KXK1',
20 | 'in': 720,
21 | 'k': 3,
22 | 'out': 720,
23 | 's': 2},
24 | { 'L': 10,
25 | 'btn': 360,
26 | 'class': 'SuperResK1KXK1',
27 | 'in': 720,
28 | 'k': 3,
29 | 'out': 1024,
30 | 's': 2},
31 | { 'L': 12,
32 | 'btn': 256,
33 | 'class': 'SuperResK1KXK1',
34 | 'in': 1024,
35 | 'k': 3,
36 | 'out': 1024,
37 | 's': 1}]],
38 | 'space_arch': 'CnnNet'}
--------------------------------------------------------------------------------
/configs/classification/models/R18-like.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 40, 's': 2},
3 | { 'L': 2,
4 | 'btn': 64,
5 | 'class': 'SuperResK1KXK1',
6 | 'in': 40,
7 | 'k': 3,
8 | 'out': 256,
9 | 's': 2},
10 | { 'L': 3,
11 | 'btn': 88,
12 | 'class': 'SuperResK1KXK1',
13 | 'in': 256,
14 | 'k': 3,
15 | 'out': 360,
16 | 's': 2},
17 | { 'L': 6,
18 | 'btn': 128,
19 | 'class': 'SuperResK1KXK1',
20 | 'in': 360,
21 | 'k': 3,
22 | 'out': 512,
23 | 's': 2},
24 | { 'L': 4,
25 | 'btn': 176,
26 | 'class': 'SuperResK1KXK1',
27 | 'in': 512,
28 | 'k': 3,
29 | 'out': 512,
30 | 's': 2},
31 | { 'L': 12,
32 | 'btn': 176,
33 | 'class': 'SuperResK1KXK1',
34 | 'in': 512,
35 | 'k': 3,
36 | 'out': 512,
37 | 's': 1}]],
38 | 'space_arch': 'CnnNet'}
--------------------------------------------------------------------------------
/configs/classification/models/R50-like.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 16, 's': 2},
3 | { 'L': 6,
4 | 'btn': 64,
5 | 'class': 'SuperResK1KXK1',
6 | 'in': 16,
7 | 'k': 3,
8 | 'out': 256,
9 | 's': 2},
10 | { 'L': 8,
11 | 'btn': 88,
12 | 'class': 'SuperResK1KXK1',
13 | 'in': 256,
14 | 'k': 3,
15 | 'out': 360,
16 | 's': 2},
17 | { 'L': 7,
18 | 'btn': 176,
19 | 'class': 'SuperResK1KXK1',
20 | 'in': 360,
21 | 'k': 3,
22 | 'out': 512,
23 | 's': 2},
24 | { 'L': 2,
25 | 'btn': 360,
26 | 'class': 'SuperResK1KXK1',
27 | 'in': 512,
28 | 'k': 3,
29 | 'out': 720,
30 | 's': 2},
31 | { 'L': 4,
32 | 'btn': 256,
33 | 'class': 'SuperResK1KXK1',
34 | 'in': 720,
35 | 'k': 3,
36 | 'out': 2896,
37 | 's': 1}]],
38 | 'space_arch': 'CnnNet'}
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-29M-224.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 40, 's': 2},
3 | { 'L': 2, 'btn': 240, 'class': 'SuperResK1DWSEK1', 'in': 40, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 40, 's': 1},
4 | { 'L': 4, 'btn': 512, 'class': 'SuperResK1DWSEK1', 'in': 40, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 85, 's': 2},
5 | { 'L': 6, 'btn': 800, 'class': 'SuperResK1DWSEK1', 'in': 85, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 134, 's': 2},
6 | { 'L': 6, 'btn': 1208, 'class': 'SuperResK1DWSEK1', 'in': 134, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 201, 's': 2},
7 | { 'L': 5, 'btn': 1872, 'class': 'SuperResK1DWSEK1', 'in': 201, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 312, 's': 2},
8 | {'class': 'ConvKXBNRELU', 'in': 312, 'k': 1, 'out': 1792, 's': 1}]],
9 | 'space_arch': 'CnnNet'}
10 |
11 |
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-29M-288.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 40, 's': 2},
3 | { 'L': 4,
4 | 'btn': 368,
5 | 'class': 'SuperResK1DWSEK1',
6 | 'in': 40,
7 | 'inner_class': 'ResK1DWSEK1',
8 | 'k': 5,
9 | 'out': 61,
10 | 's': 2},
11 | { 'L': 4,
12 | 'btn': 576,
13 | 'class': 'SuperResK1DWSEK1',
14 | 'in': 61,
15 | 'inner_class': 'ResK1DWSEK1',
16 | 'k': 5,
17 | 'out': 96,
18 | 's': 2},
19 | { 'L': 5,
20 | 'btn': 872,
21 | 'class': 'SuperResK1DWSEK1',
22 | 'in': 96,
23 | 'inner_class': 'ResK1DWSEK1',
24 | 'k': 5,
25 | 'out': 145,
26 | 's': 2},
27 | { 'L': 6,
28 | 'btn': 1304,
29 | 'class': 'SuperResK1DWSEK1',
30 | 'in': 145,
31 | 'inner_class': 'ResK1DWSEK1',
32 | 'k': 5,
33 | 'out': 217,
34 | 's': 1},
35 | { 'L': 4,
36 | 'btn': 1968,
37 | 'class': 'SuperResK1DWSEK1',
38 | 'in': 217,
39 | 'inner_class': 'ResK1DWSEK1',
40 | 'k': 5,
41 | 'out': 328,
42 | 's': 2},
43 | {'class': 'ConvKXBNRELU', 'in': 328, 'k': 1, 'out': 1792, 's': 1}]],
44 | 'space_arch': 'CnnNet'}
45 |
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-50M.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 48, 's': 2},
3 | {'L': 7, 'btn': 672, 'class': 'SuperResK1DWSEK1', 'in': 48, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 112, 's': 2},
4 | {'L': 9, 'btn': 1008, 'class': 'SuperResK1DWSEK1', 'in': 112, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 168, 's': 2},
5 | {'L': 7, 'btn': 1512, 'class': 'SuperResK1DWSEK1', 'in': 168, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 252, 's': 2},
6 | {'L': 3, 'btn': 2272, 'class': 'SuperResK1DWSEK1', 'in': 252, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 378, 's': 2},
7 | {'L': 1, 'btn': 3456, 'class': 'SuperResK1DWSEK1', 'in': 378, 'inner_class': 'ResK1DWSEK1', 'k': 3, 'out': 576, 's': 1},
8 | {'class': 'ConvKXBNRELU', 'in': 576, 'k': 1, 'out': 2048, 's': 1}]],
9 | 'space_arch': 'CnnNet'}
10 |
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-89M.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 56, 's': 2},
3 | {'L': 10, 'btn': 816, 'class': 'SuperResK1DWSEK1', 'in': 56, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 136, 's': 2},
4 | {'L': 9, 'btn': 1224, 'class': 'SuperResK1DWSEK1', 'in': 136, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 204, 's': 2},
5 | {'L': 7, 'btn': 1952, 'class': 'SuperResK1DWSEK1', 'in': 204, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 326, 's': 2},
6 | {'L': 4, 'btn': 2944, 'class': 'SuperResK1DWSEK1', 'in': 326, 'inner_class': 'ResK1DWSEK1', 'k': 5, 'out': 490, 's': 2},
7 | {'L': 1, 'btn': 4464, 'class': 'SuperResK1DWSEK1', 'in': 490, 'inner_class': 'ResK1DWSEK1', 'k': 3, 'out': 744, 's': 1},
8 | {'class': 'ConvKXBNRELU', 'in': 744, 'k': 1, 'out': 2560, 's': 1}]],
9 | 'space_arch': 'CnnNet'}
10 |
11 |
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-R18.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 32, 's': 2},
3 | { 'L': 1, 'btn': 40, 'class': 'SuperResK1KXK1', 'in': 32, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 96, 's': 2},
4 | { 'L': 6, 'btn': 40, 'class': 'SuperResK1KXK1', 'in': 96, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 384, 's': 2},
5 | { 'L': 9, 'btn': 64, 'class': 'SuperResK1KXK1', 'in': 384, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 384, 's': 2},
6 | { 'L': 10, 'btn': 104, 'class': 'SuperResK1KXK1', 'in': 384, 'inner_class': 'ResK1KXK1', 'k': 3, 'out': 1024, 's': 1},
7 | { 'L': 12, 'btn': 104, 'class': 'SuperResK1KXK1', 'in': 1024, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 672, 's': 2}]],
8 | 'space_arch': 'CnnNet'}
9 |
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-R34.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 24, 's': 2},
3 | { 'L': 1, 'btn': 24, 'class': 'SuperResK1KXK1', 'in': 24, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 128, 's': 2},
4 | { 'L': 10, 'btn': 48, 'class': 'SuperResK1KXK1', 'in': 128, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 512, 's': 2},
5 | { 'L': 13, 'btn': 88, 'class': 'SuperResK1KXK1', 'in': 512, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 896, 's': 2},
6 | { 'L': 11, 'btn': 104, 'class': 'SuperResK1KXK1', 'in': 896, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 1024, 's': 1},
7 | { 'L': 14, 'btn': 128, 'class': 'SuperResK1KXK1', 'in': 1024, 'inner_class': 'ResK1KXK1', 'k': 5, 'out': 616, 's': 2}]],
8 | 'space_arch': 'CnnNet'}
--------------------------------------------------------------------------------
/configs/classification/models/deepmad-R50.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'out': 32, 's': 2},
3 | { 'L': 1,
4 | 'btn': 40,
5 | 'class': 'SuperResK1KXK1',
6 | 'in': 32,
7 | 'inner_class': 'ResK1KXK1',
8 | 'k': 5,
9 | 'out': 128,
10 | 's': 2},
11 | { 'L': 11,
12 | 'btn': 48,
13 | 'class': 'SuperResK1KXK1',
14 | 'in': 128,
15 | 'inner_class': 'ResK1KXK1',
16 | 'k': 5,
17 | 'out': 512,
18 | 's': 2},
19 | { 'L': 12,
20 | 'btn': 88,
21 | 'class': 'SuperResK1KXK1',
22 | 'in': 512,
23 | 'inner_class': 'ResK1KXK1',
24 | 'k': 5,
25 | 'out': 872,
26 | 's': 2},
27 | { 'L': 13,
28 | 'btn': 104,
29 | 'class': 'SuperResK1KXK1',
30 | 'in': 872,
31 | 'inner_class': 'ResK1KXK1',
32 | 'k': 5,
33 | 'out': 1024,
34 | 's': 1},
35 | { 'L': 15,
36 | 'btn': 120,
37 | 'class': 'SuperResK1KXK1',
38 | 'in': 1024,
39 | 'inner_class': 'ResK1KXK1',
40 | 'k': 5,
41 | 'out': 1232,
42 | 's': 2}]],
43 | 'space_arch': 'CnnNet'}
44 |
--------------------------------------------------------------------------------
/configs/damoyolo/damoyolo_k1kx_small.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/k1kx_R640_layers25_lat12e-5/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 | """ image config """
9 | image_size = 320 # 224 for Imagenet, 160 for mcu
10 |
11 | """ Model config """
12 | model = dict(
13 | type = 'CnnNet',
14 | structure_info = [
15 | {'class': 'ConvKXBNRELU', 'in': 12, 'out': 32, 's': 1, 'k': 3},
16 | {'class': 'SuperResK1KX', 'in': 32, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 32},
17 | {'class': 'SuperResK1KX', 'in': 48, 'out': 96, 's': 2, 'k': 3, 'L': 1, 'btn': 48},
18 | {'class': 'SuperResK1KX', 'in': 96, 'out': 96, 's': 2, 'k': 3, 'L': 1, 'btn': 96},
19 | {'class': 'SuperResK1KX', 'in': 96, 'out': 192, 's': 1, 'k': 3, 'L': 1, 'btn': 96},
20 | {'class': 'SuperResK1KX', 'in': 192, 'out': 384, 's': 2, 'k': 3, 'L': 1, 'btn': 192},
21 | ]
22 | )
23 |
24 | """ Latency config """
25 | latency = dict(
26 | type = 'OpPredictor',
27 | data_type = "FP16_DAMOYOLO",
28 | batch_size = 32,
29 | image_size = image_size,
30 | )
31 |
32 | """ Budget config """
33 | budgets = [
34 | dict(type = "layers",budget = 25),
35 | dict(type = "latency", budget = 12e-5)
36 | ]
37 |
38 | """ Score config """
39 | score = dict(type = 'madnas', multi_block_ratio = [0,0,1,1,16])
40 |
41 | """ Space config """
42 | space = dict(
43 | type = 'space_k1kx',
44 | image_size = image_size,
45 | channel_range_list = [None, None, [64, 128], None, [128, 256], [256, 512]],
46 | kernel_size_list = [3],
47 |
48 | )
49 |
50 | """ Search config """
51 | search=dict(
52 | minor_mutation = False, # whether fix the stage layer
53 | minor_iter = 100000, # which iteration to enable minor_mutation
54 | popu_size = 512,
55 | num_random_nets = 500000, # the searching iterations
56 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
57 | num_network = 1,
58 | )
59 |
60 |
--------------------------------------------------------------------------------
/configs/damoyolo/damoyolo_k1kx_tiny.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/k1kx_R640_layers25_lat8e-5/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 |
8 | """ image config """
9 | image_size = 320 # 224 for Imagenet, 160 for mcu
10 |
11 | """ Model config """
12 | model = dict(
13 | type = 'CnnNet',
14 | structure_info = [
15 | {'class': 'ConvKXBNRELU', 'in': 12, 'out': 32, 's': 1, 'k': 3},
16 | {'class': 'SuperResK1KX', 'in': 32, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 32},
17 | {'class': 'SuperResK1KX', 'in': 48, 'out': 96, 's': 2, 'k': 3, 'L': 1, 'btn': 48},
18 | {'class': 'SuperResK1KX', 'in': 96, 'out': 96, 's': 2, 'k': 3, 'L': 1, 'btn': 96},
19 | {'class': 'SuperResK1KX', 'in': 96, 'out': 192, 's': 1, 'k': 3, 'L': 1, 'btn': 96},
20 | {'class': 'SuperResK1KX', 'in': 192, 'out': 384, 's': 2, 'k': 3, 'L': 1, 'btn': 192},
21 | ]
22 | )
23 |
24 | """ Latency config """
25 | latency = dict(
26 | type = 'OpPredictor',
27 | data_type = "FP16_DAMOYOLO",
28 | batch_size = 32,
29 | image_size = image_size,
30 | )
31 |
32 | """ Budget config """
33 | budgets = [
34 | dict(type = "layers",budget = 20),
35 | dict(type = "latency", budget = 8e-5)
36 | ]
37 |
38 | """ Score config """
39 | score = dict(type = 'madnas', multi_block_ratio = [0,0,1,1,16])
40 |
41 | """ Space config """
42 | space = dict(
43 | type = 'space_k1kx',
44 | image_size = image_size,
45 | channel_range_list = [None, None, [64, 96], None, [128, 192], [256, 384]],
46 | kernel_size_list = [3],
47 | )
48 |
49 | """ Search config """
50 | search=dict(
51 | minor_mutation = False, # whether fix the stage layer
52 | minor_iter = 100000, # which iteration to enable minor_mutation
53 | popu_size = 512,
54 | num_random_nets = 500000, # the searching iterations
55 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
56 | num_network = 1,
57 | )
58 |
59 |
--------------------------------------------------------------------------------
/configs/damoyolo/damoyolo_kxkx_medium.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/kxkx_R640_layers20_lat4e-4/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 320 # 224 for Imagenet, 160 for mcu
11 |
12 | """ Model config """
13 | model = dict(
14 | type = 'CnnNet',
15 | structure_info = [
16 | {'class': 'ConvKXBNRELU', 'in': 12, 'out': 32, 's': 1, 'k': 3},
17 | {'class': 'SuperResKXKX', 'in': 32, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 32},
18 | {'class': 'SuperResKXKX', 'in': 48, 'out': 96, 's': 2, 'k': 3, 'L': 1, 'btn': 48},
19 | {'class': 'SuperResKXKX', 'in': 96, 'out': 96, 's': 2, 'k': 3, 'L': 1, 'btn': 96},
20 | {'class': 'SuperResKXKX', 'in': 96, 'out': 192, 's': 1, 'k': 3, 'L': 1, 'btn': 96},
21 | {'class': 'SuperResKXKX', 'in': 192, 'out': 384, 's': 2, 'k': 3, 'L': 1, 'btn': 192},
22 | ]
23 | )
24 |
25 | """ Latency config """
26 | latency = dict(
27 | type = 'OpPredictor',
28 | data_type = "FP16_DAMOYOLO",
29 | batch_size = 32,
30 | image_size = image_size,
31 | )
32 |
33 | """ Budget config """
34 | budgets = [
35 | dict(type = "layers",budget = 20),
36 | dict(type = "latency", budget = 4e-4)
37 | ]
38 |
39 | """ Score config """
40 | score = dict(type = 'madnas', multi_block_ratio = [0,0,1,1,16])
41 |
42 | """ Space config """
43 | space = dict(
44 | type = 'space_kxkx',
45 | image_size = image_size,
46 | channel_range_list = [None, None, [64, 128], None, [128, 256], [256, 512]],
47 | kernel_size_list = [3],
48 | )
49 |
50 | """ Search config """
51 | search=dict(
52 | minor_mutation = False, # whether fix the stage layer
53 | minor_iter = 100000, # which iteration to enable minor_mutation
54 | popu_size = 512,
55 | num_random_nets = 500000, # the searching iterations
56 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
57 | num_network = 1,
58 | )
59 |
60 |
--------------------------------------------------------------------------------
/configs/detection/R50_FLOPs.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/R50_R480_FLOPs188e8/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 480 # 224 for Imagenet, 480 for detection, 160 for mcu
11 |
12 | """ Model config """
13 | model = dict(
14 | type = 'CnnNet',
15 | structure_info = [
16 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
17 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64}, \
18 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
19 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 768, 's': 2, 'k': 3, 'L': 1, 'btn': 256}, \
20 | {'class': 'SuperResK1KXK1', 'in': 768, 'out': 1024, 's': 1, 'k': 3, 'L': 1, 'btn': 256}, \
21 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, \
22 | ]
23 | )
24 |
25 | """ Budget config """
26 | budgets = [
27 | dict(type = "flops", budget = 188e8),
28 | dict(type = "layers",budget = 91),
29 | ]
30 |
31 | """ Score config """
32 | score = dict(type = 'madnas', multi_block_ratio = [0,0,1,1,6])
33 |
34 | """ Space config """
35 | space = dict(
36 | type = 'space_k1kxk1',
37 | image_size = image_size,
38 | )
39 |
40 | """ Search config """
41 | search=dict(
42 | minor_mutation = False, # whether fix the stage layer
43 | minor_iter = 100000, # which iteration to enable minor_mutation
44 | popu_size = 256,
45 | num_random_nets = 100000, # the searching iterations
46 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
47 | num_network = 1,
48 | )
49 |
50 |
--------------------------------------------------------------------------------
/configs/detection/R50_FLOPs_predictor.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/R50_R480_FLOPs188e8_predictor/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 480 # 224 for Imagenet, 480 for detection, 160 for mcu
11 |
12 | """ Model config """
13 | model = dict(
14 | type = 'CnnNet',
15 | structure_info = [
16 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3}, \
17 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64}, \
18 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128}, \
19 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 768, 's': 2, 'k': 3, 'L': 1, 'btn': 256}, \
20 | {'class': 'SuperResK1KXK1', 'in': 768, 'out': 1024, 's': 1, 'k': 3, 'L': 1, 'btn': 256}, \
21 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, \
22 | ]
23 | )
24 |
25 | """ Latency config """
26 | latency = dict(
27 | type = 'OpPredictor',
28 | data_type = "FP16",
29 | batch_size = 32,
30 | image_size = image_size,
31 | )
32 |
33 | """ Budget config """
34 | budgets = [
35 | dict(type = "flops", budget = 188e8),
36 | dict(type = "latency", budget = 8e-4),
37 | dict(type = "layers",budget = 91),
38 | ]
39 |
40 | """ Score config """
41 | score = dict(type = 'madnas', multi_block_ratio = [0,0,1,1,6])
42 |
43 | """ Space config """
44 | space = dict(
45 | type = 'space_k1kxk1',
46 | image_size = image_size,
47 | )
48 |
49 | """ Search config """
50 | search=dict(
51 | minor_mutation = False, # whether fix the stage layer
52 | minor_iter = 100000, # which iteration to enable minor_mutation
53 | popu_size = 256,
54 | num_random_nets = 100000, # the searching iterations
55 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
56 | num_network = 1,
57 | )
58 |
59 |
--------------------------------------------------------------------------------
/configs/detection/models/gfocal_maedet/maedet_l_6x_lr0.02.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2021-2022 Alibaba Group Holding Limited.
2 |
3 | _base_ = 'gfocal_r50_fpn_ms6x.py'
4 | # model settings
5 | model = dict(
6 | backbone=dict(
7 | type='MadNas',
8 | net_str="configs/gfocal_madnas/maedet_l.txt",
9 | out_indices=(1,2,3,4),
10 | init_cfg=None), # if load pretrained model, fill the path of the pth file.
11 | neck=dict(
12 | type='FPN',
13 | in_channels=[144, 608, 1912, 2400],
14 | out_channels=256,
15 | start_level=1,
16 | add_extra_convs='on_output', # use P5
17 | num_outs=5),
18 | )
19 | # training and testing settings
20 | img_norm_cfg = dict(
21 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
22 | train_pipeline = [
23 | dict(type='LoadImageFromFile'),
24 | dict(type='LoadAnnotations', with_bbox=True),
25 | dict(
26 | type='Resize',
27 | img_scale=[(1333, 480), (1333, 960)],
28 | multiscale_mode='range',
29 | keep_ratio=True),
30 | dict(type='RandomFlip', flip_ratio=0.5),
31 | dict(type='Normalize', **img_norm_cfg),
32 | dict(type='Pad', size_divisor=32),
33 | dict(type='DefaultFormatBundle'),
34 | dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
35 | ]
36 | test_pipeline = [
37 | dict(type='LoadImageFromFile'),
38 | dict(
39 | type='MultiScaleFlipAug',
40 | img_scale=(1333, 800),
41 | flip=False,
42 | transforms=[
43 | dict(type='Resize', keep_ratio=True),
44 | dict(type='RandomFlip'),
45 | dict(type='Normalize', **img_norm_cfg),
46 | dict(type='Pad', size_divisor=32),
47 | dict(type='ImageToTensor', keys=['img']),
48 | dict(type='Collect', keys=['img']),
49 | ])
50 | ]
51 | data = dict(
52 | train=dict(pipeline=train_pipeline),
53 | val=dict(pipeline=test_pipeline),
54 | test=dict(pipeline=test_pipeline))
55 | # optimizer
56 | optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
57 |
58 | # learning policy
59 | lr_config = dict(
60 | warmup='linear',
61 | warmup_iters=7330,
62 | warmup_ratio=0.1,
63 | step=[65, 71])
64 | total_epochs = 73
65 | use_syncBN_torch = True
--------------------------------------------------------------------------------
/configs/detection/models/gfocal_maedet/maedet_m_6x_lr0.02.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2021-2022 Alibaba Group Holding Limited.
2 |
3 | _base_ = 'gfocal_r50_fpn_ms6x.py'
4 | # model settings
5 | model = dict(
6 | backbone=dict(
7 | type='MadNas',
8 | net_str="configs/gfocal_madnas/maedet_m.txt",
9 | out_indices=(1,2,3,4),
10 | init_cfg=None), # if load pretrained model, fill the path of the pth file.
11 | neck=dict(
12 | type='FPN',
13 | in_channels=[120, 512, 1632, 2048],
14 | out_channels=256,
15 | start_level=1,
16 | add_extra_convs='on_output', # use P5
17 | num_outs=5),
18 | )
19 | # training and testing settings
20 | img_norm_cfg = dict(
21 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
22 | train_pipeline = [
23 | dict(type='LoadImageFromFile'),
24 | dict(type='LoadAnnotations', with_bbox=True),
25 | dict(
26 | type='Resize',
27 | img_scale=[(1333, 480), (1333, 960)],
28 | multiscale_mode='range',
29 | keep_ratio=True),
30 | dict(type='RandomFlip', flip_ratio=0.5),
31 | dict(type='Normalize', **img_norm_cfg),
32 | dict(type='Pad', size_divisor=32),
33 | dict(type='DefaultFormatBundle'),
34 | dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
35 | ]
36 | test_pipeline = [
37 | dict(type='LoadImageFromFile'),
38 | dict(
39 | type='MultiScaleFlipAug',
40 | img_scale=(1333, 800),
41 | flip=False,
42 | transforms=[
43 | dict(type='Resize', keep_ratio=True),
44 | dict(type='RandomFlip'),
45 | dict(type='Normalize', **img_norm_cfg),
46 | dict(type='Pad', size_divisor=32),
47 | dict(type='ImageToTensor', keys=['img']),
48 | dict(type='Collect', keys=['img']),
49 | ])
50 | ]
51 | data = dict(
52 | train=dict(pipeline=train_pipeline),
53 | val=dict(pipeline=test_pipeline),
54 | test=dict(pipeline=test_pipeline))
55 | # optimizer
56 | optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
57 |
58 | # learning policy
59 | lr_config = dict(
60 | warmup='linear',
61 | warmup_iters=7330,
62 | warmup_ratio=0.1,
63 | step=[65, 71])
64 | total_epochs = 73
65 | use_syncBN_torch = True
--------------------------------------------------------------------------------
/configs/detection/models/gfocal_maedet/maedet_s_6x_lr0.02.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2021-2022 Alibaba Group Holding Limited.
2 |
3 | _base_ = 'gfocal_r50_fpn_ms6x.py'
4 | # model settings
5 | model = dict(
6 | backbone=dict(
7 | type='MadNas',
8 | net_str="configs/gfocal_madnas/maedet_s.txt",
9 | out_indices=(1,2,3,4),
10 | init_cfg=None), # if load pretrained model, fill the path of the pth file.
11 | neck=dict(
12 | type='FPN',
13 | in_channels=[48, 272, 1024, 2048],
14 | out_channels=192,
15 | start_level=1,
16 | add_extra_convs='on_output', # use P5
17 | num_outs=5),
18 | bbox_head=dict(
19 | in_channels=192,
20 | feat_channels=192),
21 | )
22 | # training and testing settings
23 | img_norm_cfg = dict(
24 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
25 | train_pipeline = [
26 | dict(type='LoadImageFromFile'),
27 | dict(type='LoadAnnotations', with_bbox=True),
28 | dict(
29 | type='Resize',
30 | img_scale=[(1333, 480), (1333, 960)],
31 | multiscale_mode='range',
32 | keep_ratio=True),
33 | dict(type='RandomFlip', flip_ratio=0.5),
34 | dict(type='Normalize', **img_norm_cfg),
35 | dict(type='Pad', size_divisor=32),
36 | dict(type='DefaultFormatBundle'),
37 | dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
38 | ]
39 | test_pipeline = [
40 | dict(type='LoadImageFromFile'),
41 | dict(
42 | type='MultiScaleFlipAug',
43 | img_scale=(1333, 800),
44 | flip=False,
45 | transforms=[
46 | dict(type='Resize', keep_ratio=True),
47 | dict(type='RandomFlip'),
48 | dict(type='Normalize', **img_norm_cfg),
49 | dict(type='Pad', size_divisor=32),
50 | dict(type='ImageToTensor', keys=['img']),
51 | dict(type='Collect', keys=['img']),
52 | ])
53 | ]
54 | data = dict(
55 | train=dict(pipeline=train_pipeline),
56 | val=dict(pipeline=test_pipeline),
57 | test=dict(pipeline=test_pipeline))
58 | # optimizer
59 | optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
60 |
61 | # learning policy
62 | lr_config = dict(
63 | warmup='linear',
64 | warmup_iters=7330,
65 | warmup_ratio=0.1,
66 | step=[65, 71])
67 | total_epochs = 73
68 | use_syncBN_torch = True
--------------------------------------------------------------------------------
/configs/detection/models/madnas.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2021-2022 Alibaba Group Holding Limited.
2 |
3 | import os,sys
4 | import torch
5 | import torch.nn as nn
6 | from cnnnet import CnnNet
7 | from ..builder import BACKBONES
8 | import ast
9 |
10 | sys.path.append(os.path.dirname(os.path.abspath(__file__)))
11 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
12 |
13 | from mmcv.cnn import ConvModule, constant_init, kaiming_init
14 | from torch.nn.modules.batchnorm import _BatchNorm
15 |
16 |
17 | @BACKBONES.register_module
18 | class MadNas(nn.Module):
19 | def __init__(self, structure_txt=None, out_indices=(1, 2, 3, 4), init_cfg=None):
20 | super(MadNas, self).__init__()
21 | with open(structure_txt, 'r') as fin:
22 | content = fin.read()
23 | output_structures = ast.literal_eval(content)
24 |
25 | network_arch = output_structures['space_arch']
26 | best_structure = output_structures['best_structures'][0]
27 | self.body = CnnNet(structure_info=best_structure, out_indices=out_indices, no_create=False)
28 | if init_cfg is not None and os.path.isfile(init_cfg):
29 | self.body.init_weights(init_cfg)
30 |
31 | def init_weights(self, pretrained=None):
32 | for m in self.modules():
33 | if isinstance(m, nn.Conv2d):
34 | kaiming_init(m)
35 | elif isinstance(m, (_BatchNorm, nn.GroupNorm)):
36 | constant_init(m, 1)
37 |
38 | def forward(self, x):
39 | """Forward function."""
40 | return self.body(x)
41 |
42 |
43 | if __name__ == "__main__":
44 | pass
--------------------------------------------------------------------------------
/configs/detection/models/maedet_l.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 80, 's': 2, 'k': 3},
3 | {'class': 'SuperResK1KXK1', 'in': 80, 'out': 144, 's': 2, 'k': 3, 'L': 2, 'btn': 80},
4 | {'class': 'SuperResK1KXK1', 'in': 144, 'out': 608, 's': 2, 'k': 5, 'L': 12, 'btn': 88},
5 | {'class': 'SuperResK1KXK1', 'in': 608, 'out': 1912, 's': 2, 'k': 5, 'L': 12, 'btn': 136},
6 | {'class': 'SuperResK1KXK1', 'in': 1912, 'out': 2400, 's': 2, 'k': 5, 'L': 10, 'btn': 220}]],
7 | 'space_arch': 'CnnNet'}
8 |
--------------------------------------------------------------------------------
/configs/detection/models/maedet_m.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 64, 's': 2, 'k': 3},
3 | {'class': 'SuperResK1KXK1', 'in': 64, 'out': 120, 's': 2, 'k': 3, 'L': 2, 'btn': 64},
4 | {'class': 'SuperResK1KXK1', 'in': 120, 'out': 512, 's': 2, 'k': 5, 'L': 10, 'btn': 72},
5 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 1632, 's': 2, 'k': 5, 'L': 10, 'btn': 112},
6 | {'class': 'SuperResK1KXK1', 'in': 1632, 'out': 2048, 's': 2, 'k': 5, 'L': 8, 'btn': 184}]],
7 | 'space_arch': 'CnnNet'}
--------------------------------------------------------------------------------
/configs/detection/models/maedet_s.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3},
3 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 48, 's': 2, 'k': 5, 'L': 2, 'btn': 32},
4 | {'class': 'SuperResK1KXK1', 'in': 48, 'out': 272, 's': 2, 'k': 3, 'L': 4, 'btn': 120},
5 | {'class': 'SuperResK1KXK1', 'in': 272, 'out': 1024, 's': 2, 'k': 5, 'L': 10, 'btn': 80},
6 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 10, 'btn': 240}]],
7 | 'space_arch': 'CnnNet'}
8 |
--------------------------------------------------------------------------------
/configs/quant/Mixed_19d2G.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/mbv2_8bits_flops300e6_layers47/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 224 # 224 for Imagenet, 480 for detection, 160 for mcu
11 |
12 | init_bit=4
13 | bits_list = [init_bit, init_bit, init_bit]
14 | """ Model config """
15 | model = dict(
16 | type = 'CnnNet',
17 | structure_info = [
18 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 16, 's': 2, 'k': 3, 'nbitsA':8, 'nbitsW':8}, \
19 | {'class': 'SuperQuantResK1DWK1', 'in': 16, 'out': 24, 's': 2, 'k': 3, 'L': 1, 'btn': 48, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
20 | {'class': 'SuperQuantResK1DWK1', 'in': 24, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 96, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
21 | {'class': 'SuperQuantResK1DWK1', 'in': 48, 'out': 64, 's': 2, 'k': 3, 'L': 1, 'btn': 128, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
22 | {'class': 'SuperQuantResK1DWK1', 'in': 64, 'out': 96, 's': 1, 'k': 3, 'L': 1, 'btn': 192, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
23 | {'class': 'SuperQuantResK1DWK1', 'in': 96, 'out': 192, 's': 2, 'k': 3, 'L': 1, 'btn': 384, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
24 | {'class': 'ConvKXBNRELU', 'in': 192, 'out': 1280, 's': 1, 'k': 1, 'nbitsA':init_bit, 'nbitsW':init_bit}, \
25 | ]
26 | )
27 |
28 | """ Budget config """
29 | budgets = [
30 | dict(type = "flops", budget = 300e6),
31 | dict(type = "layers",budget = 47),
32 | ]
33 |
34 | """ Score config """
35 | score = dict(
36 | type = 'madnas',
37 | multi_block_ratio = [0,0,1,1,6],
38 | init_std = 4,
39 | init_std_act = 5,
40 | )
41 |
42 | """ Space config """
43 | space = dict(
44 | type = 'space_quant_k1dwk1',
45 | image_size = image_size,
46 | )
47 |
48 | """ Search config """
49 | search=dict(
50 | minor_mutation = False, # whether fix the stage layer
51 | minor_iter = 100000, # which iteration to enable minor_mutation
52 | popu_size = 512,
53 | num_random_nets = 500000, # the searching iterations
54 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
55 | num_network = 1,
56 | )
57 |
58 |
--------------------------------------------------------------------------------
/configs/quant/Mixed_7d0G.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | work_dir = './save_model/mbv2_4bits_flops109e6_layers47/'
6 | log_level = 'INFO' # INFO/DEBUG/ERROR
7 | log_freq = 1000
8 |
9 | """ image config """
10 | image_size = 224 # 224 for Imagenet, 480 for detection, 160 for mcu
11 |
12 | init_bit=4
13 | bits_list = [init_bit, init_bit, init_bit]
14 | """ Model config """
15 | model = dict(
16 | type = 'CnnNet',
17 | structure_info = [
18 | {'class': 'ConvKXBNRELU', 'in': 3, 'out': 16, 's': 2, 'k': 3, 'nbitsA':8, 'nbitsW':8}, \
19 | {'class': 'SuperQuantResK1DWK1', 'in': 16, 'out': 24, 's': 2, 'k': 3, 'L': 1, 'btn': 48, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
20 | {'class': 'SuperQuantResK1DWK1', 'in': 24, 'out': 48, 's': 2, 'k': 3, 'L': 1, 'btn': 96, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
21 | {'class': 'SuperQuantResK1DWK1', 'in': 48, 'out': 64, 's': 2, 'k': 3, 'L': 1, 'btn': 128, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
22 | {'class': 'SuperQuantResK1DWK1', 'in': 64, 'out': 96, 's': 1, 'k': 3, 'L': 1, 'btn': 192, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
23 | {'class': 'SuperQuantResK1DWK1', 'in': 96, 'out': 192, 's': 2, 'k': 3, 'L': 1, 'btn': 384, 'nbitsA':bits_list, 'nbitsW':bits_list}, \
24 | {'class': 'ConvKXBNRELU', 'in': 192, 'out': 1280, 's': 1, 'k': 1, 'nbitsA':init_bit, 'nbitsW':init_bit}, \
25 | ]
26 | )
27 |
28 | """ Budget config """
29 | budgets = [
30 | dict(type = "flops", budget = 109e6),
31 | dict(type = "layers",budget = 47),
32 | ]
33 |
34 | """ Score config """
35 | score = dict(
36 | type = 'madnas',
37 | multi_block_ratio = [0,0,1,1,6],
38 | init_std = 4,
39 | init_std_act = 5,
40 | )
41 |
42 | """ Space config """
43 | space = dict(
44 | type = 'space_quant_k1dwk1',
45 | image_size = image_size,
46 | )
47 |
48 | """ Search config """
49 | search=dict(
50 | minor_mutation = False, # whether fix the stage layer
51 | minor_iter = 100000, # which iteration to enable minor_mutation
52 | popu_size = 256,
53 | num_random_nets = 500000, # the searching iterations
54 | sync_size_ratio = 1.0, # control each thread sync number: ratio * popu_size
55 | num_network = 1,
56 | )
57 |
58 |
--------------------------------------------------------------------------------
/configs/quant/README.md:
--------------------------------------------------------------------------------
1 | ## Abstract
2 |
3 | * **Instruction**
4 |
5 | We propose Quantization Entropy Score (QE-Score) to calculate the entropy for searching efficient low-precision backbones. In this folder, we provide the example scripts and structure txt for quantization models, which are aligned with MobileNetV2-4/8bit.
6 | Mixed7d0G is aligned with MobileNetV2-4bit, while Mixed19d2G is aligned with MobileNetV2-8bit. The training pipeline is released on the [QE-Score official repository](https://github.com/implus/GFocalV2).
7 |
8 |
9 | * **Use the searching examples for Quantization**
10 | ```shell
11 | sh tools/dist_search.sh Mixed_7d0G.py
12 | ```
13 | **`mixed_7d0G.py` is the config for searching Mixed7d0G model within the budget of FLOPs of MobileNetV2-4bit.**
14 |
15 | **`mixed_19d2G.py` is the config for searching Mixed19d2G model within the budget of FLOPs of MobileNetV2-8bit.**
16 |
17 | ***
18 |
19 | ## Results and Models
20 |
21 | |Backbone|Param (MB)|BitOps (G)|ImageNet TOP1|Structure|Download|
22 | |:----|:----|:----|:----|:----|:----|
23 | |MBV2-8bit|3.4|19.2|71.90%| -| -|
24 | |MBV2-4bit|2.3|7|68.90%| -|- |
25 | |Mixed19d2G|3.2|18.8|74.80%|[txt](models/mixed7d0G.txt) |[model](https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/LightNAS/quant/mixed-7d0G/quant_238_70.7660.pth.tar) |
26 | |Mixed7d0G|2.2|6.9|70.80%|[txt](models/mixed19d2G.txt) |[model](https://idstcv.oss-cn-zhangjiakou.aliyuncs.com/LightNAS/quant/mixed-19d2G/quant_237_74.8180.pth.tar) |
27 |
28 | The ImageNet training pipeline can be found at [https://github.com/tinyvision/imagenet-training-pipeline ](https://github.com/tinyvision/imagenet-training-pipeline)
29 |
30 | **Note**:
31 | - If searching without quantization, Budget_flops is equal to the base flops as in other tasks.
32 | - If searching with quantization, Budget_flops = Budget_flops_base x (Act_bit / 8bit) x (Weight_bit / 8bit). Hence, BitOps = Budget_flops x 8 x 8.
33 |
34 |
35 | ***
36 | ## Citation
37 |
38 | If you use this toolbox in your research, please cite the paper.
39 |
40 | ```
41 | @inproceedings{qescore,
42 | title = {Entropy-Driven Mixed-Precision Quantization for Deep Network Design},
43 | author = {Zhenhong Sun and Ce Ge and Junyan Wang and Ming Lin and Hesen Chen and Hao Li and Xiuyu Sun},
44 | journal = {Advances in Neural Information Processing Systems},
45 | year = {2022},
46 | }
47 |
--------------------------------------------------------------------------------
/configs/quant/models/mixed19d2G.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'nbitsA': 8, 'nbitsW': 8, 'out': 16, 's': 2},
3 | { 'L': 3,
4 | 'btn': 144,
5 | 'class': 'SuperQuantResK1DWK1',
6 | 'in': 16,
7 | 'inner_class': 'ResK1DWK1',
8 | 'k': 5,
9 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
10 | 'nbitsW': [5, 5, 5, 5, 5, 5, 5, 5, 5],
11 | 'out': 40,
12 | 's': 2},
13 | { 'L': 3,
14 | 'btn': 320,
15 | 'class': 'SuperQuantResK1DWK1',
16 | 'in': 40,
17 | 'inner_class': 'ResK1DWK1',
18 | 'k': 5,
19 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
20 | 'nbitsW': [5, 5, 5, 5, 5, 5, 5, 5, 5],
21 | 'out': 80,
22 | 's': 2},
23 | { 'L': 3,
24 | 'btn': 616,
25 | 'class': 'SuperQuantResK1DWK1',
26 | 'in': 80,
27 | 'inner_class': 'ResK1DWK1',
28 | 'k': 5,
29 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
30 | 'nbitsW': [4, 4, 4, 4, 4, 4, 4, 4, 4],
31 | 'out': 176,
32 | 's': 2},
33 | { 'L': 3,
34 | 'btn': 448,
35 | 'class': 'SuperQuantResK1DWK1',
36 | 'in': 176,
37 | 'inner_class': 'ResK1DWK1',
38 | 'k': 5,
39 | 'nbitsA': [5, 5, 5, 4, 4, 4, 5, 5, 5],
40 | 'nbitsW': [5, 5, 5, 5, 5, 5, 5, 5, 5],
41 | 'out': 224,
42 | 's': 1},
43 | { 'L': 3,
44 | 'btn': 960,
45 | 'class': 'SuperQuantResK1DWK1',
46 | 'in': 224,
47 | 'inner_class': 'ResK1DWK1',
48 | 'k': 5,
49 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
50 | 'nbitsW': [5, 5, 5, 5, 5, 5, 5, 5, 5],
51 | 'out': 240,
52 | 's': 2},
53 | {'class': 'ConvKXBNRELU', 'in': 240, 'k': 1, 'nbitsA': 5, 'nbitsW': 5, 'out': 1280, 's': 1}]],
54 | 'space_arch': 'CnnNet'}
--------------------------------------------------------------------------------
/configs/quant/models/mixed7d0G.txt:
--------------------------------------------------------------------------------
1 | { 'best_structures':[ [
2 | {'class': 'ConvKXBNRELU', 'in': 3, 'k': 3, 'nbitsA': 8, 'nbitsW': 8, 'out': 8, 's': 2},
3 | { 'L': 3,
4 | 'btn': 64,
5 | 'class': 'SuperQuantResK1DWK1',
6 | 'in': 8,
7 | 'inner_class': 'ResK1DWK1',
8 | 'k': 5,
9 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
10 | 'nbitsW': [5, 5, 5, 5, 5, 5, 4, 4, 4],
11 | 'out': 32,
12 | 's': 2},
13 | { 'L': 3,
14 | 'btn': 128,
15 | 'class': 'SuperQuantResK1DWK1',
16 | 'in': 32,
17 | 'inner_class': 'ResK1DWK1',
18 | 'k': 5,
19 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
20 | 'nbitsW': [5, 5, 5, 5, 5, 5, 4, 4, 4],
21 | 'out': 64,
22 | 's': 2},
23 | { 'L': 3,
24 | 'btn': 224,
25 | 'class': 'SuperQuantResK1DWK1',
26 | 'in': 64,
27 | 'inner_class': 'ResK1DWK1',
28 | 'k': 5,
29 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
30 | 'nbitsW': [5, 5, 5, 5, 5, 5, 5, 5, 5],
31 | 'out': 64,
32 | 's': 2},
33 | { 'L': 3,
34 | 'btn': 336,
35 | 'class': 'SuperQuantResK1DWK1',
36 | 'in': 64,
37 | 'inner_class': 'ResK1DWK1',
38 | 'k': 5,
39 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
40 | 'nbitsW': [5, 5, 5, 6, 6, 6, 5, 5, 5],
41 | 'out': 96,
42 | 's': 1},
43 | { 'L': 3,
44 | 'btn': 672,
45 | 'class': 'SuperQuantResK1DWK1',
46 | 'in': 96,
47 | 'inner_class': 'ResK1DWK1',
48 | 'k': 5,
49 | 'nbitsA': [5, 5, 5, 5, 5, 5, 5, 5, 5],
50 | 'nbitsW': [6, 6, 6, 4, 4, 4, 5, 5, 5],
51 | 'out': 192,
52 | 's': 2},
53 | {'class': 'ConvKXBNRELU', 'in': 192, 'k': 1, 'nbitsA': 5, 'nbitsW': 5, 'out': 1280, 's': 1}]],
54 | 'space_arch': 'CnnNet'}
55 |
--------------------------------------------------------------------------------
/docs/arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/lightweight-neural-architecture-search/8ccaf889fcd06079d268a355c765e9d0af071612/docs/arch.png
--------------------------------------------------------------------------------
/get_started.md:
--------------------------------------------------------------------------------
1 | # Commence usage
2 |
3 | For initial usage, please follow the steps below sequentially.
4 |
5 | ## Search for the model architecture.
6 |
7 | - Directories [configs/classification](configs/classification) and [configs/detection](configs/detection) respectively contain search configuration files for classification and detection, as demonstrated below.
8 | - Taking a classification task as an example, search for the CNN architecture of ResNet-50 and execute the following steps:
9 |
10 | ```shell
11 | sh tools/dist_search.sh configs/classification/R50_FLOPs.py
12 | #or
13 | python tools/search.py configs/classification/R50_FLOPs.py
14 | ```
15 |
16 | ## Export the search results.
17 |
18 | - [tools/export.py](tools/export.py), A script for exporting the searched model architecture and its related dependencies is provided, allowing for quick verification of the demo
19 |
20 | - For example [R50_FLOPs](configs/classification/R50_FLOPs.py):
21 |
22 | ```shell
23 | python tools/export.py save_model/R50_R224_FLOPs41e8 output_dir
24 | ```
25 |
26 | Copy the demo deployment and related code to the **output_dir/R50_R224_FLOPs41e8/** directory, which should include the following contents:
27 |
28 | - best_structure.json:Several optimal model architectures that were found during the search.
29 | - demo.py:A simple script demonstrating how to use the models
30 | - cnnnet.py:The class definitions and utility functions used for constructing the models
31 | - modules: The foundational modules of the models.
32 | - weights/:Several optimal model weights that were found during the search (only available for one-shot NAS methods).
33 |
34 |
35 | ## Using the searched architecture.
36 |
37 | - [demo.py](tinynas/deploy/cnnnet/demo.py) is a basic usage example, but you can also run demo.py directly after exporting the model architecture in the previous step.
38 |
39 | - Continuing with the ResNet-50 architecture for a classification task as an example, the core code is explained below:
40 |
41 | - Import dependencies
42 |
43 | ```python
44 | import ast
45 | from cnnnet import CnnNet
46 | ```
47 |
48 | - Load the optimal structure from a file."
49 |
50 | ```python
51 | with open('best_structure.json', 'r') as fin:
52 | content = fin.read()
53 | output_structures = ast.literal_eval(content)
54 |
55 | network_arch = output_structures['space_arch']
56 | best_structures = output_structures['best_structures']
57 | ```
58 |
59 | - Instantiate the classification backbone network.
60 |
61 | ```python
62 | network_id = 0 # Index number. Multiple structures can be output during the search, as set by num_network=5 in example_cls_res50.sh.
63 | out_indices = (4, ) # Output stage. For classification tasks, only the output from the final stage needs to be obtained.
64 |
65 | backbone = CnnNet(
66 | structure_info=best_structures[network_id],
67 | out_indices=out_indices,
68 | num_classes=1000,
69 | classification=True,
70 | )
71 | backbone.init_weight(pretrained)
72 | ```
73 |
74 | - You can now fully utilize the `backbone` :smile:
75 |
76 | - For further usage methods of the CNN detection task model, please refer to [tinynas/deploy/](tinynas/deploy/)
77 |
--------------------------------------------------------------------------------
/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | ## Additional Requirements
4 | - Linux
5 | - GCC 7+
6 | - Python 3.6+
7 | - PyTorch 1.9+
8 | - CUDA 10.2+
9 |
10 | ## Dependency Installation
11 |
12 | 1. Create a conda virtual environment and activate
13 |
14 | ```shell
15 | conda create -n tinynas python=3.6 -y
16 | conda activate tinynas
17 | ```
18 |
19 | 2. Install OpenMPI and mpi4py
20 |
21 | a. Install using conda command(recommended)
22 |
23 | ```shell
24 | conda install -c conda-forge mpi4py=3.0.3 openmpi=4.0.4
25 | ```
26 |
27 | b. Build from source (More faster when Multi-Process)
28 | - From [Here](https://www.open-mpi.org/software/ompi/v4.0/) download openmpi source code
29 |
30 | ```shell
31 | tar -xzvf openmpi-4.0.1.tar.gz
32 | cd openmpi-4.0.1
33 | ./configure --prefix=$HOME/openmpi
34 | make && make install
35 | ```
36 | - add mpi to the system path
37 |
38 | ```shell
39 | export PATH=$HOME/openmpi/bin:$PATH
40 | export LD_LIBRARY_PATH=$HOME/openmpi/lib:$LD_LIBRARY_PATH
41 | ```
42 | - install mpi4py
43 |
44 | ```shell
45 | # conda
46 | conda install -c conda-forge mpi4py
47 | # or pip
48 | pip install mpi4py
49 | ```
50 |
51 | 3. Run the following commands or [Official Guide](https://pytorch.org/get-started/locally/) install torch and torchvision
52 |
53 | ```shell
54 | conda install pytorch==1.9.0 torchvision==0.10.0 torchaudio==0.9.0 cudatoolkit=10.2 -c pytorch
55 | ```
56 | > If you see `"Not be found for jpeg"`, please install libjpeg first.
57 | ```shell
58 | sudo yum install libjpeg # for centos
59 | sudo apt install libjpeg-dev # for ubuntu
60 | ```
61 |
62 | 4. ModelScope (optional)
63 |
64 | > For light-weight, we modify and port some code of modelscope , if you want to experience more features, you can visite [ModelScope](https://modelscope.cn/home)
65 | , or run the following installation commands
66 | ```shell
67 | pip install "modelscope[cv]" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html
68 | ```
69 |
70 | 5. Other Requirements
71 |
72 | ```shell
73 | pip install -r requirements/nas.txt
74 | ```
75 |
76 | 6. Installation check
77 | ```python
78 | import tinynas
79 | print(tinynas.__version__)
80 | ```
81 |
--------------------------------------------------------------------------------
/modelscope/__init__.py:
--------------------------------------------------------------------------------
1 | from .version import __release_datetime__, __version__
2 |
3 | __all__ = ['__version__', '__release_datetime__']
4 |
--------------------------------------------------------------------------------
/modelscope/fileio/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | from .file import File, LocalStorage
4 | from .io import dump, dumps, load
5 |
--------------------------------------------------------------------------------
/modelscope/fileio/format/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | from .base import FormatHandler
4 | from .json import JsonHandler
5 | from .yaml import YamlHandler
6 |
--------------------------------------------------------------------------------
/modelscope/fileio/format/base.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | from abc import ABCMeta, abstractmethod
3 |
4 |
5 | class FormatHandler(metaclass=ABCMeta):
6 | # if `text_format` is True, file
7 | # should use text mode otherwise binary mode
8 | text_mode = True
9 |
10 | @abstractmethod
11 | def load(self, file, **kwargs):
12 | pass
13 |
14 | @abstractmethod
15 | def dump(self, obj, file, **kwargs):
16 | pass
17 |
18 | @abstractmethod
19 | def dumps(self, obj, **kwargs):
20 | pass
21 |
--------------------------------------------------------------------------------
/modelscope/fileio/format/json.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | import numpy as np
3 |
4 | from .base import FormatHandler
5 |
6 |
7 | def set_default(obj):
8 | """Set default json values for non-serializable values.
9 |
10 | It helps convert ``set``, ``range`` and ``np.ndarray`` data types to list.
11 | It also converts ``np.generic`` (including ``np.int32``, ``np.float32``,
12 | etc.) into plain numbers of plain python built-in types.
13 | """
14 | if isinstance(obj, (set, range)):
15 | return list(obj)
16 | elif isinstance(obj, np.ndarray):
17 | return obj.tolist()
18 | elif isinstance(obj, np.generic):
19 | return obj.item()
20 | raise TypeError(f'{type(obj)} is unsupported for json dump')
21 |
22 |
23 | class JsonHandler(FormatHandler):
24 | """Use jsonplus, serialization of Python types to JSON that "just works"."""
25 |
26 | def load(self, file):
27 | import jsonplus
28 | return jsonplus.loads(file.read())
29 |
30 | def dump(self, obj, file, **kwargs):
31 | file.write(self.dumps(obj, **kwargs))
32 |
33 | def dumps(self, obj, **kwargs):
34 | import jsonplus
35 | kwargs.setdefault('default', set_default)
36 | return jsonplus.dumps(obj, **kwargs)
37 |
--------------------------------------------------------------------------------
/modelscope/fileio/format/yaml.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | import yaml
3 |
4 | try:
5 | from yaml import CDumper as Dumper
6 | from yaml import CLoader as Loader
7 | except ImportError:
8 | from yaml import Loader, Dumper # type: ignore
9 |
10 | from .base import FormatHandler # isort:skip
11 |
12 |
13 | class YamlHandler(FormatHandler):
14 |
15 | def load(self, file, **kwargs):
16 | kwargs.setdefault('Loader', Loader)
17 | return yaml.load(file, **kwargs)
18 |
19 | def dump(self, obj, file, **kwargs):
20 | kwargs.setdefault('Dumper', Dumper)
21 | yaml.dump(obj, file, **kwargs)
22 |
23 | def dumps(self, obj, **kwargs):
24 | kwargs.setdefault('Dumper', Dumper)
25 | return yaml.dump(obj, **kwargs)
26 |
--------------------------------------------------------------------------------
/modelscope/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/lightweight-neural-architecture-search/8ccaf889fcd06079d268a355c765e9d0af071612/modelscope/utils/__init__.py
--------------------------------------------------------------------------------
/modelscope/utils/config_ds.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | import os
4 | from pathlib import Path
5 |
6 | # Cache location
7 | from modelscope.hub.constants import DEFAULT_MODELSCOPE_DATA_ENDPOINT
8 |
9 | DEFAULT_CACHE_HOME = Path.home().joinpath('.cache')
10 | CACHE_HOME = os.getenv('CACHE_HOME', DEFAULT_CACHE_HOME)
11 | DEFAULT_MS_CACHE_HOME = os.path.join(CACHE_HOME, 'modelscope', 'hub')
12 | MS_CACHE_HOME = os.path.expanduser(
13 | os.getenv('MS_CACHE_HOME', DEFAULT_MS_CACHE_HOME))
14 |
15 | DEFAULT_MS_DATASETS_CACHE = os.path.join(MS_CACHE_HOME, 'datasets')
16 | MS_DATASETS_CACHE = Path(
17 | os.getenv('MS_DATASETS_CACHE', DEFAULT_MS_DATASETS_CACHE))
18 |
19 | DOWNLOADED_DATASETS_DIR = 'downloads'
20 | DEFAULT_DOWNLOADED_DATASETS_PATH = os.path.join(MS_DATASETS_CACHE,
21 | DOWNLOADED_DATASETS_DIR)
22 | DOWNLOADED_DATASETS_PATH = Path(
23 | os.getenv('DOWNLOADED_DATASETS_PATH', DEFAULT_DOWNLOADED_DATASETS_PATH))
24 |
25 | HUB_DATASET_ENDPOINT = os.environ.get('HUB_DATASET_ENDPOINT',
26 | DEFAULT_MODELSCOPE_DATA_ENDPOINT)
27 |
--------------------------------------------------------------------------------
/modelscope/utils/data_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | from collections.abc import Mapping
3 |
4 | import torch
5 |
6 | from modelscope.outputs import ModelOutputBase
7 |
8 |
9 | def to_device(batch, device, non_blocking=False):
10 | """Put the data to the target cuda device just before the forward function.
11 | Args:
12 | batch: The batch data out of the dataloader.
13 | device: (str | torch.device): The target device for the data.
14 |
15 | Returns: The data to the target device.
16 |
17 | """
18 | if isinstance(batch, ModelOutputBase):
19 | for idx in range(len(batch)):
20 | batch[idx] = to_device(batch[idx], device)
21 | return batch
22 | elif isinstance(batch, dict) or isinstance(batch, Mapping):
23 | return type(batch)({k: to_device(v, device) for k, v in batch.items()})
24 | elif isinstance(batch, (tuple, list)):
25 | return type(batch)(to_device(v, device) for v in batch)
26 | elif isinstance(batch, torch.Tensor):
27 | return batch.to(device, non_blocking=non_blocking)
28 | else:
29 | return batch
30 |
--------------------------------------------------------------------------------
/modelscope/utils/file_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | import inspect
4 | import os
5 | from pathlib import Path
6 |
7 |
8 | # TODO: remove this api, unify to flattened args
9 | def func_receive_dict_inputs(func):
10 | """to decide if a func could recieve dict inputs or not
11 |
12 | Args:
13 | func (class): the target function to be inspected
14 |
15 | Returns:
16 | bool: if func only has one arg ``input`` or ``inputs``, return True, else return False
17 | """
18 | full_args_spec = inspect.getfullargspec(func)
19 | varargs = full_args_spec.varargs
20 | varkw = full_args_spec.varkw
21 | if not (varargs is None and varkw is None):
22 | return False
23 |
24 | args = [] if not full_args_spec.args else full_args_spec.args
25 | args.pop(0) if (args and args[0] in ['self', 'cls']) else args
26 |
27 | if len(args) == 1 and args[0] in ['input', 'inputs']:
28 | return True
29 |
30 | return False
31 |
32 |
33 | def get_default_cache_dir():
34 | """
35 | default base dir: '~/.cache/modelscope'
36 | """
37 | default_cache_dir = Path.home().joinpath('.cache', 'modelscope')
38 | return default_cache_dir
39 |
40 |
41 | def read_file(path):
42 |
43 | with open(path, 'r') as f:
44 | text = f.read()
45 | return text
46 |
--------------------------------------------------------------------------------
/modelscope/utils/json_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | import json
4 | import numpy as np
5 |
6 |
7 | class EnhancedEncoder(json.JSONEncoder):
8 | """ Enhanced json encoder for not supported types """
9 |
10 | def default(self, obj):
11 | if isinstance(obj, np.integer):
12 | return int(obj)
13 | elif isinstance(obj, np.floating):
14 | return float(obj)
15 | elif isinstance(obj, np.ndarray):
16 | return obj.tolist()
17 | return json.JSONEncoder.default(self, obj)
18 |
--------------------------------------------------------------------------------
/modelscope/utils/logger.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | import importlib
4 | import logging
5 | from typing import Optional
6 |
7 | init_loggers = {}
8 |
9 | formatter = logging.Formatter(
10 | '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
11 |
12 |
13 | def get_logger(log_file: Optional[str] = None,
14 | log_level: int = logging.INFO,
15 | file_mode: str = 'w'):
16 | """ Get logging logger
17 |
18 | Args:
19 | log_file: Log filename, if specified, file handler will be added to
20 | logger
21 | log_level: Logging level.
22 | file_mode: Specifies the mode to open the file, if filename is
23 | specified (if filemode is unspecified, it defaults to 'w').
24 | """
25 |
26 | logger_name = __name__.split('.')[0]
27 | logger = logging.getLogger(logger_name)
28 |
29 | if logger_name in init_loggers:
30 | add_file_handler_if_needed(logger, log_file, file_mode, log_level)
31 | return logger
32 |
33 | # handle duplicate logs to the console
34 | # Starting in 1.8.0, PyTorch DDP attaches a StreamHandler (NOTSET)
35 | # to the root logger. As logger.propagate is True by default, this root
36 | # level handler causes logging messages from rank>0 processes to
37 | # unexpectedly show up on the console, creating much unwanted clutter.
38 | # To fix this issue, we set the root logger's StreamHandler, if any, to log
39 | # at the ERROR level.
40 | for handler in logger.root.handlers:
41 | if type(handler) is logging.StreamHandler:
42 | handler.setLevel(logging.ERROR)
43 |
44 | stream_handler = logging.StreamHandler()
45 | handlers = [stream_handler]
46 |
47 | if importlib.util.find_spec('torch') is not None:
48 | from modelscope.utils.torch_utils import is_master
49 | is_worker0 = is_master()
50 | else:
51 | is_worker0 = True
52 |
53 | if is_worker0 and log_file is not None:
54 | file_handler = logging.FileHandler(log_file, file_mode)
55 | handlers.append(file_handler)
56 |
57 | for handler in handlers:
58 | handler.setFormatter(formatter)
59 | handler.setLevel(log_level)
60 | logger.addHandler(handler)
61 |
62 | if is_worker0:
63 | logger.setLevel(log_level)
64 | else:
65 | logger.setLevel(logging.ERROR)
66 |
67 | init_loggers[logger_name] = True
68 |
69 | return logger
70 |
71 |
72 | def add_file_handler_if_needed(logger, log_file, file_mode, log_level):
73 | for handler in logger.handlers:
74 | if isinstance(handler, logging.FileHandler):
75 | return
76 |
77 | if importlib.util.find_spec('torch') is not None:
78 | from modelscope.utils.torch_utils import is_master
79 | is_worker0 = is_master()
80 | else:
81 | is_worker0 = True
82 |
83 | if is_worker0 and log_file is not None:
84 | file_handler = logging.FileHandler(log_file, file_mode)
85 | file_handler.setFormatter(formatter)
86 | file_handler.setLevel(log_level)
87 | logger.addHandler(file_handler)
88 |
--------------------------------------------------------------------------------
/modelscope/utils/megatron_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | from typing import Optional
4 |
5 | from megatron_util import initialize_megatron
6 |
7 | from modelscope.utils.config import Config
8 | from modelscope.utils.hub import read_config
9 |
10 | _DEFAULT_CFG_WITH_MODEL_TYPE = {
11 | 'gpt-moe': {
12 | 'version': 'moe',
13 | 'world_size': 8
14 | },
15 | 'plug': {
16 | 'version': 'v1',
17 | 'world_size': 8,
18 | 'tensor_model_parallel_size': 8,
19 | 'seed': 1234
20 | },
21 | 'mglm-text-summarization': {
22 | 'version': 'v1',
23 | 'seed': 1234
24 | },
25 | }
26 |
27 |
28 | def init_megatron_util(cfg: Optional[Config] = None,
29 | model_dir: Optional[str] = None,
30 | **kwargs):
31 | assert not (cfg is None and model_dir is None), \
32 | 'cfg and model_dir cannot both be None when initializing megatron_util'
33 | if cfg is None:
34 | cfg = read_config(model_dir)
35 | try:
36 | megatron_cfg = cfg.megatron
37 | except AttributeError:
38 | try:
39 | model_type = cfg.model.type
40 | except AttributeError:
41 | # Fit models without model type, such as mglm
42 | model_type = cfg.pipeline.type
43 | megatron_cfg = _DEFAULT_CFG_WITH_MODEL_TYPE[model_type] \
44 | if model_type in _DEFAULT_CFG_WITH_MODEL_TYPE else {}
45 | megatron_cfg.update(kwargs)
46 | initialize_megatron(megatron_cfg)
47 |
--------------------------------------------------------------------------------
/modelscope/utils/metric.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Megvii Inc. All rights reserved.
2 | # Copyright © Alibaba, Inc. and its affiliates.
3 |
4 | import functools
5 | import os
6 | from collections import defaultdict, deque
7 |
8 | import numpy as np
9 | import torch
10 |
11 | __all__ = [
12 | 'AverageMeter',
13 | 'MeterBuffer',
14 | 'gpu_mem_usage',
15 | ]
16 |
17 |
18 | def gpu_mem_usage():
19 | """
20 | Compute the GPU memory usage for the current device (MB).
21 | """
22 | mem_usage_bytes = torch.cuda.max_memory_allocated()
23 | return mem_usage_bytes / (1024 * 1024)
24 |
25 |
26 | class AverageMeter:
27 | """Track a series of values and provide access to smoothed values over a
28 | window or the global series average.
29 | """
30 |
31 | def __init__(self, window_size=50):
32 | self._deque = deque(maxlen=window_size)
33 | self._total = 0.0
34 | self._count = 0
35 |
36 | def update(self, value):
37 | self._deque.append(value)
38 | self._count += 1
39 | self._total += value
40 |
41 | @property
42 | def median(self):
43 | d = np.array(list(self._deque))
44 | return np.median(d)
45 |
46 | @property
47 | def avg(self):
48 | # if deque is empty, nan will be returned.
49 | d = np.array(list(self._deque))
50 | return d.mean()
51 |
52 | @property
53 | def global_avg(self):
54 | return self._total / max(self._count, 1e-5)
55 |
56 | @property
57 | def latest(self):
58 | return self._deque[-1] if len(self._deque) > 0 else None
59 |
60 | @property
61 | def total(self):
62 | return self._total
63 |
64 | def reset(self):
65 | self._deque.clear()
66 | self._total = 0.0
67 | self._count = 0
68 |
69 | def clear(self):
70 | self._deque.clear()
71 |
72 |
73 | class MeterBuffer(defaultdict):
74 | """Computes and stores the average and current value"""
75 |
76 | def __init__(self, window_size=20):
77 | factory = functools.partial(AverageMeter, window_size=window_size)
78 | super().__init__(factory)
79 |
80 | def reset(self):
81 | for v in self.values():
82 | v.reset()
83 |
84 | def get_filtered_meter(self, filter_key='time'):
85 | return {k: v for k, v in self.items() if filter_key in k}
86 |
87 | def update(self, values=None, **kwargs):
88 | if values is None:
89 | values = {}
90 | values.update(kwargs)
91 | for k, v in values.items():
92 | if isinstance(v, torch.Tensor):
93 | v = v.detach()
94 | self[k].update(v)
95 |
96 | def clear_meters(self):
97 | for v in self.values():
98 | v.clear()
99 |
--------------------------------------------------------------------------------
/modelscope/utils/tensor_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # Part of the implementation is borrowed from huggingface/transformers.
3 | from collections.abc import Mapping
4 |
5 |
6 | def torch_nested_numpify(tensors):
7 | """ Numpify nested torch tensors.
8 |
9 | NOTE: If the type of input tensors is dict-like(Mapping, dict, OrderedDict, etc.), the return type will be dict.
10 |
11 | Args:
12 | tensors: Nested torch tensors.
13 |
14 | Returns:
15 | The numpify tensors.
16 | """
17 |
18 | import torch
19 | "Numpify `tensors` (even if it's a nested list/tuple of tensors)."
20 | if isinstance(tensors, (list, tuple)):
21 | return type(tensors)(torch_nested_numpify(t) for t in tensors)
22 | if isinstance(tensors, Mapping):
23 | # return dict
24 | return {k: torch_nested_numpify(t) for k, t in tensors.items()}
25 | if isinstance(tensors, torch.Tensor):
26 | t = tensors.cpu()
27 | return t.numpy()
28 | return tensors
29 |
30 |
31 | def torch_nested_detach(tensors):
32 | """ Detach nested torch tensors.
33 |
34 | NOTE: If the type of input tensors is dict-like(Mapping, dict, OrderedDict, etc.), the return type will be dict.
35 |
36 | Args:
37 | tensors: Nested torch tensors.
38 |
39 | Returns:
40 | The detached tensors.
41 | """
42 |
43 | import torch
44 | "Detach `tensors` (even if it's a nested list/tuple of tensors)."
45 | if isinstance(tensors, (list, tuple)):
46 | return type(tensors)(torch_nested_detach(t) for t in tensors)
47 | if isinstance(tensors, Mapping):
48 | return {k: torch_nested_detach(t) for k, t in tensors.items()}
49 | if isinstance(tensors, torch.Tensor):
50 | return tensors.detach()
51 | return tensors
52 |
--------------------------------------------------------------------------------
/modelscope/utils/timer.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates.
2 | # Copyright © Alibaba, Inc. and its affiliates.
3 |
4 | import datetime
5 | import time
6 |
7 |
8 | class Timer(object):
9 |
10 | def __init__(self):
11 | """Recorder of time consumption.
12 |
13 | """
14 | self.reset()
15 |
16 | @property
17 | def average_time(self):
18 | return self.total_time / self.calls if self.calls > 0 else 0.0
19 |
20 | def tic(self):
21 | # using time.time instead of time.clock because time time.clock
22 | # does not normalize for multithreading
23 | self.start_time = time.time()
24 |
25 | def toc(self, average=True):
26 | self.add(time.time() - self.start_time)
27 | if average:
28 | return self.average_time
29 | else:
30 | return self.diff
31 |
32 | def add(self, time_diff):
33 | self.diff = time_diff
34 | self.total_time += self.diff
35 | self.calls += 1
36 |
37 | def reset(self):
38 | self.total_time = 0.0
39 | self.calls = 0
40 | self.start_time = 0.0
41 | self.diff = 0.0
42 |
43 | def avg_time_str(self):
44 | time_str = str(datetime.timedelta(seconds=self.average_time))
45 | return time_str
46 |
47 |
48 | def get_time_str(time_diff):
49 | time_str = str(datetime.timedelta(seconds=time_diff))
50 | return time_str
51 |
--------------------------------------------------------------------------------
/modelscope/utils/type_assert.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | from functools import wraps
4 | from inspect import signature
5 |
6 |
7 | def type_assert(*ty_args, **ty_kwargs):
8 | """a decorator which is used to check the types of arguments in a function or class
9 | Examples:
10 | >>> @type_assert(str)
11 | ... def main(a: str, b: list):
12 | ... print(a, b)
13 | >>> main(1)
14 | Argument a must be a str
15 |
16 | >>> @type_assert(str, (int, str))
17 | ... def main(a: str, b: int | str):
18 | ... print(a, b)
19 | >>> main('1', [1])
20 | Argument b must be (, )
21 |
22 | >>> @type_assert(str, (int, str))
23 | ... class A:
24 | ... def __init__(self, a: str, b: int | str)
25 | ... print(a, b)
26 | >>> a = A('1', [1])
27 | Argument b must be (, )
28 | """
29 |
30 | def decorate(func):
31 | # If in optimized mode, disable type checking
32 | if not __debug__:
33 | return func
34 |
35 | # Map function argument names to supplied types
36 | sig = signature(func)
37 | bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments
38 |
39 | @wraps(func)
40 | def wrapper(*args, **kwargs):
41 | bound_values = sig.bind(*args, **kwargs)
42 | # Enforce type assertions across supplied arguments
43 | for name, value in bound_values.arguments.items():
44 | if name in bound_types:
45 | if not isinstance(value, bound_types[name]):
46 | raise TypeError('Argument {} must be {}'.format(
47 | name, bound_types[name]))
48 | return func(*args, **kwargs)
49 |
50 | return wrapper
51 |
52 | return decorate
53 |
--------------------------------------------------------------------------------
/modelscope/utils/typing.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | from typing import Dict, List, Tuple, Union
4 |
5 | Image = Union[str, 'Image.Image', 'numpy.ndarray']
6 | Text = str
7 | Audio = Union[str, bytes, 'np.ndarray']
8 | Video = Union[str, 'np.ndarray', 'cv2.VideoCapture']
9 |
10 | Tensor = Union['torch.Tensor', 'tf.Tensor']
11 |
--------------------------------------------------------------------------------
/modelscope/version.py:
--------------------------------------------------------------------------------
1 | # Make sure to modify __release_datetime__ to release time when making official release.
2 | __version__ = '1.2.0'
3 | # default release datetime for branches under active development is set
4 | # to be a time far-far-away-into-the-future
5 | __release_datetime__ = '2099-10-13 08:56:12'
6 |
--------------------------------------------------------------------------------
/requirements/nas.txt:
--------------------------------------------------------------------------------
1 | braceexpand
2 | dataclasses
3 | easydict
4 | filelock
5 | ftfy
6 | regex
7 | requests
8 | scipy==1.5.4
9 | tabulate==0.8.9
10 | thop>=0.0.31
11 | tqdm
12 | addict
13 | yapf
14 | packaging
15 | importlib_metadata
16 |
--------------------------------------------------------------------------------
/requirements/tests.txt:
--------------------------------------------------------------------------------
1 | expecttest
2 | flake8
3 | isort>=4.3.21
4 | pre-commit
5 | yapf==0.30.0 # use fix version to ensure consistent auto-styling
6 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [isort]
2 | line_length = 79
3 | multi_line_output = 0
4 | known_standard_library = setuptools
5 | known_first_party = modelscope
6 | known_third_party = json,yaml
7 | no_lines_before = STDLIB,LOCALFOLDER
8 | default_section = THIRDPARTY
9 |
10 | [yapf]
11 | BASED_ON_STYLE = pep8
12 | BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF = true
13 | SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN = true
14 | SPLIT_BEFORE_ARITHMETIC_OPERATOR = true
15 |
16 | [codespell]
17 | skip = *.ipynb
18 | quiet-level = 3
19 | ignore-words-list = patten,nd,ty,mot,hist,formating,winn,gool,datas,wan,confids
20 |
21 | [flake8]
22 | select = B,C,E,F,P,T4,W,B9
23 | max-line-length = 120
24 | ignore = F401,F405,F821,W503
25 | exclude = docs/src,*.pyi,.git
26 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import re, os
2 | import shutil
3 | import setuptools
4 |
5 | def get_install_requirements():
6 | with open('requirements/nas.txt', 'r', encoding='utf-8') as fin:
7 | reqs = [x.strip() for x in fin.read().splitlines()]
8 | reqs = [x for x in reqs if not x.startswith('#')]
9 | return reqs
10 |
11 | with open('tinynas/__init__.py', 'r') as f:
12 | version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(),
13 | re.MULTILINE).group(1)
14 |
15 | with open('README.md', encoding='utf-8') as f:
16 | readme_md = f.read()
17 |
18 | def pack_resource():
19 | # pack resource such as configs and tools
20 | root_dir = os.path.dirname(__file__)
21 | proj_dir = os.path.join(root_dir,'tinynas')
22 |
23 | filenames = ['configs', 'tools']
24 | for filename in filenames:
25 | src_dir = os.path.join(root_dir, filename)
26 | dst_dir = os.path.join(proj_dir, filename)
27 | if os.path.exists(dst_dir):
28 | shutil.rmtree(dst_dir)
29 | shutil.copytree(src_dir, dst_dir)
30 |
31 | if __name__ == '__main__':
32 | pack_resource()
33 | setuptools.setup(
34 | name='tinynas',
35 | version=version,
36 | author='TinyML team of Alibaba DAMO Academy',
37 | description='A lightweight zero-short NAS toolbox for backbone search',
38 | long_description=readme_md,
39 | long_description_content_type='text/markdown',
40 | license='Apache License',
41 | packages=setuptools.find_packages(exclude=['*configs*', '*tools*', '*modelscope*']),
42 | include_package_data=True,
43 | install_requires=get_install_requirements(),
44 | classifiers=[
45 | 'License :: OSI Approved :: Apache Software License',
46 | 'Programming Language :: Python :: 3',
47 | 'Operating System :: OS Independent'
48 | ],
49 | )
50 |
--------------------------------------------------------------------------------
/tinynas/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | __version__ = '2.0.0'
5 |
--------------------------------------------------------------------------------
/tinynas/budgets/README.md:
--------------------------------------------------------------------------------
1 | ## Budgets module
2 |
3 | This module mainly compare between a actual value of one model and a budget value. Currently, only ExceedBudget clas is implemented, which will return false if the model value exceed budget value setting in config.
4 |
5 | - **Surpported Budgets**
6 |
7 | `layers`: the Conv layers budget of the network.
8 |
9 | `flops`: the FLOPs budget of the network.
10 |
11 | `model_size`: the number of parameters budget of the network.
12 |
13 | `latency`: the latency budget of the network.
14 |
15 | `max_feature`: the max feature map budget for MCU of the network.
16 |
17 | `efficient_score`: the efficient score budget of the network.
18 |
--------------------------------------------------------------------------------
/tinynas/budgets/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .builder import build_budget
6 | from .base import *
7 | from .budgets import *
8 |
--------------------------------------------------------------------------------
/tinynas/budgets/base.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from abc import ABC, abstractmethod
6 |
7 | class BudgetBase(ABC, ):
8 |
9 | def __init__(self,
10 | name,
11 | budget):
12 | super().__init__()
13 | self.budget_name = name
14 | self.budget_value = budget
15 |
16 | @abstractmethod
17 | def __call__(self, input):
18 | pass
19 |
20 | @property
21 | def name(self,):
22 | return self.budget_name
23 |
24 | @property
25 | def budget(self,):
26 | return self.budget_value
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tinynas/budgets/budgets.py:
--------------------------------------------------------------------------------
1 | from .builder import BUDGETS
2 | from .base import BudgetBase
3 |
4 | @BUDGETS.register_module(module_name = 'layers')
5 | @BUDGETS.register_module(module_name = 'model_size')
6 | @BUDGETS.register_module(module_name = 'flops')
7 | @BUDGETS.register_module(module_name = 'latency')
8 | @BUDGETS.register_module(module_name = 'max_feature')
9 | @BUDGETS.register_module(module_name = 'efficient_score')
10 | class ExceedBudget(BudgetBase):
11 | def __init__(self, name, budget, logger, **kwargs):
12 | super().__init__(name, budget)
13 | self.logger = logger
14 |
15 | def compare(self, model_info):
16 | input = model_info[self.name]
17 | if self.budget < input:
18 | self.logger.debug(
19 | '{} value = {} in the structure_info exceed the budget ={}'.
20 | format(self.name, input, self.budget))
21 | return False
22 | return True
23 |
24 | def __call__(self, model_info):
25 | return self.compare(model_info)
26 |
--------------------------------------------------------------------------------
/tinynas/budgets/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | BUDGETS= Registry('budgets')
8 |
9 | def build_budget(cfg, default_args: dict = None):
10 | """ build budget given a budget name
11 |
12 | Args:
13 | name (str, optional): Model name, if None, default budget
14 | will be used.
15 | default_args (dict, optional): Default initialization arguments.
16 | """
17 | cfg['name'] = cfg['type']
18 | return build_from_cfg(cfg, BUDGETS, default_args=default_args)
19 |
20 |
--------------------------------------------------------------------------------
/tinynas/deploy/cnn3dnet/demo.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | import ast
4 | import os
5 | import argparse
6 | import torch
7 | from cnn3dnet import Cnn3DNet
8 |
9 | def parse_args():
10 | parser = argparse.ArgumentParser()
11 | parser.add_argument('--structure_txt', type=str)
12 | parser.add_argument('--pretrained', type=str, default=None)
13 | args = parser.parse_args()
14 | return args
15 |
16 | def get_backbone(filename,
17 | pretrained=True,
18 | network_id=0,
19 | classification=True #False for detetion
20 | ):
21 | # load best structures
22 | with open(filename, 'r') as fin:
23 | content = fin.read()
24 | output_structures = ast.literal_eval(content)
25 |
26 | network_arch = output_structures['space_arch']
27 | best_structures = output_structures['best_structures']
28 |
29 | # If task type is classification, param num_classes is required
30 | out_indices = (1, 2, 3, 4) if not classification else (4, )
31 | backbone = Cnn3DNet(
32 | structure_info=best_structures[network_id],
33 | out_indices=out_indices,
34 | num_classes=400,
35 | classification=classification)
36 | backbone.init_weights(pretrained)
37 |
38 | return backbone, network_arch
39 |
40 |
41 | if __name__ == '__main__':
42 | # make input
43 |
44 | args = parse_args()
45 |
46 | x = torch.randn(1, 3, 16, 224, 224)
47 |
48 | # instantiation
49 | backbone, network_arch = get_backbone(args.structure_txt,
50 | args.pretrained)
51 |
52 | print(backbone)
53 | # forward
54 | input_data = [x]
55 | backbone.eval()
56 | pred = backbone(*input_data)
57 |
58 | #print output
59 | for o in pred:
60 | print(o.size())
61 |
--------------------------------------------------------------------------------
/tinynas/deploy/cnn3dnet/modules/__init__.py:
--------------------------------------------------------------------------------
1 | from .blocks_basic_3D import *
2 | from .super_res3d_k1dwk1 import *
3 |
4 |
5 | __all_blocks_3D__ = {
6 | 'Conv3DKXBN': Conv3DKXBN,
7 | 'Conv3DKXBNRELU': Conv3DKXBNRELU,
8 | 'BaseSuperBlock3D': BaseSuperBlock3D,
9 | 'Res3DK1DWK1': Res3DK1DWK1,
10 | 'SuperRes3DK1DWK1': SuperRes3DK1DWK1,
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/tinynas/deploy/cnnnet/demo.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 |
3 | import ast
4 | import os
5 | import argparse
6 | import torch
7 | from cnnnet import CnnNet
8 |
9 | def parse_args():
10 | parser = argparse.ArgumentParser()
11 | parser.add_argument('--structure_txt', type=str)
12 | parser.add_argument('--pretrained', type=str, default=None)
13 | args = parser.parse_args()
14 | return args
15 |
16 | def get_backbone(filename,
17 | pretrained=True,
18 | network_id=0,
19 | classification=True #False for detetion
20 | ):
21 | # load best structures
22 | with open(filename, 'r') as fin:
23 | content = fin.read()
24 | output_structures = ast.literal_eval(content)
25 |
26 | network_arch = output_structures['space_arch']
27 | best_structures = output_structures['best_structures']
28 |
29 | # If task type is classification, param num_classes is required
30 | out_indices = (1, 2, 3, 4) if not classification else (4, )
31 | backbone = CnnNet(
32 | structure_info=best_structures[network_id],
33 | out_indices=out_indices,
34 | num_classes=1000,
35 | classification=classification)
36 | backbone.init_weights(pretrained)
37 |
38 | return backbone, network_arch
39 |
40 |
41 | if __name__ == '__main__':
42 | # make input
43 |
44 | args = parse_args()
45 |
46 | x = torch.randn(1, 3, 224, 224)
47 |
48 | # instantiation
49 | backbone, network_arch = get_backbone(args.structure_txt,
50 | args.pretrained)
51 |
52 | print(backbone)
53 | # forward
54 | input_data = [x]
55 | backbone.eval()
56 | pred = backbone(*input_data)
57 |
58 | #print output
59 | for o in pred:
60 | print(o.size())
61 |
--------------------------------------------------------------------------------
/tinynas/deploy/cnnnet/modules/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .blocks_basic import (BaseSuperBlock, ConvKXBN, ConvKXBNRELU,
6 | network_weight_stupid_init)
7 | from .super_res_k1dwk1 import ResK1DWK1, SuperResK1DWK1
8 | from .super_res_k1dwsek1 import ResK1DWSEK1, SuperResK1DWSEK1
9 | from .super_quant_res_k1dwk1 import SuperQuantResK1DWK1
10 | from .super_res_k1kxk1 import ResK1KXK1, SuperResK1KXK1
11 | from .super_res_k1kx import ResK1KX, SuperResK1KX
12 | from .super_res_kxkx import ResKXKX, SuperResKXKX
13 |
14 | __all_blocks__ = {
15 | 'ConvKXBN': ConvKXBN,
16 | 'ConvKXBNRELU': ConvKXBNRELU,
17 | 'BaseSuperBlock': BaseSuperBlock,
18 | 'ResK1KXK1': ResK1KXK1,
19 | 'ResK1KX': ResK1KX,
20 | 'ResKXKX': ResKXKX,
21 | 'ResK1DWK1': ResK1DWK1,
22 | 'ResK1DWSEK1': ResK1DWSEK1,
23 | 'SuperResK1KXK1': SuperResK1KXK1,
24 | 'SuperResK1KX': SuperResK1KX,
25 | 'SuperResKXKX': SuperResKXKX,
26 | 'SuperResK1DWK1': SuperResK1DWK1,
27 | 'SuperResK1DWSEK1': SuperResK1DWSEK1,
28 | 'SuperQuantResK1DWK1': SuperQuantResK1DWK1,
29 | }
30 |
--------------------------------------------------------------------------------
/tinynas/deploy/cnnnet/modules/super_quant_res_k1dwk1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import copy
6 | import os
7 | import sys
8 | from .super_res_k1dwk1 import SuperResK1DWK1
9 |
10 | class SuperQuantResK1DWK1(SuperResK1DWK1):
11 |
12 | def __init__(self,
13 | structure_info,
14 | no_create=False,
15 | dropout_channel=None,
16 | dropout_layer=None,
17 | **kwargs):
18 | '''
19 |
20 | :param structure_info: {
21 | 'class': 'SuperResK1DWK1',
22 | 'in': in_channels,
23 | 'out': out_channels,
24 | 's': stride (default=1),
25 | 'k': kernel_size,
26 | 'p': padding (default=(k-1)//2,
27 | 'g': grouping (default=1),
28 | 'btn':, bottleneck_channels,
29 | 'L': num_inner_layers,
30 | }
31 | :param NAS_mode:
32 | '''
33 | super().__init__(
34 | structure_info=structure_info,
35 | no_create=no_create,
36 | dropout_channel=dropout_channel,
37 | dropout_layer=dropout_layer,
38 | **kwargs)
39 |
40 |
41 | __module_blocks__ = {
42 | 'SuperQuantResK1DWK1': SuperQuantResK1DWK1,
43 | }
44 |
--------------------------------------------------------------------------------
/tinynas/evolutions/README.md:
--------------------------------------------------------------------------------
1 | ## Population module
2 |
3 | Currently, Only a simple population class is implemented, which maintain the Populaiton. The information in Population consists of different ranked list, including Structure_info, ACC, Score, Paramters, FLOPs, Latency, Layers, Stages. More information for the candidate structure could be added freely.
4 |
5 | - **Population Class**
6 |
7 | `init_population`: Initialize population parameters and information list.
8 |
9 | `update_population`: Update the individual network information that meets the searched budgets.
10 |
11 | `rank_population`: Rank the Population info list with ACC.
12 |
13 | `merge_shared_data`: Merge different Population info between different threads.
14 |
15 | `export_dict`: Export the whole Population info list to a dict for the searching process.
16 |
17 | `get_individual_info`: Get the individual network information with index.
18 |
--------------------------------------------------------------------------------
/tinynas/evolutions/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .population import Population
6 |
--------------------------------------------------------------------------------
/tinynas/latency/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .robust_gpu_predictor import RobustGpuPredictor
6 | from .op_predictor import OpPredictor
7 | from .builder import *
8 |
--------------------------------------------------------------------------------
/tinynas/latency/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | LATENCIES = Registry('latencies')
8 |
9 | def build_latency(cfg, default_args: dict = None):
10 | """ build latency given a latency name
11 |
12 | Args:
13 | name (str, optional): Latency name, if None, default latency
14 | will be used.
15 | default_args (dict, optional): Default initialization arguments.
16 | """
17 | return build_from_cfg(cfg, LATENCIES, default_args=default_args)
18 |
19 |
--------------------------------------------------------------------------------
/tinynas/latency/op_predictor.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import numpy as np
3 | from .op_profiler import OpProfiler
4 | from .builder import LATENCIES
5 |
6 | @LATENCIES.register_module(module_name = 'OpPredictor')
7 | class OpPredictor():
8 | def __init__(self, device_name = 'V100', data_type = 'FP32', batch_size = 32, image_size = 224, logger=None, **kwargs):
9 |
10 | self.logger = logger or logging
11 | self.batch_size = batch_size
12 | self.image_size = image_size
13 | self.predictor = OpProfiler(
14 | device_name = device_name,
15 | data_type = data_type,
16 | logger = self.logger)
17 |
18 | def __call__(self, model):
19 | try:
20 | net_params = model.get_params_for_trt(self.image_size)
21 | # remove other params, only conv and convDW
22 | net_params_conv = []
23 | for idx, net_param in enumerate(net_params):
24 | if net_param[0] in ['Regular', 'Depthwise']:
25 | net_params_conv.append(net_param)
26 | times = [0] * len(net_params_conv)
27 |
28 | # the unit is millisecond with batch_size, so modify it to second
29 | _, the_latency = self.predictor(net_params_conv, times,
30 | self.batch_size)
31 | the_latency = the_latency / self.batch_size / 1000
32 | except Exception as e:
33 | self.logger.error(str(e))
34 | the_latency = np.inf
35 |
36 | return the_latency
37 |
38 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/R50.txt:
--------------------------------------------------------------------------------
1 | [ {'class': 'ConvKXBNRELU', 'in': 3, 'k': 7, 'out': 64, 's': 2},
2 | { 'L': 3,
3 | 'btn': 64,
4 | 'class': 'SuperResK1KXK1',
5 | 'in': 64,
6 | 'inner_class': 'ResK1KXK1',
7 | 'k': 3,
8 | 'out': 256,
9 | 's': 2},
10 | { 'L': 4,
11 | 'btn': 128,
12 | 'class': 'SuperResK1KXK1',
13 | 'in': 256,
14 | 'inner_class': 'ResK1KXK1',
15 | 'k': 3,
16 | 'out': 512,
17 | 's': 2},
18 | { 'L': 6,
19 | 'btn': 256,
20 | 'class': 'SuperResK1KXK1',
21 | 'in': 512,
22 | 'inner_class': 'ResK1KXK1',
23 | 'k': 3,
24 | 'out': 1024,
25 | 's': 2},
26 | { 'L': 3,
27 | 'btn': 512,
28 | 'class': 'SuperResK1KXK1',
29 | 'in': 1024,
30 | 'inner_class': 'ResK1KXK1',
31 | 'k': 3,
32 | 'out': 2048,
33 | 's': 2}]
34 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/README.md:
--------------------------------------------------------------------------------
1 | ***
2 | 
3 | ***
4 | ## Introduction
5 |
6 |
7 |
8 | The latency predictor based on Conv operations profiler, supporting Nvidia GPUs.
9 |
10 | Thanks to the sequential structure of the neural network, we can approximate the latency of the model by summing up the latency of each layer.
11 |
12 | First build a operations latency library containing the latency of sampling Conv operations under a large [configurations](python/config.in).
13 |
14 | Then use the `predictor.py` to predict the summary latency of each layer in the target network structure. The operation which is not in the library is obtained by Scipy Interpolations between other operations.
15 |
16 |
17 | ***
18 |
19 | Major features
20 |
21 | * **Sampling process with python example**
22 |
23 | `python`: the code how to generate the operations latency library on target device. [How to use](python/README.md).
24 |
25 | * **Nvidia GPUs TRT latency**
26 |
27 | `V100`: the sampling operations latency library for Nvidia GPU V100 based TRT with precision of FP32/FP16/INT8
28 |
29 | Other GPUs like P100/T4, could use the sampling code to generate the library like V100.
30 |
31 |
32 |
33 | ***
34 |
35 | ## Format for each element in the library
36 |
37 | ```python
38 | {Conv_type, Batch, In_C, In_H, In_W, Out_C, Kernel, Stride, ElmtFused} Latency
39 | ```
40 | * Conv_type: 'Regular' or 'Depthwise' convolution
41 | * Batch: batch size, typical = 1, 32, 64, 128
42 | * In_C: input_channels; Out_C: output_channels; In_C=Out_C*Ratio
43 | * In_H: input_height; In_W: input_width
44 | * Kernel: kernel size, typical = 1, 3, 5, 7
45 | * Stride: stride value for convolution, typical = 1, 2
46 | * ElmtFused: whether the elementwise sum operation of the relink structure is included
47 | * Latency: the profiling time of each element
48 |
49 |
50 | ## Format for each element in the predictor
51 | [("Regular", self.stride, elmtfused, self.kernel_size, 1, self.in_channels, input_resolution, self.out_channels)]
52 |
53 | ```python
54 | [Conv_type, Stride, ElmtFused, Kernel, Batch, In_C, In_H, Out_C]
55 | ```
56 | * Conv_type: 'Regular' or 'Depthwise'
57 | * Stride: stride value for convolution, typical = 1, 2
58 | * ElmtFused: whether the elementwise sum operation of the relink structure is included
59 | * Kernel: kernel size, typical = 1, 3, 5, 7
60 | * Batch: 1, specific batchsize in a hyper parameter for the predictor
61 | * In_C: input_channels; Out_C: output_channels
62 | * In_H: the width the feature map is equal to the height
63 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .predictor import OpProfiler
6 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/op_profiler.jpg:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:957880a2e8c01d075810b244742e73e373190ed4342cf34e567fde5b5e0a2d0f
3 | size 311735
4 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/python/README.md:
--------------------------------------------------------------------------------
1 | ***
2 | ### example
3 | 1. generate the sampling txt with the configurations.
4 | ```shell
5 | python sample.py --config path_to_config_file --nbits 8 --save-file sample
6 | ```
7 |
8 | 2. Use the shell to inference each convolution with specific program on device, generate log.
9 | ```shell
10 | sh sample.sh
11 | ```
12 |
13 | 3. read the log to generate the final lib.
14 |
15 | ```shell
16 | python read_log.py
17 | ```
18 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/python/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/lightweight-neural-architecture-search/8ccaf889fcd06079d268a355c765e9d0af071612/tinynas/latency/op_profiler/python/__init__.py
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/python/config.in:
--------------------------------------------------------------------------------
1 | batch 1
2 | elmt_fused 0
3 | filter_size 1 3 5 7
4 | min_feature_size 7
5 | max_feature_size 256
6 | number_feature_size 16
7 | output_channel 32 64 96 128 160 192 256 384 512 768 1024 1280 1536 1792 1920 2048
8 | stride 1 2
9 | type 0
10 | channel_ratio 4 2 1 0.5 0.25
11 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/python/read_log.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import argparse
6 | import ast
7 | import copy
8 | import os
9 | import sys
10 | import time
11 |
12 | import numpy as np
13 |
14 | # {Conv_type, Batch, In_C, In_H, In_W, Out_C, Kernel, Stride, ElmtFused} Latency
15 | str_format = '%s %d %d %d %d %d %d %d %d %d\n'
16 | Conv_type_dict = {0: 'Regular', 1: 'Depthwise'}
17 |
18 |
19 | def parse_args():
20 | parser = argparse.ArgumentParser()
21 | parser.add_argument('--log_file', type=str, default='log')
22 | parser.add_argument('--nbits', type=int, default=8)
23 | parser.add_argument('--save_file', type=str, default='../conv_data.out')
24 | args = parser.parse_args()
25 | return args
26 |
27 |
28 | def main():
29 | import pdb
30 | args = parse_args()
31 | lines = open('%s.int%d.txt' %
32 | (args.log_file, args.nbits)).read().splitlines()
33 | iter_flag = False
34 | lib_lines = []
35 | for line in lines:
36 | if 'iter-' in line:
37 | if iter_flag:
38 | exit()
39 | params = line.split(': ')[1].split(' ')
40 | params_line = '{%s}' % (','.join(params[:-1]))
41 | print(params_line)
42 | iter_flag = True
43 | if iter_flag and 'run time_ms: ' in line:
44 | iter_flag = False
45 | # "run time_ms: 4123.077000 ms"
46 | latency = float(line.split(' ')[2])
47 | lib_lines.append('%s %f' % (params_line, latency))
48 | print(latency)
49 | with open(args.save_file + '.int%d' % (args.nbits), 'w') as fw:
50 | fw.writelines('\n'.join(lib_lines))
51 |
52 |
53 | if __name__ == '__main__':
54 | main()
55 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/python/sample.sh:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | nbits="${2:-"8"}"
6 |
7 | DataFile="sample.int8.txt"
8 |
9 | LD_LIBRARY_PATH=sample_lib/:$LD_LIBRARY_PATH
10 | insmod /system/init/soc-nna.ko
11 |
12 | if [ ! -e $DataFile ]; then
13 | echo "Fail to open file"
14 | exit 1
15 | fi
16 |
17 | iter=0
18 |
19 | # {Conv_type, Batch, In_C, In_H, In_W, Out_C, Kernel, Stride, ElmtFused} Latency
20 | while read line
21 | do
22 | [ -z "$line" ] && continue
23 | set -- $line
24 | iter=$((iter+1))
25 | echo "iter-$iter: $line"
26 |
27 | Conv_type=$(($1))
28 | Batch=$(($2))
29 | In_C=$(($3))
30 | In_H=$(($4))
31 | In_W=$(($5))
32 | Out_C=$(($6))
33 | Kernel=$(($7))
34 | Stride=$(($8))
35 | # ElmtFused=$(($9))
36 | # Latency=$((${10}))
37 |
38 | # call venus_eval_test_uclibc, an example for profiling each convolution.
39 | if [ $iter -gt 3539 ]
40 | then
41 | ./venus_eval_test_uclibc $In_H $In_W $In_C $nbits $Out_C $nbits $Kernel $Kernel $Stride $nbits
42 | fi
43 | done < $DataFile
44 |
--------------------------------------------------------------------------------
/tinynas/latency/op_profiler/test_predictor.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import argparse
6 | import logging
7 | ###
8 | import os
9 |
10 | import predictor as opp
11 | import torch
12 | from nas.models import MasterNet
13 |
14 |
15 | def predict_the_latency(save_dir,
16 | plainnet_struct,
17 | resolution,
18 | device_name='V100',
19 | date_type='FP16',
20 | bs_list=[1, 32, 64],
21 | save_onnx=False):
22 |
23 | fw = open('%s/conv_test.out' % (device_name), 'w')
24 | the_model = MasterNet(
25 | num_classes=1000,
26 | structure_txt=plainnet_struct,
27 | no_create=False,
28 | out_indices=(4, ))
29 | print('the model is %s\n' % (str(the_model)))
30 |
31 | net_params = the_model.get_params_for_trt(resolution)
32 | # print(net_params)
33 | # remove other params, only conv and convDW
34 | net_params_conv = []
35 | for idx, net_param in enumerate(net_params):
36 | if net_param[0] in ['Regular', 'Depthwise']:
37 | net_params_conv.append(net_param)
38 | # print("idx %d: %s"%(idx, net_param))
39 | times = [0] * len(net_params_conv)
40 | for net_param_conv in net_params_conv:
41 | fw.write('%s %s\n' % (net_param_conv, 0))
42 |
43 | Predictor_opp = opp.OpProfiler(
44 | device_name=device_name, date_type=date_type)
45 | the_latency_list = []
46 | for batchsize in bs_list:
47 | _, the_latency = Predictor_opp(net_params_conv, times, batchsize)
48 | the_latency = the_latency / batchsize
49 | the_latency_list.append(the_latency_list)
50 | print('batchsize: %d, the TensorRT predict Latency is %.4f ms' %
51 | (batchsize, the_latency))
52 |
53 | fw.close()
54 |
55 | if save_onnx:
56 | for batchsize in bs_list:
57 | x = torch.randn(
58 | batchsize, 3, resolution, resolution, requires_grad=False)
59 | out_name = os.path.join(
60 | save_dir, '%s/R50_bs%d.onnx' % (device_name, batchsize))
61 | os.makedirs(os.path.dirname(out_name), exist_ok=True)
62 | torch.onnx.export(the_model, x, out_name, input_names=['input'])
63 |
64 | return the_latency_list
65 |
--------------------------------------------------------------------------------
/tinynas/latency/robust_gpu_predictor.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import argparse
6 | import logging
7 | import os
8 | import sys
9 | import time
10 |
11 | import numpy as np
12 | import torch
13 | from .builder import LATENCIES
14 |
15 |
16 | def __get_latency__(model, batch_size, image_size, channel, gpu,
17 | benchmark_repeat_times, fp16):
18 | device = torch.device('cuda:{}'.format(gpu))
19 | torch.backends.cudnn.benchmark = True
20 |
21 | torch.cuda.set_device(gpu)
22 | model = model.cuda(gpu)
23 | if fp16:
24 | model = model.half()
25 | dtype = torch.float16
26 | else:
27 | dtype = torch.float32
28 | if type(image_size) == list and len(image_size) == 2:
29 | the_image = torch.randn(
30 | batch_size,
31 | channel,
32 | image_size[0],
33 | image_size[1],
34 | dtype=dtype,
35 | device=device)
36 | else:
37 | the_image = torch.randn(
38 | batch_size,
39 | channel,
40 | image_size,
41 | image_size,
42 | dtype=dtype,
43 | device=device)
44 | model.eval()
45 | warmup_T = 3
46 | with torch.no_grad():
47 | for i in range(warmup_T):
48 | _ = model(the_image)
49 | start_timer = time.time()
50 | for repeat_count in range(benchmark_repeat_times):
51 | _ = model(the_image)
52 |
53 | end_timer = time.time()
54 | the_latency = (end_timer
55 | - start_timer) / float(benchmark_repeat_times) / batch_size
56 | return the_latency
57 |
58 | @LATENCIES.register_module(module_name = 'RobustGpuPredictor')
59 | class RobustGpuPredictor():
60 |
61 | def __init__(self,
62 | batch_size,
63 | image_size,
64 | gpu ,
65 | channel=3,
66 | fp16=False,
67 | repeat_times=30,
68 | **kwargs):
69 | assert isinstance(gpu, int), 'Must set enable_gpu=True in cfg'
70 | self.batch_size = batch_size
71 | self.image_size = image_size
72 | self.gpu = gpu
73 | self.channel = channel
74 | self.repeat_times = repeat_times
75 | self.fp16 = fp16
76 | assert isinstance(gpu, int)
77 |
78 | def __call__(self, model):
79 |
80 | robust_repeat_times = 10
81 | latency_list = []
82 | model = model.cuda(self.gpu)
83 | for repeat_count in range(robust_repeat_times):
84 | try:
85 | the_latency = __get_latency__(model, self.batch_size,
86 | self.image_size, self.channel,
87 | self.gpu,
88 | self.repeat_times,
89 | self.fp16)
90 | except Exception as e:
91 | print(e)
92 | the_latency = np.inf
93 |
94 | latency_list.append(the_latency)
95 |
96 | pass # end for
97 | latency_list.sort()
98 | avg_latency = np.mean(latency_list[2:8])
99 | std_latency = np.std(latency_list[2:8])
100 | return avg_latency #, std_latency
101 |
102 |
103 | def main():
104 | pass
105 |
106 |
107 | if __name__ == '__main__':
108 | main()
109 |
--------------------------------------------------------------------------------
/tinynas/models/README.md:
--------------------------------------------------------------------------------
1 | ## Models Definition module
2 |
3 | The basic network (supernet) is defined by the unified framework with the structure info list. CnnNet is the overall backbone network, which is composed of differet downsample stages with structure info list. A stage is composed of several blocks, such as Resnet bottleneck block, MobileV2 Depthwise block. Basic block is composed of 2D convolutions.
4 |
5 | ***
6 | ### **SuperModel**
7 | * **`cnnnet.py`**: Define the backbone network for CnnNet, such as classification and detection.
8 |
9 | ***
10 | ### **Typical Structure Info List for CnnNet**
11 | ```
12 | [{'class': 'ConvKXBNRELU', 'in': 3, 'out': 32, 's': 2, 'k': 3},
13 | {'class': 'SuperResK1KXK1', 'in': 32, 'out': 256, 's': 2, 'k': 3, 'L': 1, 'btn': 64},
14 | {'class': 'SuperResK1KXK1', 'in': 256, 'out': 512, 's': 2, 'k': 3, 'L': 1, 'btn': 128},
15 | {'class': 'SuperResK1KXK1', 'in': 512, 'out': 1024, 's': 2, 'k': 3, 'L': 1, 'btn': 256},
16 | {'class': 'SuperResK1KXK1', 'in': 1024, 'out': 2048, 's': 2, 'k': 3, 'L': 1, 'btn': 512}, ]
17 | ```
18 | ***
19 | ### **Supported Blocks**
20 | `Supported 2D CNN blocks:`
21 | ```
22 | __all_blocks__ = {
23 | 'ConvKXBN': ConvKXBN,
24 | 'ConvKXBNRELU': ConvKXBNRELU,
25 | 'BaseSuperBlock': BaseSuperBlock,
26 | 'ResK1KXK1': ResK1KXK1,
27 | 'ResK1KX': ResK1KX,
28 | 'ResKXKX': ResKXKX,
29 | 'ResK1DWK1': ResK1DWK1,
30 | 'ResK1DWSEK1': ResK1DWSEK1,
31 | 'SuperResK1KXK1': SuperResK1KXK1,
32 | 'SuperResK1KX': SuperResK1KX,
33 | 'SuperResKXKX': SuperResKXKX,
34 | 'SuperResK1DWK1': SuperResK1DWK1,
35 | 'SuperResK1DWSEK1': SuperResK1DWSEK1,
36 | 'SuperQuantResK1DWK1': SuperQuantResK1DWK1,
37 | }
38 | ```
39 | `Supported 3D CNN blocks:`
40 |
41 | ```
42 | __all_blocks_3D__ = {
43 | 'Conv3DKXBN': Conv3DKXBN,
44 | 'Conv3DKXBNRELU': Conv3DKXBNRELU,
45 | 'BaseSuperBlock3D': BaseSuperBlock3D,
46 | 'Res3DK1DWK1': Res3DK1DWK1,
47 | 'SuperRes3DK1DWK1': SuperRes3DK1DWK1,
48 | }
49 | ```
50 | **Note**:
51 |
52 | - `BaseSuperBlock` is the basic class for super block.
53 | - `SuperResK1KXK1` is the derived class from ``BaseSuperBlock`` to unit `L` class `ResK1KXK1`.
54 | - `SuperResK1DWK1` is the derived class from ``BaseSuperBlock`` to unit `L` class `ResK1DWK1`.
55 | - `SuperResK1DWSEK1` is the derived class from ``BaseSuperBlock`` to unit `L` class `ResK1DWSEK1`.
56 | - `SuperResK1KX` is the derived class from ``BaseSuperBlock`` to unit `L` class `ResK1KX`.
57 | - `SuperResKXKX` is the derived class from ``BaseSuperBlock`` to unit `L` class `ResKXKX`.
58 | - `SuperQuantResK1DWK1` is the derived class from ``SuperResK1DWK1``.
59 | - `SuperRes3DK1DWK1` is the derived class from ``BaseSuperBlock`` to unit `L` class `Res3DK1DWK1`.
60 | ***
61 | ### **Useful functions for masternet**
62 |
63 | `get_model_size`: Get the number of parameters of the network
64 |
65 | `get_flops`: Get the FLOPs of the network
66 |
67 | `get_layers`: Get the Conv layers of the network
68 |
69 | `get_latency`: Get the latency from predictor or benchmark
70 |
71 | `get_params_for_trt`: Get the paramters of the network for latency prediction.
72 |
73 | `get_max_feature`: Get the number of max feature map for MCU.
74 |
75 | `get_efficient_score`: Get efficient_score of the network.
76 |
77 | `madnas_forward_pre_GAP`: Get the madnas score of the network, which does not need forward on GPU and has very fast speed .
78 |
79 | `deepmad_forward_pre_GAP`: Get the deepmad score of the network, which does not need forward on GPU and has very fast speed.
80 |
81 | `stentr_forward_pre_GAP`: Get the spatio-temporal entropy score of the network, which does not need forward on GPU and has very fast speed.
82 |
83 | ***
84 |
--------------------------------------------------------------------------------
/tinynas/models/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .builder import build_model
6 | from .cnnnet import CnnNet
7 | from .cnn3dnet import Cnn3DNet
8 |
--------------------------------------------------------------------------------
/tinynas/models/base.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import ast
6 | import logging
7 | import os
8 | import sys
9 |
10 | from torch import nn
11 | from abc import ABC, abstractmethod
12 |
13 | class Model(ABC, nn.Module):
14 |
15 | def __init__(self,
16 | structure=None,
17 | logger=None):
18 | super().__init__()
19 | self.structure_info = structure
20 | self.logger = logger or logging
21 |
22 | if isinstance(structure, str):
23 | if os.path.exists(structure):
24 | with open(structure, 'r') as fid:
25 | self.structure_info = ''.join(
26 | [x.strip() for x in fid.readlines()])
27 | self.structure_info = ast.literal_eval(self.structure_info)
28 |
29 | @abstractmethod
30 | def forward(self, *args, **kwargs):
31 | pass
32 |
33 | @abstractmethod
34 | def get_model_size(self, return_list=False):
35 | pass
36 |
37 | @abstractmethod
38 | def get_flops(self, resolution):
39 | pass
40 |
41 | @abstractmethod
42 | def build(self, structure_info):
43 | pass
44 |
--------------------------------------------------------------------------------
/tinynas/models/blocks_cnn_2d/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .blocks_basic import (BaseSuperBlock, ConvKXBN, ConvKXBNRELU,
6 | network_weight_stupid_init)
7 | from .super_res_k1dwk1 import ResK1DWK1, SuperResK1DWK1
8 | from .super_res_k1dwsek1 import ResK1DWSEK1, SuperResK1DWSEK1
9 | from .super_quant_res_k1dwk1 import SuperQuantResK1DWK1
10 | from .super_res_k1kxk1 import ResK1KXK1, SuperResK1KXK1
11 | from .super_res_k1kx import ResK1KX, SuperResK1KX
12 | from .super_res_kxkx import ResKXKX, SuperResKXKX
13 |
14 | __all_blocks__ = {
15 | 'ConvKXBN': ConvKXBN,
16 | 'ConvKXBNRELU': ConvKXBNRELU,
17 | 'BaseSuperBlock': BaseSuperBlock,
18 | 'ResK1KXK1': ResK1KXK1,
19 | 'ResK1KX': ResK1KX,
20 | 'ResKXKX': ResKXKX,
21 | 'ResK1DWK1': ResK1DWK1,
22 | 'ResK1DWSEK1': ResK1DWSEK1,
23 | 'SuperResK1KXK1': SuperResK1KXK1,
24 | 'SuperResK1KX': SuperResK1KX,
25 | 'SuperResKXKX': SuperResKXKX,
26 | 'SuperResK1DWK1': SuperResK1DWK1,
27 | 'SuperResK1DWSEK1': SuperResK1DWSEK1,
28 | 'SuperQuantResK1DWK1': SuperQuantResK1DWK1,
29 | }
30 |
--------------------------------------------------------------------------------
/tinynas/models/blocks_cnn_2d/super_quant_res_k1dwk1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import copy
6 | import os
7 | import sys
8 | from .super_res_k1dwk1 import SuperResK1DWK1
9 |
10 | class SuperQuantResK1DWK1(SuperResK1DWK1):
11 |
12 | def __init__(self,
13 | structure_info,
14 | no_create=False,
15 | dropout_channel=None,
16 | dropout_layer=None,
17 | **kwargs):
18 | '''
19 |
20 | :param structure_info: {
21 | 'class': 'SuperResK1DWK1',
22 | 'in': in_channels,
23 | 'out': out_channels,
24 | 's': stride (default=1),
25 | 'k': kernel_size,
26 | 'p': padding (default=(k-1)//2,
27 | 'g': grouping (default=1),
28 | 'btn':, bottleneck_channels,
29 | 'L': num_inner_layers,
30 | }
31 | :param NAS_mode:
32 | '''
33 | super().__init__(
34 | structure_info=structure_info,
35 | no_create=no_create,
36 | dropout_channel=dropout_channel,
37 | dropout_layer=dropout_layer,
38 | **kwargs)
39 |
40 |
41 | __module_blocks__ = {
42 | 'SuperQuantResK1DWK1': SuperQuantResK1DWK1,
43 | }
44 |
--------------------------------------------------------------------------------
/tinynas/models/blocks_cnn_3d/__init__.py:
--------------------------------------------------------------------------------
1 | from .blocks_basic_3D import *
2 | from .super_res3d_k1dwk1 import *
3 |
4 |
5 | __all_blocks_3D__ = {
6 | 'Conv3DKXBN': Conv3DKXBN,
7 | 'Conv3DKXBNRELU': Conv3DKXBNRELU,
8 | 'BaseSuperBlock3D': BaseSuperBlock3D,
9 | 'Res3DK1DWK1': Res3DK1DWK1,
10 | 'SuperRes3DK1DWK1': SuperRes3DK1DWK1,
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/tinynas/models/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | MODELS= Registry('models')
8 |
9 | def build_model(cfg, default_args: dict = None):
10 | """ build model given a model name
11 |
12 | Args:
13 | name (str, optional): Model name, if None, default model
14 | will be used.
15 | default_args (dict, optional): Default initialization arguments.
16 | """
17 | return build_from_cfg(cfg, MODELS, default_args=default_args)
18 |
19 |
--------------------------------------------------------------------------------
/tinynas/scores/README.md:
--------------------------------------------------------------------------------
1 | ## Score module
2 |
3 | ***
4 | ### **MadNAS Score**:
5 | The version of mathematical formula calculation, which does not need forward on GPU and has very fast speed.
6 |
7 | ***
8 | ### **DeepMad Score**:
9 | The version of mathematical formula calculation, which does not need forward on GPU and has very fast speed.
10 |
11 | ### **Random Score**:
12 | Random generated scores for debug.
13 |
14 | ### **Ensemble Score**:
15 | Calculate combinated score of multiple score_type with ratio.
16 |
17 |
18 | ### **STEntr Score**:
19 | Calculate spatio-temporal entropy score.
20 |
--------------------------------------------------------------------------------
/tinynas/scores/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .builder import build_score
6 | from .compute_madnas import ComputeMadnasScore
7 | from .compute_random import ComputeRandomScore
8 | from .compute_ensemble import ComputeEnsembleScore
9 | from .compute_deepmad import ComputeDeepMadScore
10 | from .compute_stentr import ComputeStentrScore
11 |
12 |
--------------------------------------------------------------------------------
/tinynas/scores/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | SCORES = Registry('scores')
8 |
9 | def build_score(cfg, default_args: dict = None):
10 | """ build score given a score name
11 |
12 | Args:
13 | name (str, optional): Score name, if None, default score
14 | will be used.
15 | default_args (dict, optional): Default initialization arguments.
16 | """
17 | return build_from_cfg(cfg, SCORES, default_args=default_args)
18 |
19 |
--------------------------------------------------------------------------------
/tinynas/scores/compute_ensemble.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import logging
6 | import os
7 | import sys
8 | import time
9 | from abc import ABCMeta, abstractmethod
10 |
11 | import numpy as np
12 | import torch
13 |
14 |
15 | from .builder import SCORES, build_score
16 |
17 | @SCORES.register_module(module_name = 'ensemble')
18 | class ComputeEnsembleScore(metaclass=ABCMeta):
19 |
20 | def __init__(self, scores = None, ratio = 1, logger = None, **kwargs):
21 |
22 | self.ratio = ratio
23 | self.logger = logger or logging
24 | self.compute_scores = []
25 | for cfg in scores:
26 | default_args = {'logger': self.logger}
27 |
28 | compute_score = build_score(cfg, default_args = default_args)
29 | self.compute_scores.append(compute_score)
30 |
31 | def __call__(self, model):
32 | info = {}
33 | info['avg_nas_score'] = 0
34 | info['std_nas_score'] = 0
35 | info['nas_score_list'] = 0
36 | timer_start = time.time()
37 |
38 | for compute_score in self.compute_scores:
39 | score_info = compute_score(model)
40 | for k, v in info.items():
41 | info[k] += score_info[k] * self.ratio
42 | timer_end = time.time()
43 | info['time'] = timer_end - timer_start
44 |
45 | self.logger.debug('avg_score:%s, consume time is %f ms' %
46 | (info['avg_nas_score'], info['time'] * 1000))
47 |
48 | return info
49 |
50 |
51 | def main():
52 | pass
53 |
54 |
55 | if __name__ == '__main__':
56 | main()
57 | pass
58 |
--------------------------------------------------------------------------------
/tinynas/scores/compute_madnas.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import logging
6 | import os
7 | import sys
8 | import time
9 | from abc import ABCMeta, abstractmethod
10 |
11 | import numpy as np
12 | import torch
13 |
14 |
15 | from .builder import SCORES
16 |
17 | @SCORES.register_module(module_name = 'madnas')
18 | class ComputeMadnasScore(metaclass=ABCMeta):
19 |
20 | def __init__(self, image_size = 224, multi_block_ratio = [0, 0, 1,1,6], ratio = 1, init_std = 1, init_std_act = 1, logger=None, **kwargs):
21 | self.init_std = init_std
22 | self.init_std_act = init_std_act
23 | self.resolution = image_size
24 | self.ratio_coef = multi_block_ratio
25 | self.ratio = ratio
26 |
27 | self.logger = logger or logging
28 |
29 | def ratio_score(self, stages_num, block_std_list):
30 |
31 | if stages_num != len(self.ratio_coef):
32 | raise ValueError(
33 | 'the length of the stage_features_list (%d) must be equal to the length of ratio_coef (%d)'
34 | % (stages_num, len(self.ratio_coef)))
35 | self.logger.debug(
36 | 'len of stage_features_list:%d, len of block_std_list:%d %s' %
37 | (stages_num, len(block_std_list), [std for std in block_std_list]))
38 | self.logger.debug(
39 | 'stage_idx:%s, stage_block_num:%s, stage_layer_num:%s' %
40 | (self.stage_idx, self.stage_block_num, self.stage_layer_num))
41 |
42 | nas_score_list = []
43 | for idx, ratio in enumerate(self.ratio_coef):
44 | if ratio == 0:
45 | nas_score_list.append(0.0)
46 | continue
47 |
48 | # compute std scaling
49 | nas_score_std = 0.0
50 | for idx1 in range(self.stage_block_num[idx]):
51 | nas_score_std += block_std_list[idx1]
52 |
53 | # larger channel and larger resolution, larger performance.
54 | resolution_stage = self.resolution // (2**(idx + 1))
55 | nas_score_feat = np.log(self.stage_channels[idx])
56 | # different stage with the different feature map ratio (2**(idx+6))/(4**(idx+1))
57 | nas_score_stage = nas_score_std + nas_score_feat
58 | # layer_num_idx = self.stage_layer_num[idx]
59 | self.logger.debug(
60 | 'stage:%d, nas_score_stage:%.3f, score_feat:%.3f, log_std:%.3f, resolution:%d'
61 | % (idx, nas_score_stage, nas_score_feat, nas_score_std,
62 | resolution_stage))
63 |
64 | nas_score_list.append(nas_score_stage * ratio)
65 | self.logger.debug('nas_score:%s' % (np.sum(nas_score_list)))
66 |
67 | return nas_score_list
68 |
69 | def __call__(self, model):
70 | info = {}
71 | timer_start = time.time()
72 | self.stage_idx, self.stage_block_num, self.stage_layer_num, self.stage_channels, self.stage_feature_map_size = model.get_stage_info(self.resolution)
73 | kwarg = {'init_std': self.init_std, 'init_std_act': self.init_std_act}
74 |
75 | block_std_list = model.madnas_forward_pre_GAP(**kwarg)
76 | nas_score_once = self.ratio_score(len(self.stage_idx), block_std_list)
77 |
78 | timer_end = time.time()
79 | nas_score_once = np.array(nas_score_once) * self.ratio
80 | avg_nas_score = np.sum(nas_score_once)
81 |
82 | info['avg_nas_score'] = avg_nas_score
83 | info['std_nas_score'] = avg_nas_score
84 | info['nas_score_list'] = nas_score_once
85 | info['time'] = timer_end - timer_start
86 | self.logger.debug('avg_score:%s, consume time is %f ms' %
87 | (avg_nas_score, info['time'] * 1000))
88 |
89 | return info
90 |
91 |
92 | def main():
93 | pass
94 |
95 |
96 | if __name__ == '__main__':
97 | main()
98 | pass
99 |
--------------------------------------------------------------------------------
/tinynas/scores/compute_random.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import logging
6 | import os
7 | import sys
8 | import time
9 | from abc import ABCMeta, abstractmethod
10 | from random import random
11 |
12 | import numpy as np
13 | import torch
14 | from torch import nn
15 | from torch.nn import functional as F
16 |
17 |
18 | from .builder import SCORES
19 |
20 | @SCORES.register_module(module_name = 'random')
21 | class ComputeRandomScore(metaclass=ABCMeta):
22 |
23 | def __init__(self, cfg, ratio = 1, logger=None, **kwargs):
24 | # TODO: to be finished after adding nas for transformer
25 | self.gpu = None
26 | self.ratio = ratio
27 |
28 | if logger is None:
29 | self.logger = logging
30 | else:
31 | self.logger = logger
32 |
33 | def __call__(self, model):
34 | '''
35 |
36 | Args:
37 | model: Model to be compute scores
38 |
39 | Returns:
40 | A dictionary. Key 'avg_nas_score' is necessary. Others ['std_nas_score', 'nas_score_list', 'time'] are
41 | optional.
42 |
43 | '''
44 | model.eval()
45 | model.requires_grad_(False)
46 |
47 | info = {}
48 | nas_score_list = []
49 | timer_start = time.time()
50 |
51 | # TODO: calculate scores
52 | nas_score_list.append([random() * 100])
53 |
54 | timer_end = time.time()
55 |
56 | nas_score_list = np.array(nas_score_list) * self.ratio
57 | avg_nas_score = np.mean(np.sum(nas_score_list, axis=1))
58 | std_nas_score = np.std(np.sum(nas_score_list, axis=1))
59 |
60 | info['avg_nas_score'] = avg_nas_score
61 | info['std_nas_score'] = std_nas_score
62 | info['nas_score_list'] = nas_score_list
63 | info['time'] = timer_end - timer_start
64 | self.logger.debug('avg_score:%s, consume time is %f ms\n' %
65 | (avg_nas_score, info['time'] * 1000))
66 |
67 | del model
68 | torch.cuda.empty_cache()
69 | return info
70 |
71 |
72 | def main():
73 | model = nn.Conv2d(3, 3, 3)
74 | score_compute = ComputeRandomScore(None)
75 | print(score_compute(model))
76 |
77 |
78 | if __name__ == '__main__':
79 | main()
80 | pass
81 |
--------------------------------------------------------------------------------
/tinynas/scores/compute_stentr.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import logging
6 | import os
7 | import sys
8 | import time
9 | from abc import ABCMeta, abstractmethod
10 |
11 | import numpy as np
12 | import torch
13 |
14 |
15 | from .builder import SCORES
16 |
17 | @SCORES.register_module(module_name = 'stentr')
18 | class ComputeStentrScore(metaclass=ABCMeta):
19 |
20 | def __init__(self, frames = 13, image_size = 160, multi_block_ratio = [0, 0, 1,1,6], ratio = 1, logger=None, **kwargs):
21 | self.frames = frames
22 | self.resolution = image_size
23 | self.ratio_coef = multi_block_ratio
24 | self.ratio = ratio
25 |
26 | self.logger = logger or logging
27 |
28 | def ratio_score(self, stages_num, block_std_list):
29 |
30 | if stages_num != len(self.ratio_coef):
31 | raise ValueError(
32 | 'the length of the stage_features_list (%d) must be equal to the length of ratio_coef (%d)'
33 | % (stages_num, len(self.ratio_coef)))
34 | self.logger.debug(
35 | 'len of stage_features_list:%d, len of block_std_list:%d %s' %
36 | (stages_num, len(block_std_list), [std for std in block_std_list]))
37 | self.logger.debug(
38 | 'stage_idx:%s, stage_block_num:%s, stage_layer_num:%s' %
39 | (self.stage_idx, self.stage_block_num, self.stage_layer_num))
40 |
41 | nas_score_list = []
42 | for idx, ratio in enumerate(self.ratio_coef):
43 | if ratio == 0:
44 | nas_score_list.append(0.0)
45 | continue
46 |
47 | # compute std scaling
48 | nas_score_std = 0.0
49 | for idx1 in range(self.stage_block_num[idx]):
50 | nas_score_std += block_std_list[idx1]
51 |
52 | # larger channel and larger resolution, larger performance.
53 | resolution_stage = self.resolution // (2**(idx + 1))
54 | nas_score_feat = np.log(self.stage_channels[idx])
55 | # different stage with the different feature map ratio (2**(idx+6))/(4**(idx+1))
56 | nas_score_stage = nas_score_std + nas_score_feat
57 | # layer_num_idx = self.stage_layer_num[idx]
58 | self.logger.debug(
59 | 'stage:%d, nas_score_stage:%.3f, score_feat:%.3f, log_std:%.3f, resolution:%d'
60 | % (idx, nas_score_stage, nas_score_feat, nas_score_std,
61 | resolution_stage))
62 |
63 | nas_score_list.append(nas_score_stage * ratio)
64 | self.logger.debug('nas_score:%s' % (np.sum(nas_score_list)))
65 |
66 | return nas_score_list
67 |
68 | def __call__(self, model):
69 | info = {}
70 | timer_start = time.time()
71 | self.stage_idx, self.stage_block_num, self.stage_layer_num, self.stage_channels, self.stage_feature_map_size = model.get_stage_info(self.resolution)
72 | # kwarg = {'init_std': self.init_std, 'init_std_act': self.init_std_act}
73 | kwarg = {'frames': self.frames ,'resolution': self.resolution}
74 | block_std_list = model.stentr_forward_pre_GAP(**kwarg)
75 | nas_score_once = self.ratio_score(len(self.stage_idx), block_std_list)
76 |
77 | timer_end = time.time()
78 | nas_score_once = np.array(nas_score_once) * self.ratio
79 | avg_nas_score = np.sum(nas_score_once)
80 |
81 | info['avg_nas_score'] = avg_nas_score
82 | info['std_nas_score'] = avg_nas_score
83 | info['nas_score_list'] = nas_score_once
84 | info['time'] = timer_end - timer_start
85 | self.logger.debug('avg_score:%s, consume time is %f ms' %
86 | (avg_nas_score, info['time'] * 1000))
87 |
88 | return info
89 |
90 |
91 | def main():
92 | pass
93 |
94 |
95 | if __name__ == '__main__':
96 | main()
97 | pass
98 |
--------------------------------------------------------------------------------
/tinynas/searchers/README.md:
--------------------------------------------------------------------------------
1 | ## Search Searcher module
2 | Searcher module can be built from a config file and run search process easily, which can execute in local-mode(single-process) or distribute-mode(multi-process). During searching, the master process will cache intermediate results, and export and save the final best structure.
3 |
4 | - **Searcher Class**
5 |
6 | `__init__`: Setup searching envirioment and then build strategy, sychonizer and population.
7 |
8 | `run`: Execute search loop and export the best structure info.
9 |
10 | `search_loop`: Master process collect and assgin newest population with workers and cache intermediate results. Then all processes execute search step.
11 |
12 | `search_step`: In search step, all processes pick a random structure info from population and then mutate a new structure info using strategy. If the new network meets the budget and has a high score, we will insert it to the population.
13 |
14 | `export_cache_generation`: cache the search intermediate population every log_freq .
15 |
16 | `export_result`: save and export best network structure info.
17 |
18 | - **Synchonizer Class**
19 |
20 | Sychonize population information between master and workers using mpi asynchronous communication.
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tinynas/searchers/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .base import BaseSearcher
6 | from .searcher import Searcher
7 | from .synchonizer import Synchonizer
8 | from .builder import build_searcher
9 |
--------------------------------------------------------------------------------
/tinynas/searchers/base.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from abc import ABC, abstractmethod
6 | from modelscope.utils.config import Config
7 |
8 | class BaseSearcher(ABC):
9 | def __init__(self, cfg_file: str):
10 | """ Searcher basic init, should be called in derived class
11 |
12 | Args:
13 | cfg_file: Path to configuration file.
14 | arg_parse_fn: Same as ``parse_fn`` in :obj:`Config.to_args`.
15 | """
16 | self.cfg = Config.from_file(cfg_file)
17 |
18 | @abstractmethod
19 | def run(self, *args, **kwargs):
20 | """ search process
21 |
22 | Train process should be implemented for specific task or
23 | model, releated paramters have been intialized in
24 | ``BaseSearcher.__init__`` and should be used in this function
25 | """
26 | pass
27 |
--------------------------------------------------------------------------------
/tinynas/searchers/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | SEARCHERS = Registry('searchers')
8 |
9 | def build_searcher(name: str = 'default_searcher', default_args: dict = None):
10 | """ build searcher given a searcher name
11 |
12 | Args:
13 | name (str, optional): Searcher name, if None, default searcher
14 | will be used.
15 | default_args (dict, optional): Default initialization arguments.
16 | """
17 | cfg = dict(type=name)
18 | return build_from_cfg(cfg, SEARCHERS, default_args=default_args)
19 |
20 |
--------------------------------------------------------------------------------
/tinynas/spaces/README.md:
--------------------------------------------------------------------------------
1 | ## Search Space module
2 | ***
3 | **For NAS, search space is very important. Referring to previous network design experience, designing the search space you want can ensure effective search results.**
4 | ***
5 |
6 | ### **Supported Search Space**
7 | * `space_k1kxk1.py`: Base Resnet-like search space for Classification and Detection.
8 | * `space_k1dwk1.py`: Base MobileNetV2-like search space.
9 | * `space_k1dwsek1.py`: Base MobileNetV2-se block search space.
10 | * `space_k1kx.py`: Base small and tiny DAMO-YOLO search space.
11 | * `space_kxkx.py`: Base medium DAMO-YOLO search space.
12 | * `space_quant_k1dwk1.py`: Base search space for Quantization search.
13 | * `space_3d_k1dwk1.py`: Base search space for 3D CNN search.
14 |
--------------------------------------------------------------------------------
/tinynas/spaces/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .base import BaseSpace
6 | from .builder import build_space
7 | from .space_k1kxk1 import Spacek1kxk1
8 | from .space_k1dwk1 import Spacek1dwk1
9 | from .space_k1dwsek1 import Spacek1dwsek1
10 | from .space_k1kx import Spacek1kx
11 | from .space_kxkx import Spacekxkx
12 | from .space_3d_k1dwk1 import Space3Dk1dwk1
13 | from .space_quant_k1dwk1 import SpaceQuantk1dwk1
14 |
--------------------------------------------------------------------------------
/tinynas/spaces/base.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 | import copy
5 | from numpy import random
6 | from abc import ABC, abstractmethod
7 | from .space_utils import (adjust_structures_inplace, __check_block_structure_info_list_valid__)
8 |
9 | class BaseSpace(ABC):
10 | def __init__(self, name = None):
11 | self.name = name
12 |
13 | @abstractmethod
14 | def mutate(self, *args, **kwargs):
15 | return None
16 |
17 | def choice(self,):
18 | return None
19 |
20 | def __call__(self, *args, **kwargs):
21 | return self.mutate(*args, **kwargs)
22 |
23 | class CnnBaseSpace(BaseSpace):
24 | def __init__(self, name = None, image_size = 224, block_num = 2, exclude_stem = False, budget_layers=None, **kwargs):
25 |
26 | super().__init__(name)
27 | self.budget_layers = budget_layers
28 | self.block_num = block_num
29 | self.exclude_stem = exclude_stem
30 | self.image_size = image_size
31 | self.mutators = {}
32 |
33 | def mutate(self, block_structure_info_list,
34 | minor_mutation=False, *args, **kwargs):
35 | block_structure_info_list = copy.deepcopy(block_structure_info_list)
36 |
37 | for mutate_count in range(self.block_num):
38 | is_valid = False
39 | new_block_structure_info_list = block_structure_info_list
40 |
41 | for idx in range(len(block_structure_info_list)):
42 | random_id = random.randint(0, len(block_structure_info_list) - 1)
43 |
44 | if self.exclude_stem:
45 | while random_id == 0:
46 | random_id = random.randint(
47 | 0,
48 | len(block_structure_info_list) - 1)
49 |
50 | mutated_block = self.mutators[block_structure_info_list[random_id] ['class']](
51 | random_id,
52 | block_structure_info_list,
53 | minor_mutation=minor_mutation)
54 |
55 | if mutated_block is None:
56 | continue
57 |
58 | new_block_structure_info_list = copy.deepcopy(block_structure_info_list)
59 | new_block_structure_info_list[random_id] = mutated_block
60 |
61 | adjust_structures_inplace(new_block_structure_info_list, self.image_size)
62 | if __check_block_structure_info_list_valid__(new_block_structure_info_list, self.budget_layers):
63 | break
64 | pass # end while not is_valid:
65 | block_structure_info_list = new_block_structure_info_list
66 |
67 | return block_structure_info_list
68 |
--------------------------------------------------------------------------------
/tinynas/spaces/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | SPACES = Registry('spaces')
8 |
9 | def build_space(cfg, default_args: dict = None):
10 | """ build space given a space name
11 |
12 | Args:
13 | name (str, optional): Space name, if None, default space
14 | will be used.
15 | default_args (dict, optional): Default initialization arguments.
16 | """
17 | return build_from_cfg(cfg, SPACES, default_args=default_args)
18 |
19 |
--------------------------------------------------------------------------------
/tinynas/spaces/mutator/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .base import Mutator
6 | from .builder import *
7 | from .basic_mutators import *
8 | from .conv_bn_relu_mutator import *
9 | from .conv3d_bn_relu_mutator import *
10 | from .super_res_k1kxk1_mutator import *
11 | from .super_res_k1dwk1_mutator import *
12 | from .super_res_k1kx_mutator import *
13 | from .super_res3d_k1dwk1_mutator import *
14 | from .super_quant_res_k1dwk1_mutator import *
15 |
16 |
--------------------------------------------------------------------------------
/tinynas/spaces/mutator/base.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from typing import (Any, Iterable, List, Optional, Tuple, cast)
6 | import random
7 | from .builder import MUTATORS
8 | Choice = Any
9 |
10 | class Sampler:
11 | """
12 | Handles `Mutator.choice()` calls.
13 | """
14 |
15 | def choice(self, candidates: List[Choice], *args, **kwargs):
16 | raise NotImplementedError()
17 |
18 | def mutation_start(self, *args, **kwargs):
19 | pass
20 |
21 | def mutation_end(self, *args, **kwargs):
22 | pass
23 |
24 |
25 | class RandomSampler(Sampler):
26 | def choice(self, candidates, *args, **kwargs):
27 | return random.choice(candidates)
28 |
29 | @MUTATORS.register_module(module_name = 'BaseMutator')
30 | class Mutator:
31 |
32 | def __init__(self, sampler = None, candidates = None, *args, **kwargs):
33 | self.sampler: Optional[Sampler] = sampler
34 | self.candidates = candidates
35 | if self.sampler is None:
36 | self.sampler = RandomSampler()
37 | self._length = len(self.candidates)
38 |
39 | def length(self):
40 | return self._length
41 |
42 | def bind_sampler(self, sampler: Sampler) -> 'Mutator':
43 | """
44 | Set the sampler which will handle `Mutator.choice` calls.
45 | """
46 | self.sampler = sampler
47 | return self
48 |
49 | def __call__(self, *args, **kwargs) ->None:
50 | return self.mutate(*args, **kwargs)
51 |
52 | def mutate(self, *args, **kwargs) -> None:
53 | """
54 | Abstract method to be implemented by subclass.
55 | Mutate a model in place.
56 | """
57 | ret = self.sampler.choice(list(self.candidates, *args, **kwargs))
58 | return ret
59 |
60 | def sample(self, *args, **kwargs) -> None:
61 | """
62 | Abstract method to be implemented by subclass.
63 | Mutate a model in place.
64 | """
65 | ret = self.sampler.choice(list(self.candidates, *args, **kwargs))
66 | return ret
67 |
68 |
69 |
--------------------------------------------------------------------------------
/tinynas/spaces/mutator/basic_mutators.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from numpy import random
6 | from .base import Mutator
7 | from .builder import MUTATORS
8 | from ..space_utils import smart_round
9 |
10 | @MUTATORS.register_module(module_name = 'ChannelMutator')
11 | class ChannelMutator(Mutator):
12 | def __init__(self, candidates, the_maximum_channel = 2048, *args, **kwargs):
13 | super().__init__(candidates = candidates)
14 | self.the_maximum_channel = the_maximum_channel
15 |
16 | def mutate(self, channels, *args, **kwargs):
17 | scale = self.sample()
18 | new_channels = smart_round(scale * channels)
19 | new_channels = min(self.the_maximum_channel, new_channels)
20 | return new_channels
21 |
22 | @MUTATORS.register_module(module_name = 'KernelMutator')
23 | class KernelMutator(Mutator):
24 | def __init__(self, candidates, *args, **kwargs):
25 | super().__init__(candidates = candidates)
26 |
27 | def mutate(self, kernel_size, *args, **kwargs):
28 | for i in range(self.length()):
29 | new_kernel_size = self.sample()
30 | if new_kernel_size != kernel_size :
31 | break
32 | return new_kernel_size
33 |
34 | @MUTATORS.register_module(module_name = 'LayerMutator')
35 | class LayerMutator(Mutator):
36 | def __init__(self, candidates, *args, **kwargs):
37 | super().__init__(candidates = candidates)
38 |
39 | def mutate(self, layer, *args, **kwargs):
40 | for i in range(self.length()):
41 | new_layer = layer + self.sample()
42 | new_layer = max(1, new_layer)
43 | if new_layer != layer:
44 | break
45 | return new_layer
46 |
47 | @MUTATORS.register_module(module_name = 'BtnMutator')
48 | class BtnMutator(Mutator):
49 | def __init__(self, candidates, *args, **kwargs):
50 | super().__init__(candidates = candidates)
51 |
52 | def mutate(self, btn_ratio, *args, **kwargs):
53 | for i in range(self.length()):
54 | new_btn_ratio = self.sample()
55 | if new_btn_ratio != btn_ratio:
56 | break
57 | return new_btn_ratio
58 |
59 | @MUTATORS.register_module(module_name = 'NbitsMutator')
60 | class NbitsMutator(Mutator):
61 | def __init__(self, candidates, *args, **kwargs):
62 | super().__init__(candidates = candidates)
63 |
64 | def mutate(self, nbits, *args, **kwargs):
65 | # avoid the endless loop
66 | if self.length() == 1 and nbits in self.candidates:
67 | return nbits
68 | ind = self.candidates.index(nbits)
69 | new_ind = ind
70 |
71 | while new_ind == ind:
72 | new_ind = random.choice((ind - 1, ind + 1))
73 | new_ind = max(0, new_ind)
74 | new_ind = min(self.length() - 1, new_ind)
75 | return self.candidates[new_ind]
76 |
77 | @MUTATORS.register_module(module_name = 'NbitsListMutator')
78 | class NbitsListMutator(Mutator):
79 | def __init__(self, candidates, nbits_ratio,*args, **kwargs):
80 | super().__init__(candidates = candidates)
81 | self.mutator = NbitsMutator(candidates = candidates)
82 | self.nbits_ratio = nbits_ratio
83 |
84 | def mutate(self, nbits_list, L, *args, **kwargs):
85 | if isinstance(nbits_list, int):
86 | return self.mutator(nbits_list)
87 | else:
88 | inner_layer = len(nbits_list)//L
89 | for layer_idx in range(L):
90 | if random.uniform(0, 1) > self.nbits_ratio:
91 | nbits_list[layer_idx*inner_layer:(layer_idx+1)*inner_layer] = \
92 | [self.mutator(nbits_list[layer_idx*inner_layer])]*inner_layer
93 | return nbits_list
94 |
--------------------------------------------------------------------------------
/tinynas/spaces/mutator/builder.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from modelscope.utils.registry import Registry, build_from_cfg
6 |
7 | MUTATORS= Registry('mutators')
8 |
9 | def build_mutator(name = 'BaseMutator', default_args: dict = None):
10 | cfg = dict(type=name)
11 | return build_from_cfg(cfg, MUTATORS, default_args=default_args)
12 |
13 | def build_channel_mutator(default_args: dict =None):
14 | return build_mutator('ChannelMutator', default_args = default_args)
15 |
16 | def build_layer_mutator(default_args: dict =None):
17 | return build_mutator('LayerMutator', default_args = default_args)
18 |
19 | def build_kernel_mutator(default_args: dict =None):
20 | return build_mutator('KernelMutator', default_args = default_args)
21 |
22 | def build_btn_mutator(default_args: dict =None):
23 | return build_mutator('BtnMutator', default_args = default_args)
24 |
25 | def build_nbits_list_mutator(default_args: dict =None):
26 | return build_mutator('NbitsListMutator', default_args = default_args)
27 |
--------------------------------------------------------------------------------
/tinynas/spaces/mutator/conv3d_bn_relu_mutator.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import bisect
6 | import copy
7 | import os
8 | import random
9 | import sys
10 |
11 | from ..space_utils import smart_round
12 | from .builder import *
13 |
14 | @MUTATORS.register_module(module_name = 'Conv3DKXBNRELU')
15 | class Conv3DKXBNRELUMutator():
16 | def __init__(self, stem_mutate_method_list,
17 | search_channel_list,
18 | search_kernel_size_list,
19 | the_maximum_channel,
20 | the_maximum_stem_channel:int =32,
21 | the_minimum_stem_channel:int = None,
22 | *args, **kwargs):
23 |
24 | kwargs.update(dict(candidates = stem_mutate_method_list))
25 | self.method_mutator = build_mutator(default_args = kwargs)
26 |
27 | kwargs.update(dict(candidates = search_channel_list, the_maximum_channel = the_maximum_channel))
28 | self.channel_mutator = build_channel_mutator(kwargs)
29 |
30 | kwargs = dict(candidates = search_kernel_size_list )
31 | self.kernel_mutator = build_kernel_mutator(kwargs)
32 | self.the_maximum_stem_channel = the_maximum_stem_channel
33 | self.the_minimum_stem_channel = the_minimum_stem_channel
34 |
35 |
36 | def __call__(self, block_id, structure_info_list, *args, **kwargs):
37 |
38 | structure_info = structure_info_list[block_id]
39 |
40 | if block_id == len(structure_info_list) - 1:
41 | return structure_info
42 |
43 | if block_id < len(structure_info_list) - 1:
44 | structure_info_next = structure_info_list[block_id + 1]
45 | structure_info = copy.deepcopy(structure_info)
46 | random_mutate_method = self.method_mutator()
47 |
48 | if random_mutate_method == 'out':
49 | new_out = self.channel_mutator(structure_info['out'])
50 | # Add the constraint: the maximum output of the stem block is 128
51 | new_out = min(self.the_maximum_stem_channel, new_out)
52 | if self.the_minimum_stem_channel:
53 | new_out = max(self.the_minimum_stem_channel, new_out)
54 |
55 | if block_id < len(structure_info_list) - 1:
56 | new_out = min(structure_info_next['out'], new_out)
57 | structure_info['out'] = new_out
58 | return structure_info
59 |
60 | if random_mutate_method == 'k':
61 | new_k = self.kernel_mutator(structure_info['k'])
62 | structure_info['k'] = new_k
63 | return structure_info
64 |
65 |
--------------------------------------------------------------------------------
/tinynas/spaces/mutator/conv_bn_relu_mutator.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import bisect
6 | import copy
7 | import os
8 | import random
9 | import sys
10 |
11 | from ..space_utils import smart_round
12 | from .builder import *
13 |
14 | @MUTATORS.register_module(module_name = 'ConvKXBNRELU')
15 | class ConvKXBNRELUMutator():
16 | def __init__(self, stem_mutate_method_list,
17 | search_channel_list,
18 | search_kernel_size_list,
19 | the_maximum_channel,
20 | the_maximum_stem_channel:int =32,
21 | the_minimum_stem_channel:int = None,
22 | *args, **kwargs):
23 |
24 | kwargs.update(dict(candidates = stem_mutate_method_list))
25 | self.method_mutator = build_mutator(default_args = kwargs)
26 |
27 | kwargs.update(dict(candidates = search_channel_list, the_maximum_channel = the_maximum_channel))
28 | self.channel_mutator = build_channel_mutator(kwargs)
29 |
30 | kwargs = dict(candidates = search_kernel_size_list )
31 | self.kernel_mutator = build_kernel_mutator(kwargs)
32 | self.the_maximum_stem_channel = the_maximum_stem_channel
33 | self.the_minimum_stem_channel = the_minimum_stem_channel
34 |
35 |
36 | def __call__(self, block_id, structure_info_list, *args, **kwargs):
37 |
38 | structure_info = structure_info_list[block_id]
39 |
40 | if block_id == len(structure_info_list) - 1:
41 | return structure_info
42 |
43 | if block_id < len(structure_info_list) - 1:
44 | structure_info_next = structure_info_list[block_id + 1]
45 | structure_info = copy.deepcopy(structure_info)
46 | random_mutate_method = self.method_mutator()
47 |
48 | if random_mutate_method == 'out':
49 | new_out = self.channel_mutator(structure_info['out'])
50 | # Add the constraint: the maximum output of the stem block is 128
51 | new_out = min(self.the_maximum_stem_channel, new_out)
52 | if self.the_minimum_stem_channel:
53 | new_out = max(self.the_minimum_stem_channel, new_out)
54 |
55 | if block_id < len(structure_info_list) - 1:
56 | new_out = min(structure_info_next['out'], new_out)
57 | structure_info['out'] = new_out
58 | return structure_info
59 |
60 | if random_mutate_method == 'k':
61 | new_k = self.kernel_mutator(structure_info['k'])
62 | structure_info['k'] = new_k
63 | return structure_info
64 |
65 |
--------------------------------------------------------------------------------
/tinynas/spaces/random_sample.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import random
6 | from .mutator.base import Sampler
7 |
8 | class RandomSampler(Sampler):
9 | def choice(self, candidates):
10 | return random.choice(candidates)
11 |
12 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_3d_k1dwk1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import bisect
6 | import copy
7 | import os
8 | import random
9 | import sys
10 |
11 | from .base import CnnBaseSpace
12 | from .builder import SPACES
13 | from .mutator import build_mutator
14 |
15 |
16 | @SPACES.register_module(module_name = 'space_3d_k1dwk1')
17 | class Space3Dk1dwk1(CnnBaseSpace):
18 |
19 | def __init__(self, name = None,
20 | image_size = 224,
21 | block_num = 2,
22 | exclude_stem = False,
23 | budget_layers=None,
24 | maximum_channel =640,
25 | **kwargs):
26 |
27 | super().__init__(name, image_size = image_size,
28 | block_num = block_num,
29 | exclude_stem = exclude_stem,
30 | budget_layers = budget_layers,
31 | **kwargs)
32 |
33 | kwargs = dict(stem_mutate_method_list = ['out'] ,
34 | the_maximum_channel = maximum_channel,
35 | mutate_method_list = ['out', 'k', 'btn', 'L'],
36 | search_kernel_size_list = [(1, 3), (1, 5), (3, 3)],
37 | search_layer_list = [-2, -1, 1, 2],
38 | search_channel_list = [2.0, 1.5, 1.25, 0.8, 0.6, 0.5],
39 | search_btn_ratio_list = [1.5, 2.0, 2.5, 3.0, 3.5, 4.0],
40 | budget_layers = budget_layers
41 | )
42 |
43 | for n in ['Conv3DKXBNRELU','SuperRes3DK1DWK1']:
44 | self.mutators[n] = build_mutator(n, kwargs)
45 |
46 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_k1dwk1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import bisect
6 | import copy
7 | import os
8 | import random
9 | import sys
10 |
11 | from .base import CnnBaseSpace
12 | from .builder import SPACES
13 | from .space_k1kxk1 import Spacek1kxk1
14 | from .mutator import build_mutator
15 |
16 |
17 | @SPACES.register_module(module_name = 'space_k1dwk1')
18 | class Spacek1dwk1(CnnBaseSpace):
19 |
20 | def __init__(self, name = None,
21 | image_size = 224,
22 | block_num = 2,
23 | exclude_stem = False,
24 | budget_layers=None,
25 | maximum_channel =1280,
26 | **kwargs):
27 |
28 | super().__init__(name, image_size = image_size,
29 | block_num = block_num,
30 | exclude_stem = exclude_stem,
31 | budget_layers = budget_layers,
32 | **kwargs)
33 |
34 | kwargs = dict(stem_mutate_method_list = ['out'] ,
35 | the_maximum_channel = maximum_channel,
36 | mutate_method_list = ['out', 'k', 'btn', 'L'],
37 | search_kernel_size_list = [3, 5],
38 | search_layer_list = [-2, -1, 1, 2],
39 | search_channel_list = [2.0, 1.5, 1.25, 0.8, 0.6, 0.5],
40 | search_btn_ratio_list = [1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0],
41 | budget_layers = budget_layers
42 | )
43 |
44 | for n in ['ConvKXBNRELU','SuperResK1DWK1']:
45 | self.mutators[n] = build_mutator(n, kwargs)
46 |
47 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_k1dwsek1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import numpy as np
6 |
7 | from .base import CnnBaseSpace
8 | from .builder import SPACES
9 | from .mutator import build_mutator
10 |
11 | @SPACES.register_module(module_name = 'space_k1dwsek1')
12 | class Spacek1dwsek1(CnnBaseSpace):
13 |
14 | def __init__(self, name = None,
15 | image_size = 224,
16 | block_num = 2,
17 | exclude_stem = False,
18 | budget_layers=None,
19 | maximum_channel =1280,
20 | **kwargs):
21 |
22 | super().__init__(name, image_size = image_size,
23 | block_num = block_num,
24 | exclude_stem = exclude_stem,
25 | budget_layers = budget_layers,
26 | **kwargs)
27 |
28 | kwargs = dict(stem_mutate_method_list = ['out'] ,
29 | the_maximum_channel = maximum_channel,
30 | mutate_method_list = ['out', 'k', 'btn', 'L'],
31 | search_kernel_size_list = [3, 5, 7],
32 | search_layer_list = [-2, -1, 1, 2],
33 | search_channel_list = np.arange(0.5, 2.01, 0.1),
34 | search_btn_ratio_list = np.arange(1.5, 6.01, 0.1),
35 | the_maximum_stem_channel = 32,
36 | the_minimum_stem_channel = 16,
37 | budget_layers = budget_layers
38 | )
39 |
40 | for n in ['ConvKXBNRELU','SuperResK1DWSEK1']:
41 | self.mutators[n] = build_mutator(n, kwargs)
42 |
43 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_k1kx.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .base import CnnBaseSpace
6 | from .builder import SPACES
7 | from .mutator import build_mutator
8 |
9 | @SPACES.register_module(module_name = 'space_k1kx')
10 | class Spacek1kx(CnnBaseSpace):
11 | def __init__(self, name = None,
12 | image_size = 224,
13 | block_num = 2,
14 | exclude_stem = False,
15 | budget_layers=None,
16 | maximum_channel =2048,
17 | channel_range_list = None,
18 | kernel_size_list = None,
19 | **kwargs):
20 |
21 | super().__init__(name, image_size = image_size,
22 | block_num = block_num,
23 | exclude_stem = exclude_stem,
24 | budget_layers = budget_layers,
25 | **kwargs)
26 | defualt_channel_range_list = [None, None, [64, 128], None, [128, 256], [256, 512]]
27 | defualt_kernel_size_list = [3]
28 |
29 | channel_range_list = channel_range_list or defualt_channel_range_list
30 | kernel_size_list = kernel_size_list or defualt_kernel_size_list
31 |
32 | kwargs = dict(stem_mutate_method_list = ['out'] ,
33 | mutate_method_list = ['out', 'btn', 'L'],
34 | the_maximum_channel = maximum_channel,
35 | channel_range = channel_range_list,
36 | search_kernel_size_list = kernel_size_list,
37 | search_layer_list = [-2, -1, 1, 2],
38 | search_channel_list = [2.0, 1.5, 1.25, 0.8, 0.6, 0.5],
39 | budget_layers = budget_layers,
40 | btn_minimum_ratio = 10 # the bottleneck must be larger than out/10
41 | )
42 | for n in ['ConvKXBNRELU','SuperResK1KX']:
43 | self.mutators[n] = build_mutator(n, kwargs)
44 |
45 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_k1kxk1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import bisect
6 | import copy
7 | import os
8 | import random
9 | import sys
10 |
11 | from .base import CnnBaseSpace
12 | from .builder import SPACES
13 | from .mutator import build_mutator
14 |
15 | @SPACES.register_module(module_name = 'space_k1kxk1')
16 | class Spacek1kxk1(CnnBaseSpace):
17 |
18 | def __init__(self, name = None,
19 | image_size = 224,
20 | block_num = 2,
21 | exclude_stem = False,
22 | budget_layers=None,
23 | maximum_channel =2048,
24 | **kwargs):
25 |
26 | super().__init__(name, image_size = image_size,
27 | block_num = block_num,
28 | exclude_stem = exclude_stem,
29 | budget_layers = budget_layers,
30 | **kwargs)
31 |
32 | kwargs = dict(stem_mutate_method_list = ['out'] ,
33 | mutate_method_list = ['out', 'k', 'btn', 'L'],
34 | the_maximum_channel = maximum_channel,
35 | search_kernel_size_list = [3, 5],
36 | search_layer_list = [-2, -1, 1, 2],
37 | search_channel_list = [1.5, 1.25, 0.8, 0.6, 0.5],
38 | budget_layers = budget_layers,
39 | btn_minimum_ratio = 10 # the bottleneck must be larger than out/10
40 | )
41 | for n in ['ConvKXBNRELU','SuperResK1KXK1']:
42 | self.mutators[n] = build_mutator(n, kwargs)
43 |
44 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_kxkx.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .base import CnnBaseSpace
6 | from .builder import SPACES
7 | from .mutator import build_mutator
8 |
9 | @SPACES.register_module(module_name = 'space_kxkx')
10 | class Spacekxkx(CnnBaseSpace):
11 |
12 | def __init__(self, name = None,
13 | image_size = 224,
14 | block_num = 2,
15 | exclude_stem = False,
16 | budget_layers=None,
17 | maximum_channel =2048,
18 | channel_range_list = None,
19 | kernel_size_list = None,
20 | **kwargs):
21 |
22 | super().__init__(name, image_size = image_size,
23 | block_num = block_num,
24 | exclude_stem = exclude_stem,
25 | budget_layers = budget_layers,
26 | **kwargs)
27 |
28 | defualt_channel_range_list = [None, None, [64, 128], None, [128, 256], [256, 512]]
29 | defualt_kernel_size_list = [3]
30 |
31 | channel_range_list = channel_range_list or defualt_channel_range_list
32 | kernel_size_list = kernel_size_list or defualt_kernel_size_list
33 |
34 | kwargs = dict(stem_mutate_method_list = ['out'] ,
35 | mutate_method_list = ['out', 'btn', 'L'],
36 | the_maximum_channel = maximum_channel,
37 | channel_range = channel_range_list,
38 | search_kernel_size_list = kernel_size_list,
39 | search_layer_list = [-2, -1, 1, 2],
40 | search_channel_list = [2.0, 1.5, 1.25, 0.8, 0.6, 0.5],
41 | budget_layers = budget_layers,
42 | btn_minimum_ratio = 10 # the bottleneck must be larger than out/10
43 | )
44 | for n in ['ConvKXBNRELU','SuperResKXKX']:
45 | self.mutators[n] = build_mutator(n, kwargs)
46 |
47 | def choice(self):
48 | return None
49 |
50 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_quant_k1dwk1.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import bisect
6 | import copy
7 | import os
8 | import random
9 | import sys
10 |
11 | from .base import CnnBaseSpace
12 | from .builder import SPACES
13 | from .space_k1kxk1 import Spacek1kxk1
14 | from .mutator import build_mutator
15 |
16 |
17 | @SPACES.register_module(module_name = 'space_quant_k1dwk1')
18 | class SpaceQuantk1dwk1(CnnBaseSpace):
19 | def __init__(self, name = None,
20 | image_size = 224,
21 | block_num = 2,
22 | exclude_stem = False,
23 | budget_layers=None,
24 | maximum_channel =1280,
25 | **kwargs):
26 |
27 | super().__init__(name, image_size = image_size,
28 | block_num = block_num,
29 | exclude_stem = exclude_stem,
30 | budget_layers = budget_layers,
31 | **kwargs)
32 |
33 | kwargs = dict(stem_mutate_method_list = ['out'] ,
34 | the_maximum_channel = maximum_channel,
35 | nbits_ratio = 0.1,
36 | mutate_method_list = ['out', 'k', 'btn', 'L', 'nbits'],
37 | search_kernel_size_list = [3, 5],
38 | search_layer_list = [-2, -1, 1, 2],
39 | search_channel_list = [2.0, 1.5, 1.25, 0.8, 0.6, 0.5],
40 | search_nbits_list = [3, 4, 5, 6],
41 | search_btn_ratio_list = [1.5, 2.0, 2.5, 3.0, 3.5, 4.0],
42 | budget_layers = budget_layers
43 | )
44 |
45 | for n in ['ConvKXBNRELU','SuperQuantResK1DWK1']:
46 | self.mutators[n] = build_mutator(n, kwargs)
47 |
48 |
--------------------------------------------------------------------------------
/tinynas/spaces/space_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 |
6 | def decode_cand_tuple(cand_tuple):
7 | depth = cand_tuple[0]
8 | return depth, list(cand_tuple[1:depth + 1]), list(
9 | cand_tuple[depth + 1:2 * depth + 1]), cand_tuple[-1]
10 |
11 |
12 | def smart_round(x, base=8):
13 | if base is None:
14 | if x > 32 * 8:
15 | round_base = 32
16 | elif x > 16 * 8:
17 | round_base = 16
18 | else:
19 | round_base = 8
20 | else:
21 | round_base = base
22 |
23 | return max(round_base, round(x / float(round_base)) * round_base)
24 |
25 |
26 | def __check_block_structure_info_list_valid__(block_structure_info_list, budget_layers = None):
27 | if len(block_structure_info_list) < 1:
28 | return False
29 |
30 | # check how many conv layers
31 | layers = 0
32 | for block_structure_info in block_structure_info_list:
33 | if 'L' not in block_structure_info.keys():
34 | layers += 1
35 | elif block_structure_info['class'] in ['SuperResK1KX', 'SuperResKXKX']:
36 | layers += block_structure_info['L'] * 2
37 | else:
38 | layers += block_structure_info['L'] * 3
39 |
40 | if budget_layers is not None and layers > budget_layers:
41 | return False
42 |
43 | return True
44 |
45 |
46 | def adjust_structures_inplace(block_structure_info_list, image_size):
47 |
48 | # adjust channels
49 | last_channels = None
50 | for i, block_structure_info in enumerate(block_structure_info_list):
51 | if last_channels is None:
52 | last_channels = block_structure_info['out']
53 | continue
54 | else:
55 | block_structure_info_list[i]['in'] = last_channels
56 | last_channels = block_structure_info['out']
57 |
58 | # adjust kernel size <= feature map / 1.5
59 | resolution = image_size
60 | for i, block_structure_info in enumerate(block_structure_info_list):
61 | stride = block_structure_info['s']
62 | kernel_size = block_structure_info['k']
63 |
64 | while kernel_size * 1.5 > resolution:
65 | kernel_size -= 2
66 |
67 | block_structure_info['k'] = kernel_size
68 |
69 | resolution /= stride
70 |
71 | return block_structure_info_list
72 |
--------------------------------------------------------------------------------
/tinynas/strategy/README.md:
--------------------------------------------------------------------------------
1 | ## Search Strategy module
2 | ***
3 | **The search strategy contains a large number of module, mainly complete the search space setting, build super model, budgets, scores, latency and so on **
4 |
5 | - **Strategy Class**
6 |
7 | `build_xxx`: Build sub modules from a cfg dict.
8 |
9 | `budgets`: A property method to get the budgets value setting in cfg.
10 |
11 | `do_compute_nas_score`: Compute a score of a network with specified method.
12 |
13 | `is_satify_budget`: Determine if a network meets budget. If dissatisfied, we will drop it.
14 |
15 | `get_info_for_evolution`: Build a new model from structure info and generate additional information, such as flops/score ans so on.
16 |
17 |
--------------------------------------------------------------------------------
/tinynas/strategy/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | from .strategy import Strategy
6 |
7 |
--------------------------------------------------------------------------------
/tinynas/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba/lightweight-neural-architecture-search/8ccaf889fcd06079d268a355c765e9d0af071612/tinynas/utils/__init__.py
--------------------------------------------------------------------------------
/tinynas/utils/dict_action.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018-2022 Open-MMLab. All rights reserved.
2 | # Origin file:
3 | # https://github.com/open-mmlab/mmcv/blob/8c23bf140a2d329537aabe8947d6ff3125ae7a16/mmcv/utils/config.py
4 | from argparse import Action
5 |
6 |
7 | class DictAction(Action):
8 | """
9 | argparse action to split an argument into KEY=VALUE form
10 | on the first = and append to a dictionary. List options can
11 | be passed as comma separated values, i.e 'KEY=V1,V2,V3', or with explicit
12 | brackets, i.e. 'KEY=[V1,V2,V3]'. It also support nested brackets to build
13 | list/tuple values. e.g. 'KEY=[(V1,V2),(V3,V4)]'
14 | """
15 |
16 | @staticmethod
17 | def _parse_int_float_bool(val):
18 | try:
19 | return int(val)
20 | except ValueError:
21 | pass
22 | try:
23 | return float(val)
24 | except ValueError:
25 | pass
26 | if val.lower() in ['true', 'false']:
27 | return True if val.lower() == 'true' else False
28 | return val
29 |
30 | @staticmethod
31 | def _parse_iterable(val):
32 | """Parse iterable values in the string.
33 | All elements inside '()' or '[]' are treated as iterable values.
34 | Args:
35 | val (str): Value string.
36 | Returns:
37 | list | tuple: The expanded list or tuple from the string.
38 | Examples:
39 | >>> DictAction._parse_iterable('1,2,3')
40 | [1, 2, 3]
41 | >>> DictAction._parse_iterable('[a, b, c]')
42 | ['a', 'b', 'c']
43 | >>> DictAction._parse_iterable('[(1, 2, 3), [a, b], c]')
44 | [(1, 2, 3), ['a', 'b'], 'c']
45 | """
46 |
47 | def find_next_comma(string):
48 | """Find the position of next comma in the string.
49 | If no ',' is found in the string, return the string length. All
50 | chars inside '()' and '[]' are treated as one element and thus ','
51 | inside these brackets are ignored.
52 | """
53 | assert (string.count('(') == string.count(')')) and (
54 | string.count('[') == string.count(']')), \
55 | f'Imbalanced brackets exist in {string}'
56 | end = len(string)
57 | for idx, char in enumerate(string):
58 | pre = string[:idx]
59 | # The string before this ',' is balanced
60 | if ((char == ',') and (pre.count('(') == pre.count(')'))
61 | and (pre.count('[') == pre.count(']'))):
62 | end = idx
63 | break
64 | return end
65 |
66 | # Strip ' and " characters and replace whitespace.
67 | val = val.strip('\'\"').replace(' ', '')
68 | is_tuple = False
69 | if val.startswith('(') and val.endswith(')'):
70 | is_tuple = True
71 | val = val[1:-1]
72 | elif val.startswith('[') and val.endswith(']'):
73 | val = val[1:-1]
74 | elif ',' not in val:
75 | # val is a single value
76 | return DictAction._parse_int_float_bool(val)
77 |
78 | values = []
79 | while len(val) > 0:
80 | comma_idx = find_next_comma(val)
81 | element = DictAction._parse_iterable(val[:comma_idx])
82 | values.append(element)
83 | val = val[comma_idx + 1:]
84 | if is_tuple:
85 | values = tuple(values)
86 | return values
87 |
88 | def __call__(self, parser, namespace, values, option_string=None):
89 | options = {}
90 | for kv in values:
91 | key, val = kv.split('=', maxsplit=1)
92 | options[key] = self._parse_iterable(val)
93 | setattr(namespace, self.dest, options)
94 |
--------------------------------------------------------------------------------
/tinynas/utils/dist_utils.py:
--------------------------------------------------------------------------------
1 | import functools
2 | from typing import Callable, List, Optional, Tuple
3 |
4 | def get_dist_info() -> Tuple[int, int]:
5 |
6 | try:
7 | import mpi4py.MPI as MPI
8 | mpi_comm = MPI.COMM_WORLD
9 | rank = mpi_comm.Get_rank()
10 | world_size = mpi_comm.Get_size()
11 | except ImportError:
12 | rank = 0
13 | world_size = 1
14 | return rank, world_size
15 |
16 | def is_master():
17 | rank, _ = get_dist_info()
18 | return rank == 0
19 |
20 | def master_only(func: Callable) -> Callable:
21 |
22 | @functools.wraps(func)
23 | def wrapper(*args, **kwargs):
24 | rank, _ = get_dist_info()
25 | if rank == 0:
26 | return func(*args, **kwargs)
27 |
28 | return wrapper
29 |
30 | def get_mpi_comm():
31 | try:
32 | import mpi4py.MPI as MPI
33 | mpi_comm = MPI.COMM_WORLD
34 | except ImportError:
35 | mpi_comm = None
36 | return mpi_comm
37 |
38 | def worker_only(func: Callable) -> Callable:
39 |
40 | @functools.wraps(func)
41 | def wrapper(*args, **kwargs):
42 | rank, _ = get_dist_info()
43 | if rank > 0:
44 | return func(*args, **kwargs)
45 |
46 | return wrapper
47 |
--------------------------------------------------------------------------------
/tinynas/utils/file_utils.py:
--------------------------------------------------------------------------------
1 | import distutils.dir_util
2 | import pprint
3 | import importlib.util
4 |
5 | from .import_utils import load_py_module_from_path
6 | from .dist_utils import master_only
7 |
8 | import os
9 |
10 | def mkfilepath(filename):
11 | filename = os.path.expanduser(filename)
12 | distutils.dir_util.mkpath(os.path.dirname(filename))
13 |
14 |
15 | def mkdir(dirname):
16 | dirname = os.path.expanduser(dirname)
17 | distutils.dir_util.mkpath(dirname)
18 |
19 |
20 | def robust_save(filename, save_function):
21 | mkfilepath(filename)
22 | backup_filename = filename + '.robust_save_temp'
23 | save_function(backup_filename)
24 | if os.path.isfile(filename):
25 | os.remove(filename)
26 | os.rename(backup_filename, filename)
27 |
28 | @master_only
29 | def save_pyobj(filename, pyobj):
30 | mkfilepath(filename)
31 | the_s = pprint.pformat(pyobj, indent=2, width=120, compact=True)
32 | with open(filename, 'w') as fid:
33 | fid.write(the_s)
34 |
35 | def load_pyobj(filename):
36 | with open(filename, 'r') as fid:
37 | the_s = fid.readlines()
38 |
39 | if isinstance(the_s, list):
40 | the_s = ''.join(the_s)
41 |
42 | the_s = the_s.replace('inf', '1e20')
43 | pyobj = ast.literal_eval(the_s)
44 | return pyobj
45 |
--------------------------------------------------------------------------------
/tinynas/utils/import_utils.py:
--------------------------------------------------------------------------------
1 | import importlib.util
2 | import os
3 |
4 | def load_py_module_from_path(module_path, module_name=None):
5 | if module_path.find(':') > 0:
6 | split_path = module_path.split(':')
7 | module_path = split_path[0]
8 | function_name = split_path[1]
9 | else:
10 | function_name = None
11 |
12 | if module_name is None:
13 | module_name = module_path.replace('/', '_').replace('.', '_')
14 |
15 | assert os.path.isfile(module_path)
16 |
17 | spec = importlib.util.spec_from_file_location(module_name, module_path)
18 | any_module = importlib.util.module_from_spec(spec)
19 | spec.loader.exec_module(any_module)
20 | if function_name is None:
21 | return any_module
22 | else:
23 | return getattr(any_module, function_name)
24 |
--------------------------------------------------------------------------------
/tinynas/utils/logger.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 | # https://github.com/alibaba/lightweight-neural-architecture-search.
4 |
5 | import logging
6 |
7 |
8 | def get_logger(name,
9 | rank=0,
10 | log_file=None,
11 | log_level="INFO",
12 | file_mode='w'):
13 | """[summary]
14 |
15 | Args:
16 | name ([type]): [description]
17 | rank (int, optional): [description]. Defaults to 0.
18 | log_file ([type], optional): [description]. Defaults to None.
19 | log_level ([type], optional): [description]. Defaults to logging.INFO.
20 | file_mode (str, optional): [description]. Defaults to 'w'.
21 |
22 | Returns:
23 | [type]: [description]
24 | """
25 | if log_level.upper() == 'DEBUG':
26 | log_level = logging.DEBUG
27 | elif log_level.upper() == 'ERROR':
28 | log_level = logging.ERROR
29 | elif log_level.upper() == 'WARNING':
30 | log_level = logging.WARNING
31 | else:
32 | log_level = logging.INFO
33 |
34 | logger = logging.getLogger(name)
35 |
36 | for handler in logger.root.handlers:
37 | if type(handler) is logging.StreamHandler:
38 | handler.setLevel(logging.ERROR)
39 |
40 | # all rank will add a StreamHandler for error output
41 | stream_handler = logging.StreamHandler()
42 | handlers = [stream_handler]
43 |
44 | # only rank 0 will add a FileHandler
45 | if rank == 0 and log_file is not None:
46 | file_handler = logging.FileHandler(log_file, file_mode)
47 | handlers.append(file_handler)
48 |
49 | formatter = logging.Formatter(
50 | f'%(asctime)s-%(name)s-%(levelname)s-rank{rank}: %(message)s')
51 | for handler in handlers:
52 | handler.setFormatter(formatter)
53 | handler.setLevel(log_level)
54 | logger.addHandler(handler)
55 |
56 | if rank == 0:
57 | logger.setLevel(log_level)
58 | else:
59 | logger.setLevel(logging.ERROR)
60 |
61 | return logger
62 |
63 | def get_root_logger(name='Search',
64 | rank=0,
65 | log_file=None,
66 | log_level=logging.INFO):
67 | """[summary]
68 |
69 | Args:
70 | name (str, optional): [description]. Defaults to 'nas'.
71 | log_file ([type], optional): [description]. Defaults to None.
72 | log_level ([type], optional): [description]. Defaults to logging.INFO.
73 |
74 | Returns:
75 | [type]: [description]
76 | """
77 | logger = get_logger(
78 | name=name, rank=rank, log_file=log_file, log_level=log_level)
79 |
80 | return logger
81 |
82 |
83 | class MyLogger():
84 |
85 | def __init__(self, log_filename=None, verbose=False):
86 | self.log_filename = log_filename
87 | self.verbose = verbose
88 | if self.log_filename is not None:
89 | mkfilepath(self.log_filename)
90 | self.fid = open(self.log_filename, 'w')
91 | else:
92 | self.fid = None
93 |
94 | def info(self, msg):
95 | msg = str(msg)
96 | print(msg)
97 | if self.fid is not None:
98 | self.fid.write(msg + '\n')
99 | self.fid.flush()
100 |
101 | def debug_info(self, msg):
102 | if not self.verbose:
103 | return
104 | msg = str(msg)
105 | print(msg)
106 | if self.fid is not None:
107 | self.fid.write(msg + '\n')
108 | self.fid.flush()
109 |
--------------------------------------------------------------------------------
/tools/dist_search.sh:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 |
4 | CONFIG=$1
5 | shift 1
6 | CFG_OPTIONS="${*:-""}"
7 |
8 | nproc=64
9 | set -e
10 |
11 | PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \
12 | mpirun --allow-run-as-root -np ${nproc} -H 127.0.0.1:${nproc} -bind-to none -map-by slot -mca pml ob1 \
13 | -mca btl ^openib -x NCCL_DEBUG=INFO -x LD_LIBRARY_PATH -x PATH \
14 | python3 $(dirname "$0")/search.py ${CONFIG} ${CFG_OPTIONS}
--------------------------------------------------------------------------------
/tools/export.py:
--------------------------------------------------------------------------------
1 | import ast
2 | import sys
3 | from os.path import basename, expanduser, abspath, dirname, exists, isdir, join
4 | from shutil import copy2, copytree, ignore_patterns, rmtree
5 | import json
6 |
7 | def export( work_dir, export_dir=None, force=False):
8 |
9 | taskid = basename(abspath(expanduser(work_dir)))
10 | base_dir = dirname(dirname(abspath(__file__)))
11 |
12 | if export_dir is None:
13 | export_dir = '.'
14 |
15 | code_dir = join(base_dir, 'tinynas', 'deploy')
16 |
17 | # parse best
18 | best_from = join(work_dir, 'best_structure.txt')
19 | best_config = ast.literal_eval(open(best_from).read())
20 | arch = best_config['space_arch'].lower()
21 |
22 | # copy source code
23 | deploy_from = join(code_dir, arch)
24 | deploy_to = join(export_dir, taskid)
25 | if exists(deploy_to) and force:
26 | if isdir(deploy_to):
27 | rmtree(deploy_to)
28 | else:
29 | os.remove(deploy_to)
30 | copytree(
31 | deploy_from,
32 | deploy_to,
33 | ignore=ignore_patterns('__pycache__', '*.pyc', '*.md'))
34 |
35 | best_to = join(deploy_to, 'best_structure.json')
36 | json.dump(best_config, open(best_to, 'w'), indent=2)
37 |
38 | # copy weight
39 | weight_from = join(work_dir, 'weights')
40 | if exists(weight_from) and isdir(weight_from):
41 | weight_to = join(deploy_to, 'weights')
42 | copytree(weight_from, weight_to)
43 |
44 | return deploy_to
45 |
46 |
47 | if __name__ == '__main__':
48 | args = {k: v for k, v in enumerate(sys.argv)}
49 |
50 | work_dir = args.get(1, None)
51 | output_dir = args.get(2, None)
52 |
53 | if work_dir is None:
54 | print('work_dir not specified!')
55 | else:
56 | loc = export(work_dir, output_dir, force=True)
57 | print('exported to', loc)
58 |
--------------------------------------------------------------------------------
/tools/local_search.sh:
--------------------------------------------------------------------------------
1 | # Copyright (c) Alibaba, Inc. and its affiliates.
2 | # The implementation is also open-sourced by the authors, and available at
3 |
4 | CONFIG=$1
5 | shift 1
6 | CFG_OPTIONS="${*:-""}"
7 |
8 | set -e
9 |
10 | PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \
11 | python3 $(dirname "$0")/search.py ${CONFIG} ${CFG_OPTIONS}
--------------------------------------------------------------------------------
/tools/search.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | from tinynas.searchers import build_searcher
3 | from tinynas.utils.dict_action import DictAction
4 |
5 | def parse_args():
6 | parser = argparse.ArgumentParser(description='Search a network model')
7 | parser.add_argument('config', help='search config file path')
8 | parser.add_argument(
9 | '--cfg_options',
10 | nargs='+',
11 | action=DictAction,
12 | help='override some settings in the used config, the key-value pair '
13 | 'in xxx=yyy format will be merged into config file. If the value to '
14 | 'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
15 | 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
16 | 'Note that the quotation marks are necessary and that no white space '
17 | 'is allowed.')
18 | args = parser.parse_args()
19 | return args
20 |
21 | def main():
22 |
23 | args = parse_args()
24 | kwargs = dict(cfg_file=args.config)
25 | if args.cfg_options is not None:
26 | kwargs['cfg_options'] = args.cfg_options
27 | searcher = build_searcher(default_args = kwargs)
28 | searcher.run()
29 |
30 | if __name__ == '__main__':
31 | main()
32 |
--------------------------------------------------------------------------------