Trials.md 8.96 KB
Newer Older
Yan Ni's avatar
Yan Ni committed
1
2
# Write a Trial Run on NNI

3
A **Trial** in NNI is an individual attempt at applying a configuration (e.g., a set of hyper-parameters) to a model.
Yan Ni's avatar
Yan Ni committed
4

5
To define an NNI trial, you need to first define the set of parameters (i.e., search space) and then update the model. NNI provides two approaches for you to define a trial: [NNI API](#nni-api) and [NNI Python annotation](#nni-annotation). You could also refer to [here](#more-examples) for more trial examples.
Yan Ni's avatar
Yan Ni committed
6
7
8
9

<a name="nni-api"></a>
## NNI API

10
### Step 1 - Prepare a SearchSpace parameters file.
Yan Ni's avatar
Yan Ni committed
11
12
13
14
15
16
17
18
19
20
21
22

An example is shown below:

```json
{
    "dropout_rate":{"_type":"uniform","_value":[0.1,0.5]},
    "conv_size":{"_type":"choice","_value":[2,3,5,7]},
    "hidden_size":{"_type":"choice","_value":[124, 512, 1024]},
    "learning_rate":{"_type":"uniform","_value":[0.0001, 0.1]}
}
```

23
Refer to [SearchSpaceSpec.md](../Tutorial/SearchSpaceSpec.md) to learn more about search spaces. Tuner will generate configurations from this search space, that is, choosing a value for each hyperparameter from the range.
Yan Ni's avatar
Yan Ni committed
24

25
### Step 2 - Update model code
Yan Ni's avatar
Yan Ni committed
26
27
28

- Import NNI

29
    Include `import nni` in your trial code to use NNI APIs.
Yan Ni's avatar
Yan Ni committed
30
31

- Get configuration from Tuner
32

Yan Ni's avatar
Yan Ni committed
33
```python
Yan Ni's avatar
Yan Ni committed
34
35
RECEIVED_PARAMS = nni.get_next_parameter()
```
36

37
`RECEIVED_PARAMS` is an object, for example:
38

Yan Ni's avatar
Yan Ni committed
39
40
41
42
`{"conv_size": 2, "hidden_size": 124, "learning_rate": 0.0307, "dropout_rate": 0.2029}`.

- Report metric data periodically (optional)

Yan Ni's avatar
Yan Ni committed
43
```python
Yan Ni's avatar
Yan Ni committed
44
45
nni.report_intermediate_result(metrics)
```
46

47
`metrics` can be any python object. If users use the NNI built-in tuner/assessor, `metrics` can only have two formats: 1) a number e.g., float, int, or 2) a dict object that has a key named `default` whose value is a number. These `metrics` are reported to [assessor](../Assessor/BuiltinAssessor.md). Often, `metrics` includes the periodically evaluated loss or accuracy.
Yan Ni's avatar
Yan Ni committed
48
49
50

- Report performance of the configuration

Yan Ni's avatar
Yan Ni committed
51
```python
Yan Ni's avatar
Yan Ni committed
52
53
nni.report_final_result(metrics)
```
54
`metrics` can also be any python object. If users use the NNI built-in tuner/assessor, `metrics` follows the same format rule as that in `report_intermediate_result`, the number indicates the model's performance, for example, the model's accuracy, loss etc. These `metrics` are reported to [tuner](../Tuner/BuiltinTuner.md).
Yan Ni's avatar
Yan Ni committed
55
56
57

### Step 3 - Enable NNI API

58
To enable NNI API mode, you need to set useAnnotation to *false* and provide the path of the SearchSpace file was defined in step 1:
Yan Ni's avatar
Yan Ni committed
59

Yan Ni's avatar
Yan Ni committed
60
```yaml
Yan Ni's avatar
Yan Ni committed
61
62
63
64
useAnnotation: false
searchSpacePath: /path/to/your/search_space.json
```

xuehui's avatar
xuehui committed
65
You can refer to [here](../Tutorial/ExperimentConfig.md) for more information about how to set up experiment configurations.
Yan Ni's avatar
Yan Ni committed
66

Chi Song's avatar
Chi Song committed
67
*Please refer to [here](https://nni.readthedocs.io/en/latest/sdk_reference.html) for more APIs (e.g., `nni.get_sequence_id()`) provided by NNI.
Yan Ni's avatar
Yan Ni committed
68
69
70
71

<a name="nni-annotation"></a>
## NNI Python Annotation

72
An alternative to writing a trial is to use NNI's syntax for python. NNI annotations are simple, similar to comments. You don't have to make structural changes to your existing code. With a few lines of NNI annotation, you will be able to:
Yan Ni's avatar
Yan Ni committed
73

74
* annotate the variables you want to tune
75
76
* specify the range  in which you want to tune the variables
* annotate which variable you want to report as an intermediate result to `assessor`
77
* annotate which variable you want to report as the final result (e.g. model accuracy) to `tuner`.
Yan Ni's avatar
Yan Ni committed
78
79
80

Again, take MNIST as an example, it only requires 2 steps to write a trial with NNI Annotation.

81
### Step 1 - Update codes with annotations
Yan Ni's avatar
Yan Ni committed
82

83
The following is a TensorFlow code snippet for NNI Annotation where the highlighted four lines are annotations that:
Yan Ni's avatar
Yan Ni committed
84
85
  1. tune batch\_size and dropout\_rate
  2. report test\_acc every 100 steps
86
  3. lastly report test\_acc as the final result.
Yan Ni's avatar
Yan Ni committed
87

88
It's worth noting that, as these newly added codes are merely annotations, you can still run your code as usual in environments without NNI installed.
Yan Ni's avatar
Yan Ni committed
89
90
91
92
93
94
95
96

```diff
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
+   """@nni.variable(nni.choice(50, 250, 500), name=batch_size)"""
    batch_size = 128
    for i in range(10000):
        batch = mnist.train.next_batch(batch_size)
Yunfeng Wang's avatar
Yunfeng Wang committed
97
+       """@nni.variable(nni.choice(0.1, 0.5), name=dropout_rate)"""
Yan Ni's avatar
Yan Ni committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
        dropout_rate = 0.5
        mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0],
                                                mnist_network.labels: batch[1],
                                                mnist_network.keep_prob: dropout_rate})
        if i % 100 == 0:
            test_acc = mnist_network.accuracy.eval(
                feed_dict={mnist_network.images: mnist.test.images,
                            mnist_network.labels: mnist.test.labels,
                            mnist_network.keep_prob: 1.0})
+           """@nni.report_intermediate_result(test_acc)"""

    test_acc = mnist_network.accuracy.eval(
        feed_dict={mnist_network.images: mnist.test.images,
                    mnist_network.labels: mnist.test.labels,
                    mnist_network.keep_prob: 1.0})
+   """@nni.report_final_result(test_acc)"""
```

116
**NOTE**:
117
- `@nni.variable` will affect its following line which should be an assignment statement whose left-hand side must be the same as the keyword `name` in the `@nni.variable` statement.
118
- `@nni.report_intermediate_result`/`@nni.report_final_result` will send the data to assessor/tuner at that line.
Yan Ni's avatar
Yan Ni committed
119

xuehui's avatar
xuehui committed
120
For more information about annotation syntax and its usage, please refer to [Annotation](../Tutorial/AnnotationSpec.md).
Yan Ni's avatar
Yan Ni committed
121
122
123
124


### Step 2 - Enable NNI Annotation

125
In the YAML configure file, you need to set *useAnnotation* to true to enable NNI annotation:
Yan Ni's avatar
Yan Ni committed
126
127
128
129
```
useAnnotation: true
```

130
## Standalone mode for debugging
131

132
NNI supports a standalone mode for trial code to run without starting an NNI experiment. This is for finding out bugs in trial code more conveniently. NNI annotation natively supports standalone mode, as the added NNI related lines are comments. For NNI trial APIs, the APIs have changed behaviors in standalone mode, some APIs return dummy values, and some APIs do not really report values. Please refer to the following table for the full list of these APIs.
133
134
135
136
137
138
139
140
141
142
```python
# NOTE: please assign default values to the hyperparameters in your trial code
nni.get_next_parameter # return {}
nni.report_final_result # have log printed on stdout, but does not report
nni.report_intermediate_result # have log printed on stdout, but does not report
nni.get_experiment_id # return "STANDALONE"
nni.get_trial_id # return "STANDALONE"
nni.get_sequence_id # return 0
```

143
You can try standalone mode with the [mnist example](https://github.com/microsoft/nni/tree/v1.9/examples/trials/mnist-tfv1). Simply run `python3 mnist.py` under the code directory. The trial code should successfully run with the default hyperparameter values.
144

145
For more information on debugging, please refer to [How to Debug](../Tutorial/HowToDebug.md)
146

147
148
149
150
## Where are my trials?

### Local Mode

151
In NNI, every trial has a dedicated directory for them to output their own data. In each trial, an environment variable called `NNI_OUTPUT_DIR` is exported. Under this directory, you can find each trial's code, data, and other logs. In addition, each trial's log (including stdout) will be re-directed to a file named `trial.log` under that directory.
152

153
If NNI Annotation is used, the trial's converted code is in another temporary directory. You can check that in a file named `run.sh` under the directory indicated by `NNI_OUTPUT_DIR`. The second line (i.e., the `cd` command) of this file will change directory to the actual directory where code is located. Below is an example of `run.sh`:
154
155

```bash
156
157
158
#!/bin/bash
cd /tmp/user_name/nni/annotation/tmpzj0h72x6 #This is the actual directory
export NNI_PLATFORM=local
Junwei Sun's avatar
Junwei Sun committed
159
export NNI_SYS_DIR=/home/user_name/nni-experiments/$experiment_id$/trials/$trial_id$
160
export NNI_TRIAL_JOB_ID=nrbb2
Junwei Sun's avatar
Junwei Sun committed
161
export NNI_OUTPUT_DIR=/home/user_name/nni-experiments/$eperiment_id$/trials/$trial_id$
162
163
164
export NNI_TRIAL_SEQ_ID=1
export MULTI_PHASE=false
export CUDA_VISIBLE_DEVICES=
Junwei Sun's avatar
Junwei Sun committed
165
166
eval python3 mnist.py 2>/home/user_name/nni-experiments/$experiment_id$/trials/$trial_id$/stderr
echo $? `date +%s%3N` >/home/user_name/nni-experiments/$experiment_id$/trials/$trial_id$/.nni/state
167
168
169
170
```

### Other Modes

Junwei Sun's avatar
Junwei Sun committed
171
When running trials on other platforms like remote machine or PAI, the environment variable `NNI_OUTPUT_DIR` only refers to the output directory of the trial, while the trial code and `run.sh` might not be there. However, the `trial.log` will be transmitted back to the local machine in the trial's directory, which defaults to `~/nni-experiments/$experiment_id$/trials/$trial_id$/`
172

173
For more information, please refer to [HowToDebug](../Tutorial/HowToDebug.md).
174

Yan Ni's avatar
Yan Ni committed
175
176
177
<a name="more-examples"></a>
## More Trial Examples

178
179
180
181
182
* [MNIST examples](MnistExamples.md)
* [Finding out best optimizer for Cifar10 classification](Cifar10Examples.md)
* [How to tune Scikit-learn on NNI](SklearnExamples.md)
* [Automatic Model Architecture Search for Reading Comprehension.](SquadEvolutionExamples.md)
* [Tuning GBDT on NNI](GbdtExample.md)
183
* [Tuning RocksDB on NNI](RocksdbExamples.md)