こんにちわ。Toruです。
今回は前回の続き、hyperasでパワメータチューニングをしてみる回です。今度はDropoutのチューニングに挑戦してみます。前回の記事を見ていない方はこちらからご覧ください。

それでは早速やっていきまーす。
前回までのおさらい
前回はDenseのニューロン数をチューニングして最適な値を取得しました。前回、hyperasを使いDenseの最適なパラメータを設定したモデルがこちらです。
1 2 3 4 5 6 |
model = Sequential() model.add(Dense(512, activation = 'relu', input_shape = (784,)))
model.add(Dropout(0.2)
model.add(Dense(256, activation = 'relu'))
model.add(Dropout(0.2) model.add(Dense(10, activation = 'softmax')) |
Denseの中の512と256、この2つの値をhyperasが自動で求めてくれました。今度はその次のDropoutの引数の最適値を求めていきます。
Dropoutとは
この章はDropoutについて、理解している方は読み飛ばしていただいて大丈夫です。Dropoutのドキュメントには「過学習を防止する効果がある」と記載されています。
イメージとしてはこういうことです。ディープラーニング のモデルは学習するうちに「暗記」をしようとします。ここでいう暗記というのは、「このデータはこの経路で行けばいい答えが出るでしょ」とモデル自体が予め決めつけてしまうことです。(イメージとして)
では、暗記がなぜダメなのか。
例えば、博多ラーメンのように細い麺のラーメンを「ラーメン」という正解ラベルとして、大量に学習させます。そのモデルに二郎系ラーメンを見せると、博多ラーメンを「ラーメン」と暗記しているモデルには「博多ラーメン以外はラーメンじゃない」と判断してしまいます。


(実際にこうなのかはわかりませんが…。)
このまま暗記が進んでいくと、もちろん過学習が起こり、一部のデータにしか適応できなくなってしまいます。これを防ぐのがDropoutです。やっていることは簡単で、ニューロンを指定された分だけ隠します。これだけ。


要するにニューロンを一時的に隠し、「回り道」をさせて学習をさせることで様々なパターンの入力データに対応できるようにします。たったこれだけで過学習を防げてしまいます。
hyperasでDropout
さあ、前置きが長くなりましたが実際に実装していきましょう。Dropoutの引数には通常、0〜1の間の値を入れます。これをhyperasで最適な値を求めるには以下のように入れます。
1 |
model.add(Dropout({{uniform(0, 1)}})) |
「0〜1の間で最適な値を教えて」これだけ。
じゃあ、これを入れたモデルを実際に実行してみましょう。上のやつを入れた今回のプログラムが以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
import keras from hyperas import optim from hyperas.distributions import choice, uniform from hyperopt import STATUS_OK, Trials, tpe, rand from keras import models, optimizers from keras.datasets import mnist from keras.layers import Dense, Dropout from keras.models import Sequential from keras.optimizers import SGD def get_data () : (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape(60000, 784) x_test = x_test.reshape(10000, 784) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255 print(x_train.shape[0], 'train samples') print(x_test.shape[0], 'test samples') y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) return x_train, y_train, x_test, y_test #並びに注意!!! def model(x_train, y_train, x_test, y_test) : model = Sequential() model.add(Dense(512, activation = 'relu', input_shape = (784,))) model.add(Dropout({{uniform(0, 1)}})) model.add(Dense(256, activation = 'relu')) model.add(Dropout({{uniform(0, 1)}})) model.add(Dense(10, activation = 'softmax')) model.summary() model.compile(loss = 'categorical_crossentropy', optimizer = \ SGD(lr = 0.05, clipnorm = 1., nesterov = True),\ metrics = ['accuracy']) hist = model.fit(x_train, y_train, batch_size = 128, epochs = 20, \ verbose = 1, validation_data = (x_test, y_test)) val_loss, val_acc = model.evaluate(x_test, y_test, verbose = 1) return {'loss': -val_acc, 'status': STATUS_OK, 'model': model} def hyper_model(model) : best_run, best_model = optim.minimize(model = model, data = get_data,\ algo = tpe.suggest,\ max_evals = 6, trials = Trials()) print("=====Result=====") print(best_model.summary()) print(best_run) _, _, x_test, y_test = get_data() val_loss, val_acc = best_model.evaluate(x_test, y_test) print("val_loss: ", val_loss) print("val_acc: ", val_acc) return val_acc, val_loss #===Learning=== val_acc, val_loss = hyper_model(model) #============== |
このプログラムを実行した結果がこちら。
1 2 3 4 5 6 7 8 9 |
_________________________________________________________________ None {'Dropout': 0.4844455237320119, 'Dropout_1': 0.026079803111884514} 60000 train samples 10000 test samples 10000/10000 [==============================] - 0s 36us/step val_loss: 0.06725202412945218 val_acc: 0.979200005531311 0.979200005531311 0.06725202412945218 |
1つ目のDropoutの引数には0.4844455237320119
2つ目のDropoutの引数には0.026079803111884514
という結果が出てきました。この値は人間には出せませんね笑 ってか、前回と正解率変わってないやんけ…。
まとめ
- 0〜1の間で最適な値を求めたい時は {{uniform(0, 1)}}
- しかし引数を変える前と後では、正解率はほとんど変わっていない。ってか全く変わっていない。
ここから言える私の結論は、
実は正解率を上げるには、モデル自体のパラメーターにはさほど影響力は無く、そのほとんどは最適化アルゴリズムで決まるんじゃないか?
ということ。全くモデル自体に影響力がないということではありません。最適化アルゴリズムと比較するとおいうことです。ということで次回、hyperasを使って最適な最適化アルゴリズムを求めたいとおもいます。
参考サイト:
https://qiita.com/wataoka/items/f46224ccccc5321543bd