QuickStart.rst 9.34 KB
Newer Older
1
2
Quick Start of Retiarii on NNI
==============================
QuanluZhang's avatar
QuanluZhang committed
3

QuanluZhang's avatar
QuanluZhang committed
4
5
6

.. contents::

QuanluZhang's avatar
QuanluZhang committed
7
In this quick start, we use multi-trial NAS as an example to show how to construct and explore a model space. There are mainly three crucial components for a neural architecture search task, namely,
QuanluZhang's avatar
QuanluZhang committed
8

QuanluZhang's avatar
QuanluZhang committed
9
10
11
* Model search space that defines a set of models to explore.
* A proper strategy as the method to explore this model space.
* A model evaluator that reports the performance of every model in the space.
QuanluZhang's avatar
QuanluZhang committed
12

QuanluZhang's avatar
QuanluZhang committed
13
The tutorial for One-shot NAS can be found `here <./OneshotTrainer.rst>`__.
14

QuanluZhang's avatar
QuanluZhang committed
15
.. note:: Currently, PyTorch is the only supported framework by Retiarii, and we have only tested **PyTorch 1.6 to 1.9**. This documentation assumes PyTorch context but it should also apply to other frameworks, which is in our future plan.
QuanluZhang's avatar
QuanluZhang committed
16
17
18
19

Define your Model Space
-----------------------

QuanluZhang's avatar
QuanluZhang committed
20
Model space is defined by users to express a set of models that users want to explore, which contains potentially good-performing models. In this framework, a model space is defined with two parts: a base model and possible mutations on the base model.
QuanluZhang's avatar
QuanluZhang committed
21
22
23
24

Define Base Model
^^^^^^^^^^^^^^^^^

QuanluZhang's avatar
QuanluZhang committed
25
Defining a base model is almost the same as defining a PyTorch (or TensorFlow) model. Usually, you only need to replace the code ``import torch.nn as nn`` with ``import nni.retiarii.nn.pytorch as nn`` to use our wrapped PyTorch modules.
QuanluZhang's avatar
QuanluZhang committed
26

QuanluZhang's avatar
QuanluZhang committed
27
Below is a very simple example of defining a base model.
QuanluZhang's avatar
QuanluZhang committed
28
29
30

.. code-block:: python

QuanluZhang's avatar
QuanluZhang committed
31
  import torch
QuanluZhang's avatar
QuanluZhang committed
32
33
  import torch.nn.functional as F
  import nni.retiarii.nn.pytorch as nn
34
  from nni.retiarii import model_wrapper
QuanluZhang's avatar
QuanluZhang committed
35

QuanluZhang's avatar
QuanluZhang committed
36
37
  @model_wrapper      # this decorator should be put on the out most
  class Net(nn.Module):
QuanluZhang's avatar
QuanluZhang committed
38
39
    def __init__(self):
      super().__init__()
QuanluZhang's avatar
QuanluZhang committed
40
41
42
43
44
45
      self.conv1 = nn.Conv2d(1, 32, 3, 1)
      self.conv2 = nn.Conv2d(32, 64, 3, 1)
      self.dropout1 = nn.Dropout(0.25)
      self.dropout2 = nn.Dropout(0.5)
      self.fc1 = nn.Linear(9216, 128)
      self.fc2 = nn.Linear(128, 10)
QuanluZhang's avatar
QuanluZhang committed
46
47

    def forward(self, x):
QuanluZhang's avatar
QuanluZhang committed
48
49
50
51
52
53
      x = F.relu(self.conv1(x))
      x = F.max_pool2d(self.conv2(x), 2)
      x = torch.flatten(self.dropout1(x), 1)
      x = self.fc2(self.dropout2(F.relu(self.fc1(x))))
      output = F.log_softmax(x, dim=1)
      return output
QuanluZhang's avatar
QuanluZhang committed
54

QuanluZhang's avatar
QuanluZhang committed
55
56
57
Define Model Mutations
^^^^^^^^^^^^^^^^^^^^^^

QuanluZhang's avatar
QuanluZhang committed
58
A base model is only one concrete model not a model space. We provide `APIs and primitives <./MutationPrimitives.rst>`__ for users to express how the base model can be mutated. That is, to build a model space which includes many models.
QuanluZhang's avatar
QuanluZhang committed
59

QuanluZhang's avatar
QuanluZhang committed
60
Based on the above base model, we can define a model space as below. 
QuanluZhang's avatar
QuanluZhang committed
61

QuanluZhang's avatar
QuanluZhang committed
62
.. code-block:: diff
QuanluZhang's avatar
QuanluZhang committed
63

QuanluZhang's avatar
QuanluZhang committed
64
65
66
67
  import torch
  import torch.nn.functional as F
  import nni.retiarii.nn.pytorch as nn
  from nni.retiarii import model_wrapper
QuanluZhang's avatar
QuanluZhang committed
68

QuanluZhang's avatar
QuanluZhang committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  @model_wrapper
  class Net(nn.Module):
    def __init__(self):
      super().__init__()
      self.conv1 = nn.Conv2d(1, 32, 3, 1)
  -   self.conv2 = nn.Conv2d(32, 64, 3, 1)
  +   self.conv2 = nn.LayerChoice([
  +       nn.Conv2d(32, 64, 3, 1),
  +       DepthwiseSeparableConv(32, 64)
  +   ])
  -   self.dropout1 = nn.Dropout(0.25)
  +   self.dropout1 = nn.Dropout(nn.ValueChoice([0.25, 0.5, 0.75]))
      self.dropout2 = nn.Dropout(0.5)
  -   self.fc1 = nn.Linear(9216, 128)
  -   self.fc2 = nn.Linear(128, 10)
  +   feature = nn.ValueChoice([64, 128, 256])
  +   self.fc1 = nn.Linear(9216, feature)
  +   self.fc2 = nn.Linear(feature, 10)
QuanluZhang's avatar
QuanluZhang committed
87

QuanluZhang's avatar
QuanluZhang committed
88
89
90
91
92
93
94
    def forward(self, x):
      x = F.relu(self.conv1(x))
      x = F.max_pool2d(self.conv2(x), 2)
      x = torch.flatten(self.dropout1(x), 1)
      x = self.fc2(self.dropout2(F.relu(self.fc1(x))))
      output = F.log_softmax(x, dim=1)
      return output
QuanluZhang's avatar
QuanluZhang committed
95

QuanluZhang's avatar
QuanluZhang committed
96
This example uses two mutation APIs, ``nn.LayerChoice`` and ``nn.ValueChoice``. ``nn.LayerChoice`` takes a list of candidate modules (two in this example), one will be chosen for each sampled model. It can be used like normal PyTorch module. ``nn.ValueChoice`` takes a list of candidate values, one will be chosen to take effect for each sampled model.
QuanluZhang's avatar
QuanluZhang committed
97

QuanluZhang's avatar
QuanluZhang committed
98
More detailed API description and usage can be found `here <./construct_space.rst>`__\.
QuanluZhang's avatar
QuanluZhang committed
99

QuanluZhang's avatar
QuanluZhang committed
100
.. note:: We are actively enriching the mutation APIs, to facilitate easy construction of model space. If the currently supported mutation APIs cannot express your model space, please refer to `this doc <./Mutators.rst>`__ for customizing mutators.
QuanluZhang's avatar
QuanluZhang committed
101

QuanluZhang's avatar
QuanluZhang committed
102
103
Explore the Defined Model Space
-------------------------------
QuanluZhang's avatar
QuanluZhang committed
104

QuanluZhang's avatar
QuanluZhang committed
105
There are basically two exploration approaches: (1) search by evaluating each sampled model independently, which is the search approach in multi-trial NAS and (2) one-shot weight-sharing based search, which is used in one-shot NAS. We demonstrate the first approach in this tutorial. Users can refer to `here <./OneshotTrainer.rst>`__ for the second approach.
QuanluZhang's avatar
QuanluZhang committed
106

QuanluZhang's avatar
QuanluZhang committed
107
First, users need to pick a proper exploration strategy to explore the defined model space. Second, users need to pick or customize a model evaluator to evaluate the performance of each explored model.
QuanluZhang's avatar
QuanluZhang committed
108

QuanluZhang's avatar
QuanluZhang committed
109
110
Pick an exploration strategy
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QuanluZhang's avatar
QuanluZhang committed
111

112
Retiarii supports many `exploration strategies <./ExplorationStrategies.rst>`__.
QuanluZhang's avatar
QuanluZhang committed
113

114
Simply choosing (i.e., instantiate) an exploration strategy as below.
QuanluZhang's avatar
QuanluZhang committed
115
116
117

.. code-block:: python

QuanluZhang's avatar
QuanluZhang committed
118
  import nni.retiarii.strategy as strategy
QuanluZhang's avatar
QuanluZhang committed
119

QuanluZhang's avatar
QuanluZhang committed
120
  search_strategy = strategy.Random(dedup=True)  # dedup=False if deduplication is not wanted
QuanluZhang's avatar
QuanluZhang committed
121

QuanluZhang's avatar
QuanluZhang committed
122
123
Pick or customize a model evaluator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QuanluZhang's avatar
QuanluZhang committed
124

QuanluZhang's avatar
QuanluZhang committed
125
In the exploration process, the exploration strategy repeatedly generates new models. A model evaluator is for training and validating each generated model to obtain the model's performance. The performance is sent to the exploration strategy for the strategy to generate better models.
QuanluZhang's avatar
QuanluZhang committed
126

QuanluZhang's avatar
QuanluZhang committed
127
Retiarii has provided two built-in model evaluators, designed for simple use cases: classification and regression. These two evaluators are built upon the awesome library PyTorch-Lightning.
QuanluZhang's avatar
QuanluZhang committed
128

QuanluZhang's avatar
QuanluZhang committed
129
An example here creates a simple evaluator that runs on MNIST dataset, trains for 2 epochs, and reports its validation accuracy.
QuanluZhang's avatar
QuanluZhang committed
130
131
132

.. code-block:: python

133
134
  import nni.retiarii.evaluator.pytorch.lightning as pl
  from nni.retiarii import serialize
135
  from torchvision import transforms
QuanluZhang's avatar
QuanluZhang committed
136

QuanluZhang's avatar
QuanluZhang committed
137
  transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
138
139
  train_dataset = serialize(MNIST, root='data/mnist', train=True, download=True, transform=transform)
  test_dataset = serialize(MNIST, root='data/mnist', train=False, download=True, transform=transform)
QuanluZhang's avatar
QuanluZhang committed
140
141
142
  trainer = pl.Classification(train_dataloader=pl.DataLoader(train_dataset, batch_size=100),
                              val_dataloaders=pl.DataLoader(test_dataset, batch_size=100),
                              max_epochs=2)
143

QuanluZhang's avatar
QuanluZhang committed
144
``serialize`` is for serializing the objects to make model evaluator executable on another process or another machine (e.g., on remote training service). Retiarii provided model evaluators and other classes are already serializable. Other objects should be applied ``serialize``, for example, ``MNIST`` in the above example.
QuanluZhang's avatar
QuanluZhang committed
145
146
147

Detailed descriptions and usages of model evaluators can be found `here <./ApiReference.rst>`__ .

148
If the built-in model evaluators do not meet your requirement, or you already wrote the training code and just want to use it, you can follow `the guide to write a new model evaluator <./WriteTrainer.rst>`__ .
QuanluZhang's avatar
QuanluZhang committed
149

QuanluZhang's avatar
QuanluZhang committed
150
.. warning:: Mutations on the parameters of model evaluator is currently not supported but will be supported in the future.
151

QuanluZhang's avatar
QuanluZhang committed
152
153
Launch an Experiment
--------------------
QuanluZhang's avatar
QuanluZhang committed
154

QuanluZhang's avatar
QuanluZhang committed
155
After all the above are prepared, it is time to start an experiment to do the model search. An example is shown below.
QuanluZhang's avatar
QuanluZhang committed
156
157
158

.. code-block:: python

QuanluZhang's avatar
QuanluZhang committed
159
  exp = RetiariiExperiment(base_model, trainer, [], simple_strategy)
QuanluZhang's avatar
QuanluZhang committed
160
  exp_config = RetiariiExeConfig('local')
QuanluZhang's avatar
QuanluZhang committed
161
  exp_config.experiment_name = 'mnist_search'
QuanluZhang's avatar
QuanluZhang committed
162
  exp_config.trial_concurrency = 2
QuanluZhang's avatar
QuanluZhang committed
163
  exp_config.max_trial_number = 20
QuanluZhang's avatar
QuanluZhang committed
164
165
166
  exp_config.training_service.use_active_gpu = False
  exp.run(exp_config, 8081)

QuanluZhang's avatar
QuanluZhang committed
167
The complete code of this example can be found :githublink:`here <examples/nas/multi-trial/mnist/search.py>`. Users can also run Retiarii Experiment with `different training services <../training_services.rst>`__ besides ``local`` training service.
168

QuanluZhang's avatar
QuanluZhang committed
169
170
Visualize the Experiment
------------------------
171

172
Users can visualize their experiment in the same way as visualizing a normal hyper-parameter tuning experiment. For example, open ``localhost::8081`` in your browser, 8081 is the port that you set in ``exp.run``. Please refer to `here <../Tutorial/WebUI.rst>`__ for details.
173

Yuge Zhang's avatar
Yuge Zhang committed
174
175
We support visualizing models with 3rd-party visualization engines (like `Netron <https://netron.app/>`__). This can be used by clicking ``Visualization`` in detail panel for each trial. Note that current visualization is based on `onnx <https://onnx.ai/>`__ . Built-in evaluators (e.g., Classification) will automatically export the model into a file, for your own evaluator, you need to save your file into ``$NNI_OUTPUT_DIR/model.onnx`` to make this work.

176
177
178
179
180
181
182
183
184
Export Top Models
-----------------

Users can export top models after the exploration is done using ``export_top_models``.

.. code-block:: python

  for model_code in exp.export_top_models(formatter='dict'):
    print(model_code)
QuanluZhang's avatar
QuanluZhang committed
185
186
187
188
189
190
191

The output is `json` object which records the mutation actions of the top model. If users want to output source code of the top model, they can use graph-based execution engine for the experiment, by simply adding the following two lines.

.. code-block:: python

  exp_config.execution_engine = 'base'
  export_formatter = 'code'