MATHGRAM

主に数学とプログラミング、時々趣味について。

あれ...?chainerよりkerasの方が書きやすくね?

こんにちは。 本記事は、kerasの簡単な紹介とmnistのソースコードを軽く紹介するという記事でございます。
そこまで深い説明はしていないので、あんまり期待しないでね・・・笑


[追記:2017/02/10]
kerasに関するエントリまとめました!よかったらこちらも参考にしてください.

モデルの可視化について: [Keras] モデルの可視化をしよう!! - MATHGRAM

自動運転などで使われる技術の実装: Implementation of FCN via Keras - MATHGRAM

Freezeの実験: [Keras] パラメータの更新をさせないfreezeに関する実験 - MATHGRAM

ロス関数を実装するために: [Keras] backend functionを使いこなそう! - MATHGRAM


さて、最近のDeep Learning界隈ではライブラリが豊富ということでpythonが主に使われています。

例えば、caffeやtensor flow、chainerなど・・・。僕の予想ではこれらが日本での三強になっているかと。特に、僕の場合はレイヤーのつながりが読みやすく、何がどうなっているのかすぐにわかるchainerが大好きです。日本で開発されたこともあり、分からないことがあると大体日本語でのレファレンスがあるので、そこも好きなポイントです。

そんなこんなで今までニューラルネットを使った学習はほとんどchainerを使ってきました。

しかし、先日ふとしたきっかけでkerasを使ってみたところ・・・

あれ…?chainerよりkerasの方が書きやすくね?

と魔が差してしまいました。完全に浮気です。

ということで今回は、chainerからkerasに浮気してしまった僕の言い訳(kerasの魅力)を書いていこうかと思います。
まずは概要を説明して、その後に恒例のMNISTを見ながらどのように層が構成されるか見ていきましょう!
それでは早速。

kerasとは?

kerasとは、theanoをベースにしたdeep learning用のフレームワークです。粒度としてはcaffeやchainerと同等のものとなりますね。(ちょっと修正。kerasはラッパーだから、caffeとchainerとは少し違うかも。すみませんでした。)

読み方はわかりません。笑
インドネシア語でkerasは"強い"や"硬い"を意味するそうですが・・・。ここが由来になってるのかなぁ?誰か知っている人いたら教えてください。とりあえずインドネシア語の発音をカタカナにしてみると"クーラス"と聞こえるので、日本語で発音するときはクーラスにしておこうかなと。まぁこんなんどうでもいいですね。

※ (11/10) なんか"ケラス"っぽいっすw すみませんでした。

開発者はgoogleの方で、ここでもgoogleの凄さを感じますね。 git hubとdocumentは以下です。

github.com Keras Documentation

それでは中身の紹介に移りましょう。

使い勝手の良さ

さて、kerasの魅力について語っていきましょう。と言っても、まだほとんど触っていないので本当のところまだまだ魅力をわかりきっていません。笑
じゃあなんでkerasに惹かれたのかという話ですが、全てはネットワークの書き方にあります。chainerをネットワークのわかりやすさから選択していた僕にとってここの部分は結構大きいわけです。
あとchainerのようにpipだけで入れられるのはかなりいいところだと思います。しかもpython3.x系にもちゃんと対応していて、GPUモードをMacで動かすのも結構簡単です。El CapitanだとchainerのGPUモードを動かすのが現状難しいようなので、Macユーザにとっても嬉しい部分だと思います。Mac上でGPUモードの環境を構築する方法はすぐに記事でまとめます。しばしお待ちを。

(5/4: GPUモードに関する記事書きました!)

それではmnistのソースコードを見ながらどのようにネットワークを組むのかを見ていきましょう。今回はMNISTまでに止まりますが、kerasのソースコードはゴリゴリ読んでいくつもりなので、便利な機能や紹介したいものがありましたら随時書いていきますね。

mnist見ていくよー

一応、僕の環境は以下です。

  • El Capitan , 10.11.4
  • CPU 2.9 GHz Intel Core i5
  • メモリ 8 GB 1600 MHz DDR3
  • NVIDIA GeForce GT 650M 512 MB
  • anaconda3-2.4.0 (pyenv)

まずはpipで簡単にインストールして、gitからコードをダウンロードしましょう。

$ pip install keras

以上でインストールは終了です。ここで、theanoとkerasがインストールされます。
ubuntuにインストールした時、theanoがうまく入らずkerasが動かないことがあったので、動かなかったら一度theanoをuninstallしてからkerasを入れてみてください。

$ pip uninstall theano
$ pip uninstall keras
$ pip install keras

こんな感じでやれば動くはずです。

それでは、とりあえずmnistを動かしましょう。git cloneでコピってきます。

$ cd
$ git clone https://github.com/fchollet/keras.git

サンプルコードは~/keras/examples/にあります。mnistをCNNで学習させているmnist_cnn.pyというファイルがありますのでこいつを動かしてみましょう。

$ python ~/keras/examples/mnist_cnn.py

学習が開始するとこんな感じにプログレスバーが出てきます。
f:id:ket-30:20160429140625g:plain
なにこれ楽しい。lossが下がっていくのを見ているだけで1日終わりそうです。
ちょっとしたことですが、こういうのがデフォルトでついてるのは嬉しいですね。

さて、動作が確認できたのでmnist_cnn.pyの中身を見ていきましょう。
説明したい部分だけ説明するので、全スクリプトを見たい場合は直接みてくださいね!

まずはimportの部分。

from __future__ import print_function
import numpy as np
np.random.seed(1337)  # for reproducibility

from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.utils import np_utils

chainerよりスッキリしてる感じがありますね。(贔屓目)

まあ、とりあえずnumpyをimportしているのはいいとして、その次はなんでしょう?
reproducibilityとは再現性という意味。
np.random.seed(int)でランダムで生成される数字を処理ごとに固定することができます。 数字はなんでもいいらしいので、1337なのは今のところ謎。 この固定した乱数で、データセットのシャッフルを行っている感じでしょうか。

その下はkerasからのimport。
上から順に、

  • データ取得用。
  • ネットワーク作成の基盤となるSequentialのインポート
  • 全結合やドロップアウトなどのネットワークに必要なcoreとなるモジュールのインポート
  • NNで使うモデルをインポート
  • 教師データの整形用

って感じになっています。かなりざっくりとした説明で申し訳ないですが、詳しい内容はDocumentを見てください、お願いします。

さて、重要なのはこっから。
ネットワーク定義の部分ですね。

model = Sequential()

model.add(Convolution2D(nb_filters, nb_conv, nb_conv,
                        border_mode='valid',
                        input_shape=(1, img_rows, img_cols)))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, nb_conv, nb_conv))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer='adadelta',
              metrics=['accuracy'])

以上がネットワークの定義している部分、全てです。
なんてわかりやすいんだ・・・。
chainerでは層を定義した後に、それをforwardで繋げていく感じですが、
kerasの場合はSequentialを基盤に、層の種類や活性化関数などをaddしていくだけでネットワークが構築できてしまいます!

ネットワークを設計したら最後に、

model.compile(loss='categorical_crossentropy',
              optimizer='adadelta',
              metrics=['accuracy'])

のようにロス関数と最適化手法を定義しつつコンパイルしてあげることで、もうモデルは出来上がり。
もちろんロス関数や最適化手法は、有名なものであればほとんど揃っています。
よっぽどのことがない限り、ここで困ることはないでしょう。

NNが組めたら、あとは学習を始めるだけ。

model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch,
          verbose=1, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, verbose=0)

fitの引数にデータを渡して、epochやバッチサイズを定義すれば学習開始です。ちなみに先ほど紹介したプログレスバーの選択がverboseという引数で設定できます。まあ眺めたいのでtrain時は基本1でいきましょう!笑

モデルの評価はevaluate。lossとaccをリストで返してくれます。ここではverboseはいらないので0になってますね。

ほとんど詳しい説明はしていませんが、読んでくれた人がkerasに興味を持ってくれれば満足です。笑 これ以降、基本的にkerasで書いていこうと考えているので、そっちの記事でもっと詳しい部分が書けたらいいなと思っております。

まとめ

かなり駆け足でしたが、kerasの紹介はここまでです。

使いこなせていないのにも関わらず、とりあえず記事にしちゃった感じなので、これから色々紹介できたらいいなー。

それでは!!!