こんにちは。Toruです。
今回はディープラーニングで必要不可欠とされるパラメーターチューニングを勝手にやってくれるhyperasというライブラリについて紹介します。このライブラリはインストールしてしまえば後は簡単に利用することができるので、是非使ってみてください。
それではやっていきます!
hyperasをインストール
まずはhyperasをインストールしましょう。私の開発環境は以下の通りです。
- MacBook Pro (2017) – MacOS Catalina 10.15.3
- Visual Studio Code – 1.42.1
- python – 3.7.0
- keras – 2.3.1
今回もVSCodeを使ってやりますのでVSCodeのターミナルからhyperasをインストールしましょう。過去にVSCodeでライブラリインストールの仕方について記事を書きましたのでこちらも参考にしてください。
■第一回

■第二回



1 | python -m pip install --user hyperas |
インストールが終わったら早速使っていきましょう。
hyperas実装する前に
今回はminstデータの分類の正解率を、hyperasを使用する前と後で比較したいので、まずは以下のどこにでもあるプログラムを実行します。ここでのパラメータはなんでも構いません。
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 77 78 79 80 81 82 83 84 85 86 87 88 89 | import keras import matplotlib.pyplot as plt 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(256, activation = 'relu', input_shape = (784,))) model.add(Dropout(0.2)) model.add(Dense(128, activation = 'relu')) model.add(Dropout(0.2)) 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 val_loss, val_acc, hist def info(val_acc, val_loss, start_time, hist) : print(" ") print("===============================") print("Accuracy:{:.2f}".format(val_acc * 100), "%") print('loss:{:.2f}'.format(val_loss * 100), "%") #Accuracy Graph plt.rc('font', family = 'serif') fig = plt.figure(figsize = (13, 6)) plt.subplot(1, 2, 1) plt.xlim([0, 20]) plt.plot(hist.history['accuracy'], label = 'Train Acc', color = 'red') plt.plot(hist.history['val_accuracy'], label = 'Test Acc', color = 'm') plt.title('Model Accuracy') plt.xlabel('Epochs') plt.ylabel('accuracy') plt.legend(bbox_to_anchor = (0.7, 0.5), loc = 'center left', borderaxespad = 0,\ fontsize = 8) #Loss Graph plt.rc('font', family = 'serif') plt.subplot(1, 2, 2) plt.xlim([0, 20]) plt.plot(hist.history['loss'], label = 'Train Loss', color = 'blue') plt.plot(hist.history['val_loss'], label = 'Test Loss', color = 'c') plt.title('Model Loss') plt.xlabel('Epochs') plt.ylabel('loss') plt.legend(bbox_to_anchor = (0.7, 0.5), loc = 'center left', borderaxespad = 0, fontsize = 8) plt.savefig ('mnist_graph.png') plt.show() #===Learning=== x_train, y_train, x_test, y_test = get_data() val_loss, val_acc, hist = model(x_train, y_train, x_test, y_test) info(val_acc, val_loss, hist) #============== |
1 2 3 4 | =============================== Accuracy:97.85 % loss:6.74 % =============================== |
グラフにするとこんな感じ。


まぁこんなもんですね。色んな人がMNISTデータの正解率を上げることに努めてくれているので簡単にこのくらいの正解率が出てしまいます。(本当にありがとうございます。)
いよいよhyperasを実装!
さて、前置きが長くなりましたが、早速hyperasを使って上のプログラムのパラメーターチューニングを行なっていきます。ここで注意なのですが、hyperasを使ったプログラムは上のプログラムと少し構成などが違うので、注意して下さい。
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 | 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({{choice([64, 128, 256, 512])}}, activation = 'relu', input_shape = (784,))) model.add(Dropout(0.2) model.add(Dense({{choice([64, 128, 256, 512])}}, activation = 'relu')) model.add(Dropout(0.2) 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) #============== |
もう気づいたかと思いますが、model()の中に {{choice([64, 128, 256, 512])}} があると思います。ここで言っているのは「ニューロン数を64, 128, 256, 512のどれにすればいい?」ということです。この中から最適なものを自動で選んで結果を出力してくれます。
他にも最適な活性化関数を知りたい場合は、 {{choice(['tanh', 'relu', 'elu'])}}
SGDの学習率で最適な値が知りたい場合は、 SGD(lr = {{uniform(0, 1)}})
例えば学習率を0〜1の間に設定したい場合はuniform()を使ってあげればOKです。それでは実行しどんな値が返ってくるか見てみましょう。
1 2 3 4 5 6 7 8 | _________________________________________________________________ None {'Dense': 3, 'Dense_1': 2} 60000 train samples 10000 test samples 10000/10000 [==============================] - 0s 41us/step val_loss: 0.06548591803396121 val_acc: 0.979200005531311 |
私は5分くらい時間がかかってしまいましたが、このような結果が帰ってきました。最初のDenseは3つ目、つまり512(0, 1, 2, 3と並んでいます。)次のDenseは2つ目、つまり256が最適じゃないですか?と言ってます。
しかし、正解率は97.92%と先ほどと比べて0.1%しか上がっていない…。結局、Denseの中のパラメータだけ変えても結果はそんなに変わらないということです。
まとめ
今回はhyperasをインストールし、実際に動かしてみました。さらに、hyperasでDenseの中のパラメータ数を最適な値が返ってくるようにしました。しかし、結果は0.1%上がっただけで驚愕するほど上がるということはありませんでした。これはシリーズ化して正解率99%以上を目指してやってみたいと思います。
次回はDropoutをhyperasを使ってハイパラメータチューニングをしていきます。よければ次回も読んでみてください!
さらにhyperasに興味がある方はこちらもご覧ください。
https://qiita.com/wataoka/items/f46224ccccc5321543bd
おすすめ記事


