概要
Tensorflow2.0のalpha版が出ていたのでBIGGINER TUTORIALSを読む。
バージョン情報
- tensorflow-gpu==2.0.0a0
- Python 3.7.3
読んだページ
Get started with TensorFlow 2.0 for beginnersのクイックスタート、服の分類問題、回帰、モデルの保存とリストアあたり。
環境構築
condaで仮想環境作ってそこにインストールしておく。pip, jupyter, matplotlib, pandas, scikit-learnは仮想環境でも使えるようにしておく。
$ conda create -n tensorflow2-alpha pip jupyter matplotlib pandas scikit-learn $ source activate tensorflow2-alpha
tensorflow2 alphaのインストール。
# CPU版 $ pip install tensorflow==2.0.0-alpha0 # GPU版 $ pip install tensorflow-gpu==2.0.0-alpha0
GPU版はcudaのバージョンが10.0に上げないといけないので、試すだけならCPU版の方が良いかもしれない。
手書き文字の分類
手始めのMNIST手書き数字分類のところ。定番の分類問題をkerasで短手数でさらっと実行している。
まずはデータの読込み。
import tensorflow as tf (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
trainデータは6万件で28×28。
x_train.shape
#=> (60000, 28, 28)
テストデータは1万件。
x_test.shape
#=> (10000, 28, 28)
28×28の値は0(黒)〜255(白)の間を取る。
0〜255の分布をヒストグラムで見るとこんな感じ。
from matplotlib import pylab as plt plt.hist(x_train[0].flatten(), bins=25)
だいたいが黒(背景)で、一部が白(数字の部分)という分布になっている。
実際に30枚を画像としてplotしてみる。
f, ax_list = plt.subplots(3, 10) f.subplots_adjust(left=0, bottom=0.05, right=0.95, top=0.45, wspace=0.1, hspace=0.1) for idx, img in enumerate(x_train[0:30]): ax = ax_list[int(idx / 10)][idx % 10] ax.tick_params(bottom=False, left=False, right=False, top=False) ax.set_xticklabels([]) ax.set_yticklabels([]) ax.imshow(img.reshape(28, 28), cmap=plt.cm.Greys_r)
0〜255のデータを0〜1に変換する。
x_train, x_test = x_train / 255.0, x_test / 255.0
modelの記述とfit / evaluate。Tensorflow1.0をそのまま使うケースと比べてかなり短い記述になっている。
# モデルの設定 model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activation='softmax') ]) # 学習 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=5) # 評価 model.evaluate(x_test, y_test)
実行結果
Epoch 1/5 60000/60000 [==============================] - 2s 40us/sample - loss: 1.1932 - accuracy: 0.6968 Epoch 2/5 60000/60000 [==============================] - 2s 39us/sample - loss: 0.5224 - accuracy: 0.8565 Epoch 3/5 60000/60000 [==============================] - 2s 39us/sample - loss: 0.4080 - accuracy: 0.8847 Epoch 4/5 60000/60000 [==============================] - 2s 38us/sample - loss: 0.3622 - accuracy: 0.8959 Epoch 5/5 60000/60000 [==============================] - 2s 38us/sample - loss: 0.3323 - accuracy: 0.9042 10000/10000 [==============================] - 0s 25us/sample - loss: 0.2835 - accuracy: 0.9174
epochが5回なのでaccuracyは0.9174止まり。30回くらい回したら0.98まではいった。
出来上がったモデルを使って予測処理をしてみる。試しにtestデータ最初の10件で。
model.predict_classes(x_test[0:30]) #=> array([7, 2, 1, 0, 4, 1, 4, 9, 5, 9, 0, 6, 9, 0, 1, 5, 9, 7, 3, 4])
実際の値画像。
f, ax_list = plt.subplots(2, 10) f.subplots_adjust(left=0, bottom=0.05, right=0.95, top=0.35, wspace=0.1, hspace=0.1) for idx, img in enumerate(x_test[0:20]): ax = ax_list[int(idx / 10)][idx % 10] ax.axis('off') ax.imshow(img.reshape(28, 28), cmap=plt.cm.Greys_r)
全部合ってる。簡易なモデルな割に優秀。
違っているものだけ抽出して表示してみる。
pred = model.predict_classes(x_test) false_indices = pred != y_test x_false = x_test[false_indices] print('正解', y_test[false_indices][0:10]) print('予測', pred[false_indices][0:10]) f, ax_list = plt.subplots(1, 10) f.subplots_adjust(left=0, bottom=0.05, right=0.95, top=0.35, wspace=0.1, hspace=0.1) for idx, img in enumerate(x_false[0:10]): ax = ax_list[idx] ax.axis('off') ax.imshow(img.reshape(28, 28), cmap=plt.cm.Greys_r)
実行結果
正解 [4 2 5 6 3 8 2 7 8 0] 予測 [6 7 3 0 5 2 1 3 4 6]
人の目で見ても読みづらいものが多いけど、一応読めないこともないレベルの文字が並んでいる。
不正解データのprobabilityを出してみる。
import numpy as np f, ax_list = plt.subplots(4, 3) f.subplots_adjust(left=0, bottom=0.2, right=1.7, top=2.2, wspace=0.1, hspace=0.3) probas = model.predict_proba(x_false[0:6]) for idx, img in enumerate(x_false[0:6]): ax = ax_list[int(idx / 3) * 2][idx % 3] ax.set_title(str(y_false[idx])) ax.axis('off') ax.imshow(img.reshape(28, 28), cmap=plt.cm.Greys_r) ax = ax_list[int(idx / 3) * 2 + 1][idx % 3] ax.set_yticklabels([]) ax.bar(np.arange(10), probas[idx].flatten())
上が元画像、下がprobabilityの分布。
正解と不正解の答えの間で迷ったようなprobabilityがついていることを期待したが、そうした結果になっているのは下段中央(人の目で見ても5に見える)だけだった。
洋服の分類
続いてfashion MNISTデータを使った分類問題。
fashion_mnistのデータをロードする。
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
yに入っているラベルの紐付けは下記。
labels = { 0: 'T-shirt/top', 1: 'Trouser', 2: 'Pullover', 3: 'Dress', 4: 'Coat', 5: 'Sandal', 6: 'Shirt', 7: 'Sneaker', 8: 'Bag', 9: 'Ankle boot' }
中に入っている画像データを見てみる。
from matplotlib import pylab as plt f, ax_list = plt.subplots(3, 5) f.subplots_adjust(left=0, bottom=0.05, right=1.5, top=1.5, wspace=0.1, hspace=0.1) for idx, img in enumerate(x_train[0:15]): ax = ax_list[int(idx / 5)][idx % 5] ax.axis('off') ax.set_title(labels[y_train[idx]]) ax.imshow(img.reshape(28, 28), cmap=plt.cm.Greys_r)
手書き数字とまったく同じコードで分類してみるepochsは50で。
x_train, x_test = x_train / 255.0, x_test / 255.0 model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=50) model.evaluate(x_test, y_test)
Epoch 1/50 60000/60000 [==============================] - 3s 45us/sample - loss: 0.5307 - accuracy: 0.8132 Epoch 2/50 60000/60000 [==============================] - 3s 42us/sample - loss: 0.4005 - accuracy: 0.8561 Epoch 3/50 60000/60000 [==============================] - 3s 43us/sample - loss: 0.3652 - accuracy: 0.8670 Epoch 4/50 60000/60000 [==============================] - 3s 46us/sample - loss: 0.3472 - accuracy: 0.8725 Epoch 5/50 60000/60000 [==============================] - 3s 43us/sample - loss: 0.3301 - accuracy: 0.8784 中略 Epoch 48/50 60000/60000 [==============================] - 3s 44us/sample - loss: 0.1757 - accuracy: 0.9326 Epoch 49/50 60000/60000 [==============================] - 3s 42us/sample - loss: 0.1761 - accuracy: 0.9321 Epoch 50/50 60000/60000 [==============================] - 3s 50us/sample - loss: 0.1717 - accuracy: 0.9327 10000/10000 [==============================] - 0s 28us/sample - loss: 0.4164 - accuracy: 0.8893
accuracy: 0.8893までいった。
ちゃんと実装すると93%くらいはすぐいくらしいので、下記URLを参考にCNNで実装してみる。
https://github.com/cmasch/zalando-fashion-mnist
# shapeを[28, 28]から[28, 28, 1]に x_train = x_train.reshape([60000, 28, 28, 1]) x_test = x_test.reshape([10000, 28, 28, 1]) # CNNのモデルを生成 from tensorflow.keras import layers model = tf.keras.models.Sequential([ layers.Convolution2D(64, (4, 4), activation='relu', input_shape=(28, 28, 1)), layers.MaxPooling2D((2, 2)), layers.Dropout(0.1), layers.Convolution2D(64, (4, 4), activation='relu'), layers.MaxPooling2D((2, 2)), layers.Dropout(0.3), layers.Flatten(), layers.Dense(256, activation='relu'), layers.Dropout(0.5), layers.Dense(64, activation='relu'), layers.BatchNormalization(), layers.Dense(10, activation='softmax') ]) model.summary()
Model: "sequential_24" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_43 (Conv2D) (None, 25, 25, 64) 1088 _________________________________________________________________ max_pooling2d_34 (MaxPooling (None, 12, 12, 64) 0 _________________________________________________________________ dropout_24 (Dropout) (None, 12, 12, 64) 0 _________________________________________________________________ conv2d_44 (Conv2D) (None, 9, 9, 64) 65600 _________________________________________________________________ max_pooling2d_35 (MaxPooling (None, 4, 4, 64) 0 _________________________________________________________________ dropout_25 (Dropout) (None, 4, 4, 64) 0 _________________________________________________________________ flatten_20 (Flatten) (None, 1024) 0 _________________________________________________________________ dense_49 (Dense) (None, 256) 262400 _________________________________________________________________ dropout_26 (Dropout) (None, 256) 0 _________________________________________________________________ dense_50 (Dense) (None, 64) 16448 _________________________________________________________________ batch_normalization_v2_20 (B (None, 64) 256 _________________________________________________________________ dense_51 (Dense) (None, 10) 650 =================================================================
これで学習してみる。i7-8550UのCPUで学習した場合で1周35秒くらい。epchが50でおよそ30分。これの前に書いた簡易なモデルだと1周3秒なので10倍くらいの重さ。
とはいえこの程度ならCPU版でもなんとかなるしGPU使えばすぐ終わるレベル。
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=50) model.evaluate(x_test, y_test)
Epoch 1/50 60000/60000 [==============================] - 34s 563us/sample - loss: 0.5737 - accuracy: 0.7923 Epoch 2/50 60000/60000 [==============================] - 34s 572us/sample - loss: 0.3969 - accuracy: 0.8558 Epoch 3/50 60000/60000 [==============================] - 36s 603us/sample - loss: 0.3554 - accuracy: 0.8675 中略 Epoch 48/50 60000/60000 [==============================] - 33s 547us/sample - loss: 0.1650 - accuracy: 0.9387 Epoch 49/50 60000/60000 [==============================] - 33s 551us/sample - loss: 0.1644 - accuracy: 0.9394 Epoch 50/50 60000/60000 [==============================] - 33s 548us/sample - loss: 0.1626 - accuracy: 0.9400 10000/10000 [==============================] - 1s 137us/sample - loss: 0.2410 - accuracy: 0.9179
0.9179までいった。
historyを見るとまだサチってはいなさそう。
plt.plot(history.history['accuracy'])
もう100回追加で学習してみたところ、0.9229まではいってほぼサチった。もうちょっと。
続く
長くなったのでその2に続く。
改定履歴
Author: Masato Watanabe, Date: 2019-05-06 記事投稿