プロクラシスト

今日の寄り道 明日の近道

【Day-17】DeepLearning系ライブラリ、『Keras』の使い方まとめ(2.x対応版)


スポンサーリンク

【最終更新 : 2017.12.17】
※以前書いた記事がObsoleteになったため、2.xできちんと動くように書き直しました。

f:id:imslotter:20171217160749p:plain

データ分析ガチ勉強アドベントカレンダー 17日目。

16日目に、1からニューラルネットを書きました。 それはそれでデータの流れだとか、活性化関数の働きだとか得るものは多かったのですが、Kerasと言うものを使ってみて、何て素晴らしいんだと感動してしまいました

今まで苦労して数十行書いていたものが、わずか3行で書ける! 正直、スクラッチで書く意味って、理解にはいいけど研究や分析には必要あんまないんですよね。車輪の再発明になるし。 と言うわけで、使えるものはどんどん使っていこうスタンスで、今日はKerasの紹介です!

Tutorial+気になった引数を掘り下げて補足のような感じで書いています。 ちなみに、各部のコード以下をつなぎ合わせるとmnistの分類器が動くようになっています。 *1 *2

Kerasとは?

Keras is a high-level neural networks library, written in Python and capable of running on top of either TensorFlow or Theano. It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research. (Documentationより)

TensorFlowやTheanoのラッパーで、簡単にディープ系の実験環境を整えられるようになっている。 実際に使ってみましたが、かなり直感的にネットワークを構成することが出来る

使ってみる

インストール

前に記事でも少し書いた。

www.procrasist.com

pip install tensorflow
pip install keras

で入ると思います。その他のライブラリ(opencvとか)は必要に応じて入れてください。

データを用意

とりあえずMNIST(デフォルトでmnistデータセットは利用可能) from keras.datasets import hogehogeでhogehogeのデータセットを読み込める。以下は読み込めるデータセット一覧

データセット 内容 trainデータ数 testデータ数
mnist 28×28の手書き数字(白黒)10個に分類 60000 10000
cifar10 32×32のカラー画像10に分類 50000 10000
cifar100 32×32のカラー画像100に分類 50000 10000
imdb 25000の映画のレビューのデータセット、ラベルは肯定否定の2種 25000 25000
reuters 11228個のニュースデータセット46トピックに分類 8972 2246
fashion_mnist 28×28の白黒画像を10種類のカテゴリに分類 60000 10000

求めたいものがあれば各々で利用すれば良い。データの渡し方の参考にこれらのデータセットの型を知っておくのがいいかも。

コード

from keras.datasets import mnist
from keras.utils import np_utils
(X_train, y_train),(X_test,y_test) = mnist.load_data()
X_train = X_train.reshape(60000,784).astype('float32')
X_test = X_test.reshape(10000,784).astype('float32')
#[0,255]の値を[0,1]に正規化
X_train /= 255.0
X_test /= 255.0
# 1 of Kのベクトルに変換
y_train = np_utils.to_categorical(y_train, 10)
y_test = np_utils.to_categorical(y_test, 10)

modelを作る

model = Sequential()で初期化
model.add()で層を積んでいく

  • 一層目:IN-784次元, OUT-64次元, 活性化関数-Selu
  • 二層目:IN-default(多分64次元) OUT-10次元 活性化関数-SoftMax関数

入力のイメージは下図。MNISTは28×28の図だが、784次元の1次元ベクトルに変換してから入力している

  • デフォである活性化関数
  • より高度な活性化関数 : keras.layers.advanced_activations モジュール内

関数の違いは下図 f:id:imslotter:20170107153956p:plain

コード

from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense( activation="selu", units=64,input_dim=784))
model.add(Dense(activation="softmax", units=10))

学習プロセス

model.compile

  • 損失関数 : どのくらいの誤差があるかを定量
  • 最適化関数 : 誤差からのパラメータ更新の仕方

loss : 損失関数

デフォで用意されている関数

関数名 意味
mean_squared_error, mse 二乗誤差
mean_absolute_error, mae 絶対誤差
mean_absolute_percentage_error, make 正解とのズレ(絶対値)の割合
mean_squared_logarithmic_error, msle 正解とのズレ(二乗誤差)の割合
squared_hinge マイナスのところは0, プラスは二乗誤差
hinge マイナスのところは0, プラスは絶対値
binary_crossentropy loglossとしても知られている
categorical_crossentropy マルチクラスloglossとして知られている(ラベルがバイナリ配列であることが必要)
sparse_categorical_crossentropy スパースラベルを取る
kullback_leibler_divergence, kld 確率を分布とみなした時の差
poisson 予測-正解*log(予測)の平均
cosine_proximity 予測と正解間のコサイン近似の負の平均

詳しい実装例はこちら GitHub

optimizer : 最適化

デフォで用意されている関数

  • SGD
  • RMSprop(デフォルトパラメータ推奨)
  • Adagrad(デフォルトパラメータ推奨)
  • Adadelta(デフォルトパラメータ推奨)
  • Adam(デフォルトは提案論文通り)
  • Adamax Adamの拡張(無限ノルム)
  • Nadam Adam+RMSprop with momentumらしい
  • TFOptimizer よくわかんない
  • 引数の詳細な設計も可能(こちらを参考 web)
  • 新しい最適化関数を作りたいなら GitHubを参考に

指標の参考には以前書いたこちらの記事もどうぞ

コード

from keras.optimizers import SGD
# optimizer = "sgd"でも、簡単に最適化関数の設定ができる
#(その場合パラメータはデフォルト値)
model.compile(loss="categorical_crossentropy", 
              optimizer=SGD(lr=0.01, momentum=0.9, nesterov=True),
              metrics=["accuracy"])

モデルの学習

学習

model.fit()でモデルを学習。引数は以下

  • X_train : データ(MNISTだと、どこに何個データが入っているか)
  • y_train : ラベル(1-10)
  • batch_size : ミニバッチにデータを分けるこの場合60000個ある学習データを、32個ずつに分けて、重みを更新する
  • epochs : 学習の繰り返し。60000個を何回学習するか
  • validation_split : 学習データの何パーセントをvalidation用データにするか(各エポックのテスト。validationの説明はこの記事を参考にどうぞ : 【Day-10】Cross Validationとパラメータサーチでモデルの調整 )

また、学習の様子も保存されている model.fit内の変数を見てみるとこんな感じ

print(history.__dict__)
>>> {'model': <keras.models.Sequential object at 0x110c78510>, 'params': {'verbose': 1, 'nb_epoch': 3, 'batch_size': 32, 'metrics': ['loss', 'acc', 'val_loss', 'val_acc'], 'nb_sample': 48000, 'do_validation': True}, 'epoch': [0, 1, 2], 'history': {'acc': [0.89862500000000001, 0.94735416666666672, 0.96150000000000002], 'loss': [0.35020409799863894, 0.18034435256198048, 0.132605804043822], 'val_acc': [0.94125000000000003, 0.95816666666666672, 0.96499999999999997], 'val_loss': [0.20651897403846184, 0.14732480475058157, 0.1263637450747192]}}

コールバック関数

keras.callbacks内の関数を使ってモデルの保存ができる。

  • check = ModelCheckpoint("modelname.hdf5")で、学習済みモデルの重みを保存する
    • その場合、model.fit(hogehoge,callbacks=[check])としてやる
  • tensorboardなどとも連携可能
  • 自分でcallbackしたい関数を作ることも可能
  • 詳しくはドキュメント参照

コード

from keras.callbacks import ModelCheckpoint
check = ModelCheckpoint("model.hdf5")
history = model.fit(X_train, y_train, epochs=20, 
                    validation_split=0.2, batch_size=32,
                    callbacks=[check])

モデルの評価

model.evaluate()という関数で、テストデータを用いたモデルの評価が可能。lossとaccuracyを見ている

コード

loss, accuracy = model.evaluate(X_test, y_test)
print("\nloss:{} accuracy:{}".format(loss, accuracy))

モデルの可視化

可視化(tensorflow)

モデルの可視化

ニューラルネットのネットワークを可視化するとき
keras.utils.visualize_util
手順(Mac, Homebrew有り)

  • $brew install graphviz
  • $pip install pydot

とすれば使える

  • to_file : 出力の画像ファイルの名前
  • show_shapes : グラフ中に出力形状を書くか(デフォはFalse)
  • show_layer_names : レイヤー名を書くか(デフォはTrue)

コード

from keras.utils.visualize_util import plot
plot(model, to_file="model.png", show_shapes=True, show_layer_names=True)

こんなのが出てくる
f:id:imslotter:20170107113053p:plain

学習の様子をplot

matplotlibで可視化

コード

import matplotlib.pyplot as plt

def plot_history(history):
    # 精度の履歴をプロット
    plt.plot(history.history['acc'],"o-",label="accuracy")
    plt.plot(history.history['val_acc'],"o-",label="val_acc")
    plt.title('model accuracy')
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.legend(loc="lower right")
    plt.show()

    # 損失の履歴をプロット
    plt.plot(history.history['loss'],"o-",label="loss",)
    plt.plot(history.history['val_loss'],"o-",label="val_loss")
    plt.title('model loss')
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.legend(loc='lower right')
    plt.show()
# modelに学習させた時の変化の様子をplot
plot_history(history)

こんな感じに

f:id:imslotter:20170107151009p:plain

正解率98%とかって半端ないですね。人間と同じかそれ以上の識別性能かも!

Keras 1.xからKeras 2.xの変更点

詳しくはこちらの公式記事を参考

上記チュートリアルで変更した点をメモとして記しておく。

Layerを作る際に、活性化関数も一緒に入れるようになった

from keras.layers import Dense, Activation
model = Sequential()
model.add(Dense(output_dim=64, input_dim=784))
model.add(Activation("relu"))

出力

UserWarning: Update your `Dense` call to the Keras 2 API: `Dense(input_dim=784, units=64)

変更後

model = Sequential()
model.add(Dense( activation="relu", units=64,input_dim=784))

nb_epoch -> epochs

from keras.callbacks import ModelCheckpoint
check = ModelCheckpoint("model.hdf5")
history = model.fit(X_train, y_train, nb_epoch=20, 
                    validation_split=0.2, batch_size=32,
                    callbacks=[check])

出力

UserWarning: The `nb_epoch` argument in `fit` has been renamed `epochs`.
  warnings.warn('The `nb_epoch` argument in `fit` '

変更後

from keras.callbacks import ModelCheckpoint
check = ModelCheckpoint("model.hdf5")
history = model.fit(X_train, y_train, epochs=20, 
                    validation_split=0.2, batch_size=32,
                    callbacks=[check])

show_accuracyの廃止 : defalutでaccuracyが出力されるようになった。

model.evaluate(X_test, y_test, show_accuracy=True)

出力

TypeError: evaluate() got an unexpected keyword argument 'show_accuracy'

変更後

model.evaluate(X_test, y_test)

まとめ

今日のポイントは
・Kerasを使うと、簡単にディープラーニングができる
・可視化も簡単にできるので、実験にはもってこい
・ただ、便利・簡単すぎるので、中身の仕組み知りたい人は一から書いてみるのもいいかも!

実際にモデルを動かしてる部分って、たかだか十数行とかですものね。すごい。 いろいろな実験がしやすそうだし、これからどんどん使っていきたい。

なお、Kerasを書籍で勉強したい方はこちらがオススメです。特にRNNに関しては丁寧に書かれているので!

詳解 ディープラーニング ~TensorFlow・Kerasによる時系列データ処理~

詳解 ディープラーニング ~TensorFlow・Kerasによる時系列データ処理~

明日はKerasを用いたRNN実装にチャレンジしてみる(予定)です!お楽しみに!

*1:日本語があると怒られる方は、ファイル先頭に#coding:utf-8をつけておきましょう。

*2:順を追ってimportしているので、そのまま使うとものすごく見にくいかもです。コピペした後は適当に体裁を整えてください

PROCRASIST