[!] この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
ハイパーパラメータとは
ハイパーパラメータとは、機械学習において学習パフォーマンスやレイヤーの構成など、トレーニング中に変化しないパラメータのことを指します。
ハイパーパラメータには大きく分けて以下の2種類が存在します。
- モデルハイパーパラメータ
- 隠れ層の数と幅など、モデルの構造に影響する。
- アルゴリズムハイパーパラメータ
- 確率的勾配降下法の学習率やモーメンタムなど、学習アルゴリズムの速度と性質に影響する。
一般的に、ハイパーパラメータは予め複数の候補を用意しておき、それらの組み合わせを入れ替えて予測や推論を繰り返し、最終的に最も性能の良いハイパーパラメータの組み合わせを採用します。
このようなハイパーパラメータの組み合わせ毎の性能評価を自動化したものをハイパーパラメータチューニング、またはハイパーチューニングと呼びます。
ここでは、KerasTuner API ⧉を使用したハイパーチューニングについて触れていきます。
環境構築
Keras Tunerは、Pythonで動作するので、事前にPythonをインストールしてください。
この記事の開発環境は以下の通りです。
- OS : Windows 10 Pro
- Python : 3.9.9
Pythonの仮想環境を作成
Pythonの開発では、パッケージのバージョン違いや依存関係が問題になることがよくあります。
そのため、仮想環境を作成して開発をおこなうことが一般的です。
ここでは、ktproject
という作業フォルダに仮想環境を作成します。
Windows PowerShellを起動し、以下のコマンドを実行して、作業フォルダを作成します。
PS > mkdir ktproject
PS > cd ktproject
続いて、以下のコマンドを実行して、仮想環境を作成および有効化します。
PS > py -3.9 -m venv .venv
PS > .\.venv\Scripts\Activate.ps1
以下のように表示されていれば、仮想環境が有効化されています。
(.venv) PS >
必要なパッケージをインストール
以下のコマンドを実行して、必要なライブラリをインストールします。
(.venv) PS > python -m pip install -U pip
(.venv) PS > pip install tensorflow
(.venv) PS > pip install tensorflow_datasets
(.venv) PS > pip install keras_tuner
これでKeras Tunerを使用する準備は完了です。
データセットについて
ここでは、MNISTデータセット ⧉を使用して手書き数字の画像を0~9のいずれかに分類します。
MNISTデータセットには以下のような手書き数字の画像が多数含まれています。
モデルについて
手書き数字の画像を分類するための単純なモデルを構築します。
ここでは、1つの平滑化の入力層、いくつかの全結合の隠れ層、0~9の数字に分類するための全結合の出力層からなるSequential
モデルを使います。
ハイパーチューニングの流れ
まずは、ハイパーチューニングのおおまかな流れを説明していきます。
ハイパーモデルの定義
ハイパーチューニング用にセットアップするモデルをハイパーモデルと呼びます。
ハイパーモデルは、モデルビルダー関数を使用するか、KerasTuner APIのHyperModel
クラスをサブクラス化することで定義できます。また、あらかじめ定義されているHyperResNet
、HyperXception
を利用することもできます。
ここでは、下記のモデルビルダー関数を使用して、画像分類モデルを定義します。
モデルビルダー関数内で、引数に渡されたHyperParameters
インスタンスのInt
メソッドやChoice
メソッドなどを呼び出すことでハイパーパラメータを定義します。
この関数が呼び出されると、定義されたハイパーパラメータを使用してモデルをハイパーチューニングし、コンパイル済みのモデルを返します。
def model_builder(hp):
model = tf.keras.Sequential()
# 入力層
model.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
# 隠れ層
hp_n_hidden_layers = hp.Int("n_hidden_layers", min_value=1, max_value=5)
for i in range(hp_n_hidden_layers):
hp_units = hp.Int("units_%d" % (i + 1), min_value=32, max_value=512, step=32)
model.add(tf.keras.layers.Dense(hp_units, activation="relu"))
# 出力層
model.add(tf.keras.layers.Dense(10, activation="softmax"))
# 最適化アルゴリズム、損失関数、評価関数を指定してコンパイル
hp_learning_rate = hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4])
model.compile(
optimizer=tf.keras.optimizers.Adam(hp_learning_rate),
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
)
return model
チューナーのインスタンス化
KerasTuner APIには、RandomSearch
、Hyperband
、BayesianOptimization
、およびSklearn
チューナーがあります。
ここでは、以下のようにval_accuracy
の収束を目的として指定し、Hyperband
チューナーをインスタンス化します。
tuner = kt.Hyperband(
hypermodel=model_builder,
objective="val_accuracy",
max_epochs=10,
directory=".cache",
project_name="kt",
overwrite=True,
)
ハイパーチューニングの実施
最後に、チューナーを使ってハイパーチューニングを実施します。
search
メソッドの引数は、tf.keras.model.fit
に使用される引数と同じです。
tuner.search(
ds_train,
epochs=10,
validation_data=ds_test,
)
実際に動作させてみる
以下のコードをktsample.py
として保存します。
import tensorflow as tf
# Tensor Flow のログを抑制
tf.get_logger().setLevel("ERROR")
import keras_tuner as kt
import tensorflow_datasets as tfds
def model_builder(hp):
model = tf.keras.Sequential()
# 入力層
model.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
# 隠れ層
hp_n_hidden_layers = hp.Int("n_hidden_layers", min_value=1, max_value=5)
for i in range(hp_n_hidden_layers):
hp_units = hp.Int("units_%d" % (i + 1), min_value=32, max_value=512, step=32)
model.add(tf.keras.layers.Dense(hp_units, activation="relu"))
# 出力層
model.add(tf.keras.layers.Dense(10, activation="softmax"))
# 最適化アルゴリズム、損失関数、評価関数を指定してコンパイル
hp_learning_rate = hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4])
model.compile(
optimizer=tf.keras.optimizers.Adam(hp_learning_rate),
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
)
return model
def normalizer(image, label):
return tf.cast(image, tf.float32) / 255.0, label
def main():
# データセットをロードする
(ds_train, ds_test), ds_info = tfds.load(
"mnist",
split=["train", "test"],
as_supervised=True,
with_info=True,
)
# 学習用のパイプラインを作成する
ds_train = ds_train.map(normalizer, num_parallel_calls=tf.data.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(ds_info.splits["train"].num_examples)
ds_train = ds_train.batch(128)
ds_train = ds_train.prefetch(tf.data.AUTOTUNE)
# 検証用のパイプラインを作成する
ds_test = ds_test.map(normalizer, num_parallel_calls=tf.data.AUTOTUNE)
ds_test = ds_test.batch(128)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.AUTOTUNE)
# チューナーをインスタンス化する
tuner = kt.Hyperband(
hypermodel=model_builder,
objective="val_accuracy",
max_epochs=10,
directory=".cache",
project_name="kt",
overwrite=True,
)
# ハイパーパラメータを検索する
tuner.search(
ds_train,
epochs=10,
validation_data=ds_test,
)
# 最も性能が良かったハイパーパラメータを使ってモデルをビルドする
hp = tuner.get_best_hyperparameters(num_trials=1)[0]
model = tuner.hypermodel.build(hp)
# モデルに画像とラベルを学習させる
model.fit(
ds_train,
epochs=6,
validation_data=ds_test,
)
# 学習済みのモデルを保存する
model.save("model")
# モデルの構成を表示する
model.summary()
if __name__ == "__main__":
main()
以下のコマンドを実行して、ktsample.py
を実行します。
(.venv) PS > python ktsample.py
実行が完了すると、最も性能が良かったモデルがmodel
フォルダ配下に保存されます。
保存されたモデルは、以下のようにkeras.models.load_model
メソッドでロードし、再利用する事ができます。
def normalizer(image, label):
return tf.cast(image, tf.float32) / 255.0, label
(ds_train, ds_test), ds_info = tfds.load(
"mnist",
split=["train", "test"],
as_supervised=True,
with_info=True,
)
ds_test = ds_test.take(nrows * ncols)
ds_test = ds_test.map(normalizer, num_parallel_calls=tf.data.AUTOTUNE)
ds_test = ds_test.batch(ncols)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.AUTOTUNE)
model = tf.keras.models.load_model('model')
output = model.predict(ds_test)
実際にモデルを再利用し、MNISTデータセットの数字画像を分類した結果は以下の通りです。
まとめ
今回は、分類モデルのモデルハイパーパラメータ、およびアルゴリズムハイパーパラメータに対してKeras Tunerによるハイパーチューニングを実施するところまでを紹介しました。
Keras Tunerを使えば、コンピュータビジョンで使われるような複雑なKerasモデルやKeras Function APIを使ったモデルなどを簡単にハイパーチューニングすることができます。
ぜひ一度、他のモデルで実践してみてください。