NNIの検索空間を調べてみる

[こちら](https://qiita.com/mine820/items/4d7a091928ab7c00dbec)で試してみたNNIですが、もう少し使い方を調べてみます。
今回は検索空間を調べてみます。

※[こちらのURL](https://github.com/Microsoft/nni/blob/master/docs/en_US/SearchSpaceSpec.md)を翻訳しています

# 検索空間とは

[こちら](https://qiita.com/mine820/items/8ee85ceaa49554bd6fc5)で説明したチューナーは、JSONファイルとして定義されている検索空間に従ってパラメーター/アーキテクチャーをサンプリングします。
ユーザは変数の名前、サンプリング戦略のタイプとそのパラメータを検索空間として定義します。

```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]},
    "batch_size":{"_type":"choice","_value":[50, 250, 500]},
    "learning_rate":{"_type":"uniform","_value":[0.0001, 0.1]}
}
```

それぞれ「変数名」「種類」「値」で構成されます。

# 検索空間の詳細

サンプリング戦略の種類ごとに見ていきます。

## choice

```JSON
{"_type":"choice","_value":options}
```

これは、変数値がオプションの1つであり、リストであることを意味します。
オプションの要素は、それ自体が[ネストされた]確率的表現である可能性があります。この場合、一部のオプションにのみ現れる確率的選択は条件付きパラメーターになります。

## randint

```JSON
{"_type":"randint","_value":[upper]}
```
これは、変数値が[0、upper)の範囲のランダムな整数であることを意味します。
この分布の意味は、より離れた整数値と比較して、近くの整数値の間で損失関数にそれ以上の相関がないということです。
これは、例えばランダムシードを記述するのに適した分布です。損失関数がおそらく近くの整数値とより相関している場合は、おそらく「quniform」「qloguniform」「qnormal」「qlognormal」などの「量子化された」連続分布のいずれかを使用する必要があります。
下限を変更したい場合は、今のところ「quniform」を使用してください。

## uniform

```JSON
{"_type":"uniform","_value":[low, high]}
```

変数値は、低い値と高い値の間の値です。
最適化するとき、この変数は両側区間に制限されます。

## quniform

```JSON
{"_type":"quniform","_value":[low, high, q]}
```

変数値は「round(uniform(low,high) / q) * q」のような値です。
目的がやや「滑らか」であるが、上と下の両方に境界があるはずである点に関して離散値に適しています。
[low, high]の範囲から一様に整数を選択したい場合は、_valueを[low, high, 1]のように書くことができます。

## loguniform

```JSON
{"_type":"loguniform","_value":[low, high]}
```

変数値は「exp(uniform(log(low),log(high)))」のような対数一様分布に従って、範囲[low, high]から引き出された値であるため、戻り値の対数は一様に分布します。
最適化するとき、この変数は正になるように制約されています。

## qloguniform

```JSON
{"_type":"qloguniform","_value":[low, high, q]}
```

変数値は「round(loguniform(low, high)) / q)* q」のような値です。
目的が「滑らか」で、値の大きさが滑らかになる離散的な変数に適していますが、上と下の両方で境界を設定する必要があります。

## normal

```JSON
{"_type":"normal","_value":[mu, sigma]}
```

変数値は、平均muと標準偏差sigmaで正規分布する実数値です。
最適化するとき、これは制約のない変数です。

## qnormal

```JSON
{"_type":"qnormal","_value":[mu, sigma, q]}
```

変数値は「round(normal(mu, sigma) / q) * q」のような値です。
おそらくmu前後の値をとる離散変数に適していますが、基本的には無制限です。

## lognormal

```JSON
{"_type":"lognormal","_value":[mu, sigma]}
```

変数値は「exp(normal(mu, sigma))」に従って描かれた値であるため、戻り値の対数は正規分布になります。
最適化するとき、この変数は正になるように制約されています。

## qlognormal

```JSON
{"_type":"qlognormal","_value":[mu, sigma, q]}
```

変数値は「round(exp(normal(mu, sigma)) / q) * q」のような値です。
目的が滑らかで、片側から区切られている変数のサイズで滑らかになる離散変数に適しています。

# チューナーとの組み合わせ

チューナーによって、設定できる検索空間が限られます。

※チューナーに関しては[こちら](https://qiita.com/mine820/items/8ee85ceaa49554bd6fc5)を参照してください

| | choice | randint | uniform | quniform | loguniform | qloguniform | normal | qnormal | lognormal | qlognormal |
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| TPE | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| Random Search | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| Anneal | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| Evolution | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| SMAC | ○ | ○ | ○ | ○ | ○ |  |  |  |  |  |
| Batch | ○ |  |  |  |  |  |  |  |  |  |
| Grid Search | ○ |  |  | ○ |  | ○ |  |  |  |  |
| Hyperband | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ | ○ |
| Metis | ○ | ○ | ○ | ○ |  |  |  |  |  |  |  |

Grid Searchでは、ユーザーの便宜のため、「quniform」と「qloguniform」の定義は変更されます。ここで、「q」はサンプリングされる値の数を指定します。
それらについての詳細は以下のとおりです。

- 「quniform」は3つの値[low, high, q]を受け取ります。ここで[low, high]は範囲を指定し、qは均等にサンプリングされる値の数を指定します。qは2以上でなければならないことに注意してください。最初のサンプリング値は 'low'で、次の各値はその前の値より「(high-low) / q」大きくなるようにサンプリングされます
- 「qloguniform」は、まず範囲を[log(low), log(high)]とsampleに変更し、次に標本値を元に戻すことを除いて、「quniform」と同じように動作します

なお、現時点では、Metis Tunerは数値選択のみをサポートしています。