ディープラーニングでハイパーパラメータを調整するとき、手作業で行うのは大変です。特にビジネスの世界においては短時間で良いものを作り上げることが重要なので、ハイパーパラメーターをコンピューターに自動調整してもらう機能は大変役に立ちます。
この記事では、時間を掛けずにハイパーパラメーターを自動調整できるRandomSearch(ランダムサーチ)を紹介します。GridSearch(グリッドサーチ)との大きな違いは、パラメーターの組み合わせを総当たりではなくランダムに決めるので、計算時間が短縮されることです。計算機資源のスペックがそこまで高くないときや、短時間で結果を出したい時に利用することが多いです。
目次
ランダムサーチとは?
ランダムサーチとは、機械学習で設定しなければいけないハイパーパラメータを自動調整するアルゴリズムです。総当たりだと時間がかかるので、上限数を設定した上でパラメーターをランダムに選び検証します。
例えば、隠れ層は4か5、活性化関数はreluかsigmoidとします。上限数を2と決めた場合は、2×2で4通りの中から2つをランダムに選び検証します。テストデータを利用した際の損失関数の値が最も小さくなったものが最終的に選ばれます。
ランダムサーチのメリット・デメリット
ハイパーパラメーターの自動調整には、他にグリッドサーチとベイズ最適化があります。これらと比較したときのメリット・デメリットを簡単に紹介します。
計算時間が短い
→検証する組み合わせ数に上限があるので、計算時間が短くて済みます。
最適な組み合わせにたどり着かない可能性がある
→検証する組み合わせはランダムに決定するので、運が悪ければ最適な組み合わせにたどり着けません。
手順①:ライブラリをインポート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import numpy as np import pandas as pd from pandas import Series, DataFrame import sklearn from tensorflow import keras import pathlib import tensorflow as tf from tensorflow.keras import layers from sklearn import datasets, preprocessing from sklearn.model_selection import RandomizedSearchCV from keras.models import Sequential from keras.layers.core import Dense, Activation from keras.utils import np_utils from keras import backend as K from keras.wrappers.scikit_learn import KerasRegressor |
手順②:データの準備
1 2 3 4 | from sklearn.datasets import load_boston boston = load_boston() X = DataFrame(boston.data, columns=boston.feature_names) Y = DataFrame(boston.target, columns=['Price']) |
手順③:データの正規化
1 2 3 4 5 6 7 | def norm(x): mean = np.mean(x) std = np.std(x) return (x - mean) / std X = norm(X) Y = norm(Y) |
スケールや値の範囲が異なる特徴量を正規化するのは良い習慣です。特徴量の正規化なしでもモデルは収束するかもしれませんが、モデルの訓練はより難しくなり、結果として得られたモデルも入力で使われる単位に依存することになります。(TensorFlow公式チュートリアル)
手順④:データをHold Out(訓練用・テスト用に分ける)
1 | train_x, test_x, train_y, test_y = sklearn.model_selection.train_test_split(X, Y) |
手順⑤:モデルを作る
1 2 3 4 5 6 7 8 9 10 | def build_model(activation , optimizer): model = keras.Sequential([ layers.Dense(10, activation=activation, input_shape=[len(train_x.keys(),)]), layers.Dense(10, activation=activation), layers.Dense(15, activation=activation), layers.Dense(1) ]) optimizer = tf.keras.optimizers.RMSprop(0.0008) model.compile(loss='mean_squared_error', optimizer=optimizer, metrics=['mean_absolute_error', 'mean_squared_error']) return model |
手順⑥:ランダムサーチを行う
1 2 3 4 5 6 7 8 9 10 11 12 13 | #ランダムサーチ用パラメーター activation = ["relu", "sigmoid"] optimizer = ["adam", "adagrad"] nb_epoch = [10, 25] batch_size = [5, 10] param_dict = dict(activation=activation, optimizer=optimizer, nb_epoch=nb_epoch, batch_size=batch_size) model = KerasRegressor(build_fn = build_model, verbose=0) rand = RandomizedSearchCV(estimator=model, param_distributions=param_dict, n_iter=10) rand_result = rand.fit(train_x, train_y) |
ランダムサーチは総当たりではなく、ランダムな組み合わせを試します。何組試行するかを指定しているのがn_iter=10の箇所です。この場合は24つまり16通りから10通りをランダムに選んで試します。
次に、ハイパーパラメーターのリストは辞書型にまとめて渡します。
そして、モデルを作成するのですが、その際にbuilt_fnに対してモデルを作る関数build_modelをコールバック関数として渡します。verboseは0だと学習の進行度が非表示になります。表示する場合は1を指定します。
最後に、ランダムサーチの実行です。estimatorにはmodelを、param_distributionsには先ほど作ったハイパーパラメータの辞書型param_dictを渡します。そして、訓練データをフィッティングさせます。
手順⑦:結果の確認
1 2 | print (rand_result.best_params_) #{'optimizer': 'adagrad', 'nb_epoch': 25, 'batch_size': 5, 'activation': 'relu'} |
計算の結果、最も良いハイパーパラメータの組み合わせが分かりました。これでランダムサーチの一連の流れは終了です。rand.predict(説明変数)とすることで、予測値を得ることも出来ます。詳しくは公式ドキュメントを御覧ください。
ランダムサーチの注意点
ランダムサーチは総当たりをしない分、計算時間が短いのが大きなメリットです。しかし、だからこそいつまで立っても真の最適なハイパーパラメーターにたどり着けないというリスクがあります。n_iterの数値をうまく調節していくことが大切になっていきます。