Trials.md 7.69 KB
Newer Older
Yan Ni's avatar
Yan Ni committed
1
2
3
4
5
6
7
8
9
# Write a Trial Run on NNI

A **Trial** in NNI is an individual attempt at applying a configuration (e.g., a set of hyper-parameters) on a model.

To define an NNI trial, you need to firstly define the set of parameters (i.e., search space) and then update the model. NNI provide 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.

<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
23
24
25
26
27
28

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]}
}
```

Refer to [SearchSpaceSpec.md](./SearchSpaceSpec.md) to learn more about search space. Tuner will generate configurations from this search space, that is, choosing a value for each hyperparameter from the range.

### Step 2 - Update model codes

- 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
`RECEIVED_PARAMS` is an object, for example:
Yan Ni's avatar
Yan Ni committed
37
38
39
40
`{"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
41
```python
Yan Ni's avatar
Yan Ni committed
42
43
nni.report_intermediate_result(metrics)
```
44
`metrics` could be any python object. If users use NNI built-in tuner/assessor, `metrics` can only have two formats: 1) a number e.g., float, int, 2) a dict object that has a key named `default` whose value is a number. This `metrics` is reported to [assessor](BuiltinAssessors.md). Usually, `metrics` could be periodically evaluated loss or accuracy.
Yan Ni's avatar
Yan Ni committed
45
46
47

- Report performance of the configuration

Yan Ni's avatar
Yan Ni committed
48
```python
Yan Ni's avatar
Yan Ni committed
49
50
nni.report_final_result(metrics)
```
51
`metrics` also could be any python object. If users use 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. This `metrics` is reported to [tuner](BuiltinTuner.md).
Yan Ni's avatar
Yan Ni committed
52
53
54
55
56

### Step 3 - Enable NNI API

To enable NNI API mode, you need to set useAnnotation to *false* and provide the path of SearchSpace file (you just defined in step 1):

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

You can refer to [here](ExperimentConfig.md) for more information about how to set up experiment configurations.

Chi Song's avatar
Chi Song committed
64
*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
65
66
67
68
69
70
71


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

An alternative to writing a trial is to use NNI's syntax for python. Simple as any annotation, NNI annotation is working like comments in your codes. You don't have to make structure or any other big changes to your existing codes. With a few lines of NNI annotation, you will be able to:

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

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

79
### Step 1 - Update codes with annotations
Yan Ni's avatar
Yan Ni committed
80

81
The following is a tensorflow code snippet for NNI Annotation, where the highlighted four lines are annotations that help you to:
Yan Ni's avatar
Yan Ni committed
82
83
84
85
86
87
88
89
90
91
92
93
94
  1. tune batch\_size and dropout\_rate
  2. report test\_acc every 100 steps
  3. at last report test\_acc as final result.

What noteworthy is: as these newly added codes are annotations, it does not actually change your previous codes logic, you can still run your code as usual in environments without NNI installed.

```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
95
+       """@nni.variable(nni.choice(0.1, 0.5), name=dropout_rate)"""
Yan Ni's avatar
Yan Ni committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
        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)"""
```

114
**NOTE**:
Yan Ni's avatar
Yan Ni committed
115
- `@nni.variable` will take effect on its following line, which is an assignment statement whose leftvalue must be specified by the keyword `name` in `@nni.variable`.
116
- `@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
117

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


### Step 2 - Enable NNI Annotation

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

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

## Where are my trials?

### Local Mode

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 could find each trial's code, data and other possible log. In addition, each trial's log (including stdout) will be re-directed to a file named `trial.log` under that directory.

If NNI Annotation is used, 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`:
```shell
#!/bin/bash
cd /tmp/user_name/nni/annotation/tmpzj0h72x6 #This is the actual directory
export NNI_PLATFORM=local
export NNI_SYS_DIR=/home/user_name/nni/experiments/$experiment_id$/trials/$trial_id$
export NNI_TRIAL_JOB_ID=nrbb2
export NNI_OUTPUT_DIR=/home/user_name/nni/experiments/$eperiment_id$/trials/$trial_id$
export NNI_TRIAL_SEQ_ID=1
export MULTI_PHASE=false
export CUDA_VISIBLE_DEVICES=
eval python3 mnist.py 2>/home/user_name/nni/experiments/$experiment_id$/trials/$trial_id$/stderr
147
echo $? `date +%s%3N` >/home/user_name/nni/experiments/$experiment_id$/trials/$trial_id$/.nni/state
148
149
150
151
152
153
154
155
```

### Other Modes

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

For more information, please refer to [HowToDebug](HowToDebug.md)

Yan Ni's avatar
Yan Ni committed
156
157
158
<a name="more-examples"></a>
## More Trial Examples

159
160
161
162
163
* [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)