Kerasでお試しCNN
30分でDeepLearningを実行できるようにお試しするキット。手っ取り早く始めるためにkeras(Tensorflow backend)をinstall。kerasについては下記のページで紹介されている。 尚、下にinstallのlogを残しているがkerasの前にBackendとなるTensorflowをinstallすると良い。
引用 : Kerasは,Pythonで書かれた,TensorFlowまたはCNTK,Theano上で実行可能な高水準のニューラルネットワークライブラリです. Kerasは,迅速な実験を可能にすることに重点を置いて開発されました. アイデアから結果に到達するまでのリードタイムをできるだけ小さくすることが,良い研究をするための鍵になります. Home - Keras Documentation
$ sudo pip install keras Cannot uninstall 'six'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall. // sixを再度install $ sudo pip install keras --ignore-installed six Installing collected packages: six, numpy, h5py, keras-applications, scipy, keras-preprocessing, pyyaml, keras Running setup.py install for pyyaml ... done Successfully installed h5py-2.8.0 keras-2.2.2 keras-applications-1.0.4 keras-preprocessing-1.0.2 numpy-1.15.2 pyyaml-3.13 scipy-1.1.0 six-1.11.0 // pythonで実行するが失敗 $ python python Python 2.7.10 (default, Oct 6 2017, 22:29:07) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from keras.models import Sequential ImportError: No module named tensorflow // tensorflowをinstall $ sudo pip install tensorflow tf-nightly Successfully installed absl-py-0.5.0 astor-0.7.1 backports.weakref-1.0.post1 enum34-1.1.6 funcsigs-1.0.2 gast-0.2.0 grpcio-1.15.0 keras-applications-1.0.5 keras-preprocessing-1.0.3 markdown-3.0 mock-2.0.0 numpy-1.14.5 pbr-4.2.0 protobuf-3.6.1 tb-nightly-1.11.0a20180923 tensorboard-1.10.0 tensorflow-1.10.1 termcolor-1.1.0 tf-nightly-1.12.0.dev20180923 werkzeug-0.14.1 wheel-0.31.1 // 再度pythonで実行 $ python python Python 2.7.10 (default, Oct 6 2017, 22:29:07) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from keras.models import Sequential Using TensorFlow backend.
Kerasのexampleは下記のgithubにまとまっている。その中でもCIFAR-10の画像を分類する問題を解く。CIFAR-10は32x32pixelの6000枚x10Classの合計60000枚の画像Datasetである。60000枚のうちTrainingが50000枚、残りはEvaluation用として利用される。DownloadしたDatasetのディレクトリ以下のpickleファイルは下記のように置かれている。batches.metaには各Classの画像数とラベル名、data_batch_xにはpythonのdictionaryオブジェクト、これらを意味するのは各画像ファイル名とそれが属するClass名を含む形式で保存されている。 https://github.com/keras-team/keras/tree/master/examples CIFAR-10 and CIFAR-100 datasets
$ tree cifar-10-batches-py cifar-10-batches-py ├── batches.meta ├── data_batch_1 ├── data_batch_2 ├── data_batch_3 ├── data_batch_4 ├── data_batch_5 ├── readme.html └── test_batch
$ less read.py import pickle import sys file_name = sys.argv[1] f = file(file_name, 'rb') print pickle.load(f) $ python read.py batches.meta {'num_cases_per_batch': 10000, 'label_names': ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'], 'num_vis': 3072} $ python read.py data_batch_1 ... 'estate_car_s_001433.png', 'cur_s_000170.png']}
次にkerasのgithubからexampleを落としてくる。exampleディレクトリ配下にあるcifar10_cnn.py
の実行を行う。cifar10_cnn.pyはCIFAR10のDataset、CNN(Convolutional Neural Network)を用いた実装のsampleとなる。githubにあるサンプルをそのまま実行するとエラーが生じるので、下記のdiffを反映する必要がある。
(追記) : cifar10_cnn.py.bak は2018/09/24時点での下記githubのファイルを取得したもの。それに対して、cifar10_cnn.pyが最新の修正を加えたもの。これらのdiffを取ることで修正した箇所を明確にした。 ref : https://github.com/keras-team/keras/blob/master/examples/cifar10_cnn.py
$ git clone git@github.com:keras-team/keras.git $ cd keras/examples $ python cifar10_cnn.py ValueError: `data_format` should be `"channels_last"` (channel after row and column) or `"channels_first"` (channel before row and column). Received: None ValueError: `steps_per_epoch=None` is only valid for a generator based on the `keras.utils.Sequence` class. Please specify `steps_per_epoch` or use the `keras.utils.Sequence` class. $ diff -u cifar10_cnn.py.bak cifar10_cnn.py --- cifar10_cnn.py.bak 2018-09-24 03:24:17.000000000 +0900 +++ cifar10_cnn.py 2018-09-24 05:00:33.000000000 +0900 @@ -11,6 +11,7 @@ from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D +import numpy as np import os batch_size = 32 @@ -102,7 +103,7 @@ # set function that will be applied on each input preprocessing_function=None, # image data format, either "channels_first" or "channels_last" - data_format=None, + data_format="channels_last", # fraction of images reserved for validation (strictly between 0 and 1) validation_split=0.0) @@ -113,6 +114,7 @@ # Fit the model on the batches generated by datagen.flow(). model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size), + steps_per_epoch=int(np.ceil(x_train.shape[0] / float(batch_size))), epochs=epochs, validation_data=(x_test, y_test), workers=4)
cifar10_cnn.py
でやっていることは簡単で、KerasのSequential Modelを利用して複数層を追加している。最終的に出力する分類数(Class数)は前述の通り10個、Data AugmentationをTrueにしているので画像あえて加工したものを水増ししてCNNの入力とし、Modelのロバスト性を高める目的でflagが設定されている。(もちろんFalseで実行することもできる。) batch_sizeの指定はミニバッチとして1度に取り組むデータ(画像)の数であり、全てのClassからbatch_size分のデータをランダムで取得する。1epochとはバッチサイズで指定したサンプルデータを全て使用した状態を示す。よって今回のTrainingで利用する画像数は50000枚、それを32のバッチサイズで画像数を定義するので、50000 / 32 = 1563
1563回のバッチを実施する。1バッチでパラメータを更新するので、1563回の更新が1epoch内で繰り返される。epochsで指定されている100回は1epochを100回実行すること。ややこしいので再度まとめると以下のようになる。
- batch_size : Datasetの中で何個のDataをサンプルして1回のバッチで利用するかを定義する。
- steps_per_epoch : 1epoch内において何回バッチにてパラメータを更新するかを定義する。
- 1epoch : batch_sizeをsteps_per_epoch回繰り返して全てのDatasetを参照した状態を1epochとする。
batch_size = 32 num_classes = 10 epochs = 100 data_augmentation = True
Sequential Modelのaddを利用して層を追加。例えば下記は2次元の畳み込みレイヤーを追加している。Conv2Dの最初の引数は畳み込みにおける出力フィルタの数、第二引数は3x3の畳み込み処理を適用することを意味する。input_shapeについては今回1画像のサイズが32x32、RGBなので3層あるということで、x_train.shape[1:]の値は(32, 32, 3)となっている。Sequential Modelの最初の層にはinput_shapeの情報が必ず必要。 Sequentialモデルのガイド - Keras Documentation
model = Sequential() model.add(Conv2D(32, (3, 3), padding='same', input_shape=x_train.shape[1:]))
model.summary()で各LayerとOutput Shape、Paramを確認することができる。ネットワークの構成としては次のもの。INPUT => CONV * 2 => POOL => CONV *2 => POOL => DENSE * 2 => OUTPUT
。CNNの基本は畳み込み層とプーリング層で構成される。間に活性化関数を挟んでいるが、層としては取り扱わない(実際にはCONV層の活性化を図っている)。
- CONV : 畳み込み層。フィルタの大きさを指定し、入力データの特徴マップを作成するために各フィルタでの畳込みの結果を出力する。
- RELU : ここではCONVの出力に対して活性化関数(ランプ関数)を適用。
- POOL : プーリング演算を適用。CONV層の後に適用され、画像データ等の入力データを扱いやすくするために重要な情報は残しながら圧縮するDown Samplingを行う。
- DENSE : 全結合層。出力層の手前で実行され、出力はClassに分類される確率といった重みになる。 出力層の数は判別したいClass数に一致する必要がある。
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_5 (Conv2D) (None, 32, 32, 32) 896 _________________________________________________________________ activation_7 (Activation) (None, 32, 32, 32) 0 _________________________________________________________________ conv2d_6 (Conv2D) (None, 30, 30, 32) 9248 _________________________________________________________________ activation_8 (Activation) (None, 30, 30, 32) 0 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 15, 15, 32) 0 _________________________________________________________________ dropout_4 (Dropout) (None, 15, 15, 32) 0 _________________________________________________________________ conv2d_7 (Conv2D) (None, 15, 15, 64) 18496 _________________________________________________________________ activation_9 (Activation) (None, 15, 15, 64) 0 _________________________________________________________________ conv2d_8 (Conv2D) (None, 13, 13, 64) 36928 _________________________________________________________________ activation_10 (Activation) (None, 13, 13, 64) 0 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 6, 6, 64) 0 _________________________________________________________________ dropout_5 (Dropout) (None, 6, 6, 64) 0 _________________________________________________________________ flatten_2 (Flatten) (None, 2304) 0 _________________________________________________________________ dense_3 (Dense) (None, 512) 1180160 _________________________________________________________________ activation_11 (Activation) (None, 512) 0 _________________________________________________________________ dropout_6 (Dropout) (None, 512) 0 _________________________________________________________________ dense_4 (Dense) (None, 10) 5130 _________________________________________________________________ activation_12 (Activation) (None, 10) 0 ================================================================= Total params: 1,250,858 Trainable params: 1,250,858 Non-trainable params: 0 _________________________________________________________________
Modelの学習にはcompileメソッドを利用する。loss関数として交差エントロピー、最適化手法としてRMSprop、評価指標としてはaccuracyを出力する。学習済みモデルと重みは指定したファイルに出力することができる。100epoch回した結果としての最終Accuracyは73.4%ということが分かる。
# Let's train the model using RMSprop model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy']) # Save model and weights if not os.path.isdir(save_dir): os.makedirs(save_dir) model_path = os.path.join(save_dir, model_name) model.save(model_path) print('Saved trained model at %s ' % model_path) # Score trained model. scores = model.evaluate(x_test, y_test, verbose=1) print('Test loss:', scores[0]) print('Test accuracy:', scores[1]) Epoch 99/100 1563/1563 [==============================] - 225s 144ms/step - loss: 0.8315 - acc: 0.7239 - val_loss: 0.7454 - val_acc: 0.7533 Epoch 100/100 1563/1563 [==============================] - 221s 142ms/step - loss: 0.8340 - acc: 0.7233 - val_loss: 0.7877 - val_acc: 0.7354 Saved trained model at /xxxx/git/keras/examples/saved_models/keras_cifar10_trained_model.h5 10000/10000 [==============================] - 12s 1ms/step Test loss: 0.7876939533233642 Test accuracy: 0.7354
出力されたh5のファイルからモデルを参照する事も可能。ただし、これを実行する上ではいくつかのpydot系のmoduleをpip installとgraphvizをbrew installしなしなければならないので注意が必要。plot_modelの結果は図のように出力される。
$ pip install pydot $ brew install graphviz from keras.models import load_model model= load_model('./saved_models/keras_cifar10_trained_model.h5') model.summary() from keras.utils import plot_model plot_model(model, 'model.png')