Deep Learning with Python 2章勉強ノート

ManningのMEAP(出版前の本のできた部分から読めるサービス)でTensorFlowとTheanoの両方に対応したラッパーツールkerasの作者Francois Chollet氏の「Deep Learning with Python」が発売されました。

1章は、Francois Chollet氏のDeep Learningへの思いの丈が詰まっており、2章からDeep Learningの紹介が始まります。

ここでは、2章の例題をSageのjupyterノートブックで試しながら、Deep Learningへの理解を深めたいと思います。

kerasのデータセット

kerasにも例題を試すためにデータセットが容易されています。

MNISTは手書き数字の画像データセットで、70000の手書き数字データが収録されおり、ここでは、60000のトレーニング用データ(train_images, train_labels)と10000の検証用データ(test_images, test_labels)に分割しています。

In [1]:
from keras.datasets import mnist
Using TensorFlow backend.
In [2]:
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_imagesのshapeをみると、60000のデータは28x28の画像情報からなり、グレースケールを0〜255で表現しています。

In [3]:
print train_images.shape
# 画像データの例として5行目の値を表示
print train_images[0][5]
(60000, 28, 28)
[  0   0   0   0   0   0   0   0   0   0   0   0   3  18  18  18 126 136
 175  26 166 255 247 127   0   0   0   0]

ラベルには、0〜9の値がセットされています。

In [4]:
len(train_labels)
Out[4]:
60000
In [5]:
train_labels
Out[5]:
array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)

画像の例として5番目の数字を表示します。

In [6]:
import numpy as np
import matplotlib.pyplot as plt 

%matplotlib inline

digit = train_images[4]
plt.imshow(digit.reshape(28,28), cmap=plt.cm.binary)
plt.show()

kerasを使って数字を認識

いきなり、kerasを使った例題がでてきます。

ここでは、処理の詳細を理解する必要はなく、kerasでニューラルネットがまるでレゴのようにニューラルネットを積み重ねるだけで、ネットワークができることを示しています。

以下の例では、以下の様なnetworkを生成しています。

  • Sequentialのインスタンスを作成し、networkにセット
  • ニューラルネットの重みの数を512個、活性化関数にReLu、入力が28*28の密なネットワーク(Dense)をnetworkに追加
  • 出力が10個の活性化関数がSoftmaxとするDenseをnetworkに追加
In [7]:
from keras.models import Sequential
from keras.layers import Dense

network = Sequential()
network.add(Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(Dense(10, activation='softmax'))

次にセットするのは、どのようにニューラルネットワークを学習させるかをcompileメソッドで指定します。

  • optimizer: 学習方法として、rmsprop
  • loss: 損失関数として、categorical_crossentropy(複数のカテゴリから1つを選択する時に使用)
  • metrics: 尺度として、accuracy
In [8]:
network.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

データの加工

イメージデータは、reshapeメソッドを使って(60000, 28, 28)から(60000, 784)の2次元データに変換し、値も整数から0〜1の実数(float32)に変換します。

In [9]:
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

ラベルも0〜9の数字から数字をインデックスとして、1とし、他は0となるone-hot形式に変換します。これには、kerasのユーティリティto_categoricalを使用します。

In [10]:
from keras.utils.np_utils import to_categorical
#  変換前のラベル
print train_labels[0]
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
# 変換後のラベル(one-hot形式)
print train_labels[0]
5
[ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.]

後は、fitメソッドでnetworkを学習させるだけです。全データに対して5回繰り返し(nb_epoch)、ミニバッチのサイズ(batch_size)を128としています。

In [11]:
network.fit(train_images, train_labels, nb_epoch=5, batch_size=128)
Epoch 1/5
60000/60000 [==============================] - 9s - loss: 0.2559 - acc: 0.9253     
Epoch 2/5
60000/60000 [==============================] - 9s - loss: 0.1044 - acc: 0.9693     
Epoch 3/5
60000/60000 [==============================] - 9s - loss: 0.0694 - acc: 0.9792     
Epoch 4/5
60000/60000 [==============================] - 9s - loss: 0.0513 - acc: 0.9846     
Epoch 5/5
60000/60000 [==============================] - 9s - loss: 0.0382 - acc: 0.9886     
Out[11]:
<keras.callbacks.History at 0x7f39a4766610>

検証用データで確認

検証用データで学習したモデル(network)を評価してみましょう。 evaluateメソッドで評価することができます。

検証結果の精度はなんと98%(0.98)と精度が高い結果となっているのですが、本文はこれをOverfitting(過学習)だと説明しています。

In [12]:
test_loss, test_acc = network.evaluate(test_images, test_labels)
 9696/10000 [============================>.] - ETA: 0s
In [13]:
print('test_acc:', test_acc)
('test_acc:', 0.97889999999999999)
In [ ]: