NNIのチューナーを調べてみる

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

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

# チューナーとは

パラメータを調整するときに使用するチューニングアルゴリズムのことです。
NNIではいくつか用意されており、これをYAMLファイルで指定します。

```yaml:一部抜粋
tuner:
  #choice: TPE, Random, Anneal, Evolution, BatchTuner, MetisTuner
  #SMAC (SMAC should be installed through nnictl)
  builtinTunerName: TPE
  classArgs:
    #choice: maximize, minimize
    optimize_mode: maximize
```

| YAMLでの設定 | チューナー名 |
|---|---|
| TPE | TPE |
| Random | Random Search |
| Anneal | Anneal |
| Evolution | Naive Evolution |
| SMAC | SMAC |
| BatchTuner | Batch tuner |
| GridSearch | Grid Search |
| Hyperband | Hyperband |
| NetworkMorphism | Network Morphism |
| MetisTuner | Metis Tuner |

# チューナー詳細

では、一つ一つ説明していきます。

## TPE

「Tree-structured Parzen Estimator」のことで、逐次モデルベース最適化（SMBO）アプローチになります。
SMBO法は、過去の測定値に基づいてハイパーパラメータの性能を概算するためにモデルを順次構築し、その後、このモデルに基づいてテストするために新しいハイパーパラメータを選択します。

ブラックボックスで最適化されているTPEは、さまざまなシナリオで使用でき、一般的に優れたパフォーマンスを示します。 （特に限られた計算資源を持っていて、少数の試行しか試みることができないとき）
多くの実験から、TPEがRandom Searchよりはるかに優れていることがわかっています。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します

詳しい説明は[こちら（PDF）](https://papers.nips.cc/paper/4443-algorithms-for-hyper-parameter-optimization.pdf)を参照してください。

## Random Search

ハイパーパラメータ最適化においては、Random Searchが驚くほど簡単で効果的です。
ハイパーパラメーターの事前分布についての知識がない場合は、Random Searchをベースラインとして使用できることをお勧めします。

Random Searchは、各試行がそれほど時間がかからず（例：各試行がすぐに完了するか、またはassessorによって早期に中止されます）、十分な計算リソースがある場合に推奨されます。 あるいは、検索空間を一様に探索したいときに使用します。
Random Searchは検索アルゴリズムのベースラインと見なすことができます。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します

詳しい説明は[こちら（PDF）](http://www.jmlr.org/papers/volume13/bergstra12a/bergstra12a.pdf)を参照してください。

## Anneal

この単純なアニーリングアルゴリズムは、前のサンプルからサンプリングすることから始まりますが、観察される最良のポイントにより近いポイントからサンプリングする傾向があります。
このアルゴリズムは、応答曲面の滑らかさを利用したRandom Searchの単純な変形です。 アニーリング速度は適応的ではありません。

各試行に時間がかかりすぎず、十分な計算リソースがある場合はAnnealが推奨されます（Random Searchとほぼ同じ）。あるいは、検索空間内の変数は、以前の分布からのサンプルである可能性があります。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します

## Naive Evolution

Naive Evolutionは、画像分類器の大規模進化からもたらされます。検索空間に基づいて母集団をランダムに初期化します。世代ごとに、それより良いものを選択し、次の世代を取得するためにそれらに対して何らかの突然変異（例えば、ハイパーパラメータの変更や、１つの層の追加／削除）を行います。
Naive Evolutionを機能させるには多くの試行が必要ですが、非常に単純で新しい機能を拡張するのは簡単です。

計算資源に対する要求は比較的高くなります。具体的には、局所最適値に陥らないようにするために、初期母集団が多く必要です。試験が短いかassessorを利用しているならば、このチューナーは良い選択です。また、トライアルコードがウェイト転送をサポートしている場合、つまりトライアルがその親から収束したウェイトを継承できる場合が推奨されます。これにより、トレーニングの進捗が大幅にスピードアップします。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します

詳しい説明は[こちら（PDF）](https://arxiv.org/pdf/1703.01041.pdf)を参照してください。

## SMAC

SMACは、順次モデルベース最適化（SMBO）に基づいています。 それはカテゴリパラメータを処理するために、最も有名な以前に使用されたモデルクラス（ガウス確率過程モデル）を適応させ、ランダムフォレストのモデルクラスをSMBOに導入します。
NNIによってサポートされているSMACは、SMAC3 Githubリポジトリのラッパーです。SMACはnnictl packageコマンドでインストールする必要があります。

```
nnictl package install --name=SMAC
```

TPEと同様に、SMACもさまざまなシナリオで試すことができるブラックボックスチューナーであり、計算リソースが限られている場合に推奨されます。これは離散ハイパーパラメータ用に最適化されているため、ほとんどのハイパーパラメータが離散的な場合に推奨されます。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します

詳しい説明は[こちら（PDF）](https://www.cs.ubc.ca/~hutter/papers/10-TR-SMAC.pdf)や[こちら（GitHub）](https://github.com/automl/SMAC3)を参照してください。

## Batch tuner

Batch tunerは、ユーザに試験コードのための簡単ないくつかの構成（すなわち、ハイパーパラメータの選択）を提供することを可能にします。すべての設定が完了したら、実験は完了です。
Batch tunerは、検索空間仕様でのタイプ選択のみをサポートします。

試したい設定が決まっている場合は、（選択を使用して）検索空間ファイル（JSON）にそれらをリストし、Batch tunerを使用してそれらを実行することができます。

```JSON:設定例
{
    "combine_params":
    {
        "_type" : "choice",
        "_value" : [{"optimizer": "Adam", "learning_rate": 0.00001},
                    {"optimizer": "Adam", "learning_rate": 0.0001},
                    {"optimizer": "Adam", "learning_rate": 0.001},
                    {"optimizer": "SGD", "learning_rate": 0.01}, 
                    {"optimizer": "SGD", "learning_rate": 0.005}, 
                    {"optimizer": "SGD", "learning_rate": 0.0002}]
    }
}
```

検索空間内のパラメーターのタイプは「choice」でなくてはならず、値はすべての組み合わせたパラメーター値を含む必要があります。

## Grid Search

Grid Searchは、検索空間ファイルで定義されたハイパーパラメータ空間の手動で指定されたサブセットを通して徹底的な検索を実行します。
設定できる検索空間のタイプは「choice」「quniform」「qloguniform」だけです。「quniform」と「qloguniform」の「q」は特別な意味を持ちます（検索空間specのspecとは異なります）。これは、低い値と高い値の範囲から均等にサンプリングされる値の数を意味します。

検索空間が小さいとき、それは検索空間全体を徹底的に掃引することが実行可能であるときに提案されます。

## Hyperband

Hyperbandは、限られたリソースを使用してできるだけ多くの構成を探索しようとし、最終的な結果を得るために有望な構成を見つけ出します。
基本的な考え方は、多くのコンフィギュレーションを生成し、それらをいくつかのSTEPで実行して有望なものを見つけ出し、さらに有望なものをいくつか選択してさらに有望なものを選択することです。

計算リソースが限られていても検索空間が比較的大きい場合に推奨されます。それは、中間結果（例えば、正確さ）がある程度、最終結果（例えば、正確さ）の良いまたは悪い結果を反映することができるというシナリオにおいてうまく機能します。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します
    - R（デフォルト：60）
        - 試行に割り当てることができる最大のSTEPS（ミニバッチまたはエポックの数）<br/>各試行では、実行時間を制御するためにSTEPSを使用します
    - eta（デフォルト：3）
        - （eta-1）/ etaは破棄された試験の割合になります

詳しい説明は[こちら（PDF）](https://arxiv.org/pdf/1603.06560.pdf)を参照してください。

## Network Morphism

Network Morphismは、ディープラーニングモデルのアーキテクチャを自動的に検索する機能を提供します。
すべての子ネットワークは、その親ネットワークから知識を継承し、深さ、幅、およびスキップ接続の変更など、さまざまな種類のネットワークに変形します。次に、歴史的なアーキテクチャとメトリックのペアを使用して、子ネットワークの価値を見積もります。それからそれは訓練するべき最も有望なものを選択します。

NetworkMorphismはpyTorchを必要とするので、先にインストールしてください。

あなたのタスク（あなた自身のデータセット）にディープラーニングを使用するが、ネットワークをどのように選択または設計するかについての見当がつきかないときに使用します。
自分のデータセットと自分のデータ拡張方法に合うように[例](https://github.com/Microsoft/nni/blob/master/examples/trials/network_morphism/cifar10/cifar10_keras.py)を変更します。 また、バッチサイズ、学習率、またはオプティマイザを変更することもできます。さまざまなタスクで優れたネットワークアーキテクチャを見つけることが可能です。現在、このチューナーはコンピュータビジョンドメインのみをサポートしています。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します
    - task（デフォルト：'cv'）
        -  実験のドメインのことで、今のところ、このチューナーはコンピュータビジョン（cv）ドメインのみをサポートしています
    - input_width（デフォルト：32）
        - 入力画像の幅
    - input_channel（デフォルト：3）
        - 入力画像チャンネル
    - n_output_node（デフォルト：10）
        - クラス数

詳しい説明は[こちら（PDF）](https://arxiv.org/pdf/1806.10282.pdf)を参照してください。

## Metis Tuner

ほとんどのツールは最適な構成を予測するだけですが、Metisは2つの出力を提供します。（a）最適な構成の現在の予測、および（b）次の試験への提案です。これ以上推測する必要はありません。
ほとんどのツールはトレーニングデータセットがノイズの多いデータを持っていないと仮定しますが、Metisは実際にあなたが特定のハイパーパラメータを再サンプリングする必要があるかどうかをあなたに伝えます。

設定できる検索空間の種類は、「choice」「quniform」「uniform」および「randint」だけです。

Metis Tunerはsklearnを必要とするので、先にインストールしてください。

```
pip3 install scikit-learn
```

TPEやSMACと同様に、Metisはブラックボックスチューナーです。システムが各試行を終えるのに長い時間がかかる場合、Metisはランダムサーチのような他のアプローチよりも有利です。さらに、Metisはその後の試験に関するガイダンスを提供します。[これ](https://github.com/Microsoft/nni/blob/master/examples/trials/auto-gbdt/search_space_metis.json)がMetisの使用例です。ユーザーは、NNI SDKを呼び出すことによって、精度などの最終結果をチューナーに送信するだけで済みます。

- 引数
    - optimize_mode
        - maximize（デフォルト）<br/>チューナーはより大きな期待値でハイパーパラメーターセットを返します
        - minimize<br/>チューナーは小さい期待値でハイパーパラメーターセットを返します

詳しい説明は[こちら](https://www.microsoft.com/en-us/research/publication/metis-robustly-tuning-tail-latencies-cloud-systems/)を参照してください。