人工知能の学習に関する備忘録

機械学習・強化学習について学んだことをまとめています

TensorFlow(2) 畳み込みネットワーク

公式のチュートリアルに従って,tensorflowをつかってfashion_mnistの分類を行ってみる.

参考:

www.tensorflow.org

作成したノートブックはこちら

colab.research.google.com

まずはimport から

import tensorflow as tf
from tensorflow import keras
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
from keras.layers import 

import numpy as np
import matplotlib.pyplot as plt
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

train_images = train_images / 255.0
test_images = test_images / 255.0

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

つぎにdatasetの読み込みの部分.
pytorchのようにdataset,dataloaderが必要ないから直感的!

生のデータは0~255の範囲のデータなので,0~1にするために,255で割る.

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

f:id:IronArt:20211030034359p:plain

続いて画像の表示,それぞれのデータはこんなかんじ.

model = keras.Sequential([
    Conv2D(32, kernel_size=(3,3), activation='relu', input_shape=(28,28,1), name="conv1"),
    Conv2D(64, kernel_size=(3,3), activation='relu', name="conv2"),
    MaxPooling2D(pool_size=(2,2)),
    Dropout(0.2),
    Flatten(),
    Dense(128, activation='relu'),
    Dropout(0.2),
    Dense(10, activation='softmax', name="output")
])

そして,今回のキモになるモデルの部分. 公式のチュートリアルは全結合層しか使ってないが,今回は畳み込みネットワークを作成しているのでその部分が少し異なる.

またtensorflowはkerasというAPIをサポートしており keras.Sequentialといったメソッドを使うことにより簡単にネットワークを記述可能.

  • Conv2Dで畳み込みの演算を実行,引数は(出力のチャンネル数,畳み込みのカーネルサイズ,活性化関数,入力される画像のshape)となっている.
  • pytorchと違い,tensorflowのshapeは(width,hight,画像のチャンネル数)と最後にチャンネル数が来るので注意が必要
  • またバッチサイズは入力する必要がなく,勝手にtensorflowが処理してくれるため便利!

nameの引数ではひとつひとつの層に名前もつけることも可能で,model.summary()からmodelの全体像の確認が可能

print(model.summary())
Model: "sequential_5"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1 (Conv2D)               (None, 26, 26, 32)        320       
_________________________________________________________________
conv2 (Conv2D)               (None, 24, 24, 64)        18496     
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
dropout_10 (Dropout)         (None, 12, 12, 64)        0         
_________________________________________________________________
flatten_6 (Flatten)          (None, 9216)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 128)               1179776   
_________________________________________________________________
dropout_11 (Dropout)         (None, 128)               0         
_________________________________________________________________
output (Dense)               (None, 10)                1290      
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________
None

各層の概要・パラメータの数などが確認できる.

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

model.fit(train_images, train_labels, epochs=5)

さらに,model.compile()で使用する最適化関数・loss関数・訓練中の評価となるメトリクスを設定する.これを忘れるとエラーが発生するので注意! そしてmodel.fit()に訓練画像,正解ラベル,エポック数を与えて学習

学習結果

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
313/313 - 6s - loss: 0.2343 - accuracy: 0.9221

Test accuracy: 0.9221000075340271

正答率はmodel.evaluate()で計算. 結果は92%程度.全結合層しか使ってないチュートリアルでは同じ回数のepochで86%程度だったので,畳み込み層の有用さが分かりますね.

次回は「画像のどの部分を見て判断したか」が可視化できるgrad-camを実装しようと思います!

発生したエラー

  • ValueError: Input 0 of layer sequential is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: (32, 28, 28)

fashion minstはチャンネルの数は1で以下のように(28,28)のshapeの画像が60000枚集まっていることが分かる.

print(train_images.shape)
(60000, 28, 28)

しかし,実際はrgb画像のような(28,28,3)といった3チャンネルの画像も処理するように,定義したネットワークで処理するためには(28,28,1)のshapeの画像が入っていかなければならない.

そこで以下のように処理することで解決.

train_imgs_shape = train_images.shape 
test_imgs_shape = test_images.shape

train_images = train_images.reshape(train_imgs_shape[0], train_imgs_shape[1], train_imgs_shape[2], 1)
test_images = test_images.reshape(test_imgs_shape[0], test_imgs_shape[1], test_imgs_shape[2], 1)

TensorFlow (1) リンク集

最近TensorFlowを触れる機会が多いので,しっかり勉強してみようと思います!

f:id:IronArt:20211030003504p:plain

ここでは,TensorFlowに関する記事・スライド・webサイトなどのリンクをまとめる予定です.本ブログではある程度の間TensorFlowを使って各種Deep Learningアルゴリズムを実装してみようと思っています.