0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

optunaしくじり備忘録

Posted at

はじめに

Google Colaboratory上でCNNを使って画像認識を試しています。
ディープラーニングではハイパーパラメータの設定値によって学習結果がかなり異なる結果になることがあります。ハイパーパラメータの最適化を行うことができるoptunaを使っていろいろと試行錯誤してみましたので、その備忘録として記録を残したいと思います。

optunaについて

まず、optunaについておさらいします。
optunaとはPrefferdNetworks社が作成したディープラーニングの学習で使用するハイパーパラメータを最適化するフレームワークのことです。optunaを使ってハイパーパラメータの最適化を実施するためには、公式サイトに記載されているようにoptuna.create_study()で学習を開始し、optimize()で最適化を実施します。
これを実施することにより最適なハイパーパラメータを算出することができます。

trial.suggest_discrete_uniform() APIについて

まず、全結合層のユニット数を設定するため、以下のような設定としました。

Warningが発生するコード
def objective(trial):
    mid_units = int(trial.suggest_discrete_uniform("mid_units", 128, 512, 128))

    model = create_model(mid_units)

study.optimize(objective, n_trials=20)

このコードで実行すると以下のようなWarningが発生しました。

FutureWarning: suggest_discrete_uniform has been deprecated in v3.0.0. This feature will be removed in v6.0.0. See https://github.com/optuna/optuna/releases/tag/v3.0.0. Use suggest_float(..., step=...) instead.

suggest_discrete_uniform() APIは、v3.0.0で非推奨となり、v6.0.0で削除されるとのこと。代わりにsuggest_float() APIを使ってくれ~と記載されていますね。

私が使用している環境のoptunaはv4.1.0でしたので、上記のWarningが出力されたということですね。Warningの指摘通り、suggest_float() APIを使うようにします。

trial.suggest_float() APIについて

suggest_discrete_uniform() APIではなくsuggest_float() APIを使ってくれ~とのことでしたので、単純に置き換えます。
公式Webでは、suggest_float() APIは以下のように説明されています。
 suggest_float(name, low, high, *[, step, log])
lowからhighまでの小数点の値から任意の値を提案するためのAPIのようですね。オプションとしてstepで値の間隔を指定できるのだろうと思います。
128~512の範囲を128間隔で指定したかったので、以下のように記述してみました。

Errorが発生するコード
def objective(trial):
    mid_units = int(trial.suggest_float("mid_units", 128, 512, 128))

    model = create_model(mid_units)

study.optimize(objective, n_trials=20)

このコードで実行すると以下のようなErrorが発生しました。

TypeError: Trial.suggest_float() takes 4 positional arguments but 5 were given

引数の数が異なっている??
いろいろと試行錯誤したところ、正しくは以下のようにstep=で数値の指定が必要なようです。

Errorが発生しないコード
def objective(trial):
    mid_units = int(trial.suggest_float("mid_units", 128, 512, step=128))

    model = create_model(mid_units)

study.optimize(objective, n_trials=20)

Sequentialモデルについて

Sequentialモデルを使ってCNNのモデルを以下のように作成しました。

Warningが発生するコード
IMG_HEIGHT = 100
IMG_WIDTH = 100

def create_model(mid_units):
    model = models.Sequential()
    model.add(keras.layers.Conv2D(filters=32, kernel_size=3,
                 activation="relu", padding="same", input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Conv2D(filters=64, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Conv2D(filters=128, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(mid_units))
    model.add(keras.layers.Dense(2, activation="softmax"))
    return model

def objective(trial):
    mid_units = int(trial.suggest_float("mid_units", 128, 512, step=128))

    model = create_model(mid_units)

study.optimize(objective, n_trials=20)

これを実行すると、以下のようなWariningが発生しました。

UserWarning: Do not pass an input_shape/input_dim argument to a layer. When using Sequential models, prefer using an Input(shape) object as the first layer in the model instead.

Sequentialモデルの場合は、最初のレイヤとしてConv2Dをいきなり配置するのではなくInputレイヤを配置してくれ~ということのようです。
そこで以下のように最初のレイヤとしてInputLayerを追加しました。

Warningが発生するコード2
IMG_HEIGHT = 100
IMG_WIDTH = 100

def create_model(mid_units):
    model = models.Sequential()
    model.add(keras.layers.InputLayer(input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)))
    model.add(keras.layers.Conv2D(filters=32, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Conv2D(filters=64, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Conv2D(filters=128, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(mid_units))
    model.add(keras.layers.Dense(2, activation="softmax"))
    return model

def objective(trial):
    mid_units = int(trial.suggest_float("mid_units", 128, 512, step=128))

    model = create_model(mid_units)

study.optimize(objective, n_trials=20)

これを実行すると、以下のようなWariningが発生しました。

UserWarning: Argument input_shape is deprecated. Use shape instead.

どうもInputLayerではinput_shapeは非推奨のようですね。
以下のように設定することでWarningは解消しました。

Warningが発生しないコード
IMG_HEIGHT = 100
IMG_WIDTH = 100

def create_model(mid_units):
    model = models.Sequential()
    model.add(keras.layers.InputLayer(shape=(IMG_HEIGHT, IMG_WIDTH, 3)))
    model.add(keras.layers.Conv2D(filters=32, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Conv2D(filters=64, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Conv2D(filters=128, kernel_size=3,
                 activation="relu", padding="same"))
    model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), padding="same"))
    model.add(keras.layers.Dropout(0.2))
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(mid_units))
    model.add(keras.layers.Dense(2, activation="softmax"))
    return model

def objective(trial):
    mid_units = int(trial.suggest_float("mid_units", 128, 512, step=128))

    model = create_model(mid_units)

study.optimize(objective, n_trials=20)

おわりに

今回はoptuna実施時に発生したWarningやErrorについて備忘録として残しました。
optunaを使ってハイパーパラメータの最適化を実施していきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?