konchangakita

KPSを一番楽しんでいたブログ 会社の看板を背負いません 転載はご自由にどうぞ

【DeepLearning特訓】CNN を TensorFlow で実装

E資格向けの自習アウトプット
自分用メモ

TensorFlow は、Googleさんが公開している機械学習で便利なライブラリ
現在のところPython では、PyTorch と2大巨頭って感じ?今まで PyTorch 使いなれてきましたが、KPS 的に TensorFlow 使いこなせるようになったほうがよさげなので、この度初挑戦

余談ですが、「テンサー」か「テンソル」かは、Googleの中の人もどっちも使うって言ってた(ようするにどっちでもおk)
なんとなく、ちゃんと学問として線形代数とかやってた人はテンソル派な気がする(なんか頭よさそー)

TensorFlow でモデルを作る下準備

まずは開発環境のバージョンを確認

import sys
import tensorflow as tf
sys.version, tf.__version__

('3.8.7 (tags/v3.8.7:6503f05, Dec 21 2020, 17:59:51) [MSC v.1928 64 bit (AMD64)]',
 '2.4.0')

Python:3.8.7
TensorFlow:2.4.0


今回使うライブラリ群をまとめてインポート
CNN でよく使う関数があらかじめ用意されています
(Kerasを別に呼び出さなくよくなってるの便利)

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPool2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.layers import Dense, Activation, Dropout, Flatten
from tensorflow.keras.utils import plot_model, to_categorical
from tensorflow.keras.datasets import cifar10

Conv2D:畳み込み処理
MaxPool2D:プーリング
Adam、Dropoutなどなど見覚えのあるのたくさんあります
このあたり関数の設置をモデルごとにイチイチ時間をかけなくてもよいのが、TensorFlow を使うメリットですね

学習用データセットの準備

CIFAR-10 という機械学習でよく使われる画像データセットを使います
6万枚の画像(32x32)と10種類クラスラベルがセットになったデータセット

(X_train, t_train),(X_test, t_test) = cifar10.load_data()

データセットは(バッチサイズ, H, W, チャネル数)になっている

X_train.shape

===
(50000, 32, 32, 3)


データの前処理

ピクセル情報は 0 - 255 で表現されているので、0-1に正規化し
10クラス分の one-hot-vector 表現に変換する

# floatに型変換
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

# 各画素値を 0-1 に正規化
X_train /= 255.0
X_test /= 255.0

# クラス分けの数に one-hot-vector 表現に
classes = 10
t_train = to_categorical(t_train, classes)
t_test = to_categorical(t_test, classes)

t_train

===
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 1.],
       [0., 0., 0., ..., 0., 0., 1.],
       ...,
       [0., 0., 0., ..., 0., 0., 1.],
       [0., 1., 0., ..., 0., 0., 0.],
       [0., 1., 0., ..., 0., 0., 0.]], dtype=float32)


TensorFlow でモデル定義

こんな感じで、まずはモデルを定義します

# モデルの定義
model = Sequential()

# 第一層(入力層)
model.add(Conv2D(32,3,input_shape=(32,32,3)))
model.add(Activation('relu'))

# 第二層(中間層)
model.add(Conv2D(32,3))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

# 第三層(中間層)
model.add(Conv2D(64,3))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))

# 第四層(出力層)
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('relu'))

model.add(Dense(classes, activation='softmax'))

adam = Adam(lr=1e-4)

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

まだ学習はスタートしません
定義した内容の確認、この一覧を見れるのは便利かも

model.summary()

Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_12 (Conv2D)           (None, 30, 30, 32)        896       
_________________________________________________________________
activation_16 (Activation)   (None, 30, 30, 32)        0         
_________________________________________________________________
conv2d_13 (Conv2D)           (None, 28, 28, 32)        9248      
_________________________________________________________________
activation_17 (Activation)   (None, 28, 28, 32)        0         
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_14 (Conv2D)           (None, 12, 12, 64)        18496     
_________________________________________________________________
activation_18 (Activation)   (None, 12, 12, 64)        0         
_________________________________________________________________
max_pooling2d_9 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
flatten_4 (Flatten)          (None, 2304)              0         
_________________________________________________________________
dense_8 (Dense)              (None, 1024)              2360320   
_________________________________________________________________
activation_19 (Activation)   (None, 1024)              0         
_________________________________________________________________
dense_9 (Dense)              (None, 10)                10250     
=================================================================
Total params: 2,399,210
Trainable params: 2,399,210
Non-trainable params: 0
_________________________________________________________________

TensorFlow の学習

fit メソッドに(学習用データセット、正解ラベル、バッチサイズ、エポック数を設定)を設定して一行
エポック数分クリック返され、エポックごとに loss と accuracy が表示されます

history = model.fit(X_train, t_train, batch_size=128, epochs=10, verbose=1, validation_split=0.1)


===
Epoch 1/10
352/352 [==============================] - 32s 91ms/step - loss: 1.9641 - accuracy: 0.2943 - val_loss: 1.5312 - val_accuracy: 0.4526
Epoch 2/10
352/352 [==============================] - 35s 98ms/step - loss: 1.4862 - accuracy: 0.4707 - val_loss: 1.3845 - val_accuracy: 0.5032
Epoch 3/10
352/352 [==============================] - 33s 94ms/step - loss: 1.3642 - accuracy: 0.5128 - val_loss: 1.3020 - val_accuracy: 0.5354
Epoch 4/10
352/352 [==============================] - 33s 94ms/step - loss: 1.2694 - accuracy: 0.5538 - val_loss: 1.2081 - val_accuracy: 0.5786
Epoch 5/10
352/352 [==============================] - 33s 94ms/step - loss: 1.1937 - accuracy: 0.5835 - val_loss: 1.1789 - val_accuracy: 0.5906
Epoch 6/10
352/352 [==============================] - 33s 95ms/step - loss: 1.1302 - accuracy: 0.6034 - val_loss: 1.1261 - val_accuracy: 0.6124
Epoch 7/10
352/352 [==============================] - 33s 95ms/step - loss: 1.0869 - accuracy: 0.6204 - val_loss: 1.0827 - val_accuracy: 0.6248
Epoch 8/10
352/352 [==============================] - 33s 95ms/step - loss: 1.0425 - accuracy: 0.6370 - val_loss: 1.0628 - val_accuracy: 0.6266
Epoch 9/10
352/352 [==============================] - 33s 94ms/step - loss: 1.0115 - accuracy: 0.6507 - val_loss: 1.0293 - val_accuracy: 0.6436
Epoch 10/10
352/352 [==============================] - 33s 95ms/step - loss: 0.9706 - accuracy: 0.6656 - val_loss: 1.0025 - val_accuracy: 0.6592

val_accuracyは、0.65xxxなのでまだまだ正解率は荒いですが、
とりあえずこれで推論実施してみる


結果確認、モデルの保存

学習したモデルで、画像一枚分予測(推論)をおこなってみる
1枚分の画像は (1, 32, 32, 3) の shape で渡してやります

X_test[:1].shape

===
(1, 32, 32, 3)


predict メソッドで推論を実行

res = model.predict(X_test[:1])
res, tf.mathargmax(

===
(array([[0.0033276 , 0.00095791, 0.07522933, 0.54298466, 0.03727062,
         0.2813044 , 0.03228953, 0.01226154, 0.01322491, 0.00114957]],
       dtype=float32),
 <tf.Tensor: shape=(), dtype=int64, numpy=3>)

正解ラベルと見比べてみると、「numpy=3」で一致しているので、とりあえずは推論成功の模様

tf.math.argmax(t_test[0])

===
<tf.Tensor: shape=(), dtype=int64, numpy=3>


モデルをパラメータごと保存

model.save('save-path')

さいごに

CNN の基本を実装してみました
E資格的には、CNNの応用モデルも抑えるべきなので、歴史を振り返りつつ
基本中の基本の CNN どう進化していったのかを覚えよう