畳み込みニューラルネットワーク, CNN(Convolutional Neural Network)は、画像分類において、画像の位置ずれに強くしたNNです。そのため、画像認証のマルチクラス分類に活用されます。特徴は、2次元フィルタによる畳み込み層と(最大)プーリング層の2種類の中間層で構築することです。
ここで、TensorFlowのチュートリアルのひとつで、Kerasを用いたNNの分類問題の例が下記リンクです。https://www.tensorflow.org/tutorials/keras/classification
本記事では、上記リンクの普通のNNに加えてCNNで実行する雛形コードとその比較結果を載せます。使用するデータセットは、Fashion MNIST(ファッションエムニスト)と呼び、下表のように衣料品10カテゴリの画像が7000枚あります。その内の6000枚を訓練データ、1000枚をテストデータとして使用します。
| ラベル |
クラス |
| 0 |
T-shirt/top |
| 1 |
Trouser |
| 2 |
Pullover |
| 3 |
Dress |
| 4 |
Coat |
| 5 |
Sandal |
| 6 |
Shirt |
| 7 |
Sneaker |
| 8 |
Bag |
| 9 |
Ankle boot
|
処理の流れは大まかには、下図左のようにカラー画像(0~255の数値データ:256階調8bitRGB)を下図右のように白黒画像(0~1の数値データ:10階調白黒)へ正規化して情報量を減らし、輪郭と濃淡から画像を識別して分類します。

即ち、下図のように各ピクセル(画素)の数値データを操作します。

下図は、本コードを実行した結果である。下図左はNN、右はCNNの各々15枚の結果を可視化した画像である。棒の高さは予測時の自身満々度を表す。そして、青色は的中、赤色はハズレを表す。よって、下図左の赤色は自身満々にハズした結果を意味する。

そのNNがハズした内容は、下図のように87%の確率でサンダルとして誤認識した。

一方、CNNの結果は、下図のように60%の確率でスニーカーとして的中した。

目的関数(損失関数:sparse_categorical_crossentropy)の世代進行に伴う変化の様子を下図に示す。下図左はNNで下図右はCNNである。CNNの方がlossが小さく、良いことがわかる。但し、解析時間はNNは44秒、CNNは375秒(6分25秒)で、CNNは8.5倍の時間を要した。つまり、精度と解析時間はトレードオフの関係にある。

■本プログラム
CNNは、フラグ「CNN_flag = True」で実行、NNは「CNN_flag = False」で実行する仕様です。適合度には、ハイパーパラメータの影響も少なからずあります。それらは、世代数、バッチ数、隠れ層の数、ニューロン数、学習率、ドロップ率、最適化アルゴリズムのオプションです。
import tensorflow as tf
from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import time
def check_data_and_normalization(train_images, train_labels, test_images, test_labels):
print("train_images", train_images[0])
print("train_images.shape", train_images.shape)
print("train_labels", len(set(train_labels)))
print("test_images.shape", test_images.shape)
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.title(class_names[train_labels[0]])
plt.savefig('No0.png')
plt.close()
img_cols = test_images[0].shape[1]
pd.options.display.max_columns = img_cols
df_img_matrix = pd.DataFrame(train_images[0])
df_img_matrix_sorted = df_img_matrix.sort_index(ascending=False)
df_img_matrix_sorted.to_csv('No0.csv')
normalized_train_images = train_images / 255.0
normalized_test_images = test_images / 255.0
plt.figure()
plt.imshow(normalized_train_images[0], cmap=plt.cm.binary)
plt.colorbar()
plt.grid(True)
plt.title(class_names[train_labels[0]])
plt.savefig('normalized_No0.png')
plt.close()
df_img_matrix = pd.DataFrame(normalized_train_images[0])
df_img_matrix_sorted = df_img_matrix.sort_index(ascending=False)
df_img_matrix_sorted.to_csv('normalized_No0.csv')
return normalized_train_images, normalized_test_images
def plot_image(i, predictions_array, true_label, img):
if len(predictions_array) != 1:
j = i
else:
j = 0
predictions_array, true_label, img = predictions_array[j], true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
if len(predictions_array) != 1:
j = i
else:
j = 0
predictions_array, true_label = predictions_array[j], true_label[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
def visualization(predictions, test_labels, test_images, test_images_ori):
num_rows = 5
num_cols = 3
num_images = num_rows * num_cols
plt.figure(figsize=(2 * 2 * num_cols, 2 * num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2 * num_cols, 2 * i + 1)
plot_image(i, predictions, test_labels, test_images_ori)
plt.subplot(num_rows, 2 * num_cols, 2 * i + 2)
plot_value_array(i, predictions, test_labels)
plt.savefig(file_name + '_summary.png')
plt.close()
for i in range(num_rows*num_cols):
img = test_images_ori[i]
img = (np.expand_dims(img,0))
if CNN_flag:
img = img.reshape(img.shape[0], img_rows, img_cols, 1)
predictions_single = model.predict(img)
plt.figure(figsize=(7,3))
plt.subplot(1,2,1)
plot_image(i, predictions_single, test_labels, test_images_ori)
plt.subplot(1,2,2)
plot_value_array(i, predictions_single, test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.tight_layout()
plt.savefig(file_name + '_' + str(i) + '.png')
plt.close()
def main():
global class_names, model, img_rows, img_cols
start_time = time.time()
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
train_images, test_images = check_data_and_normalization(train_images, train_labels, test_images, test_labels)
img_rows = train_images[0].shape[0]
img_cols = test_images[0].shape[1]
print('img_rows', img_rows)
print('img_cols', img_cols)
if CNN_flag:
print('CNN_flag', CNN_flag)
print(keras.backend.image_data_format())
train_images = train_images.reshape(train_images.shape[0], img_rows, img_cols, 1)
test_images_bp = test_images
print("test_images test_images_bp")
print(test_images, test_images_bp)
test_images = test_images.reshape(test_images.shape[0], img_rows, img_cols, 1)
model = keras.Sequential([
keras.layers.Conv2D(filters = 32,
kernel_size = (3,3),
padding = "same",
activation = "relu",
input_shape = (img_rows,img_cols,1)),
keras.layers.MaxPooling2D(pool_size=(2,2)),
keras.layers.Flatten(),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(drop_rate),
keras.layers.Dense(10, activation='softmax')
])
else:
model = keras.Sequential([
keras.layers.Flatten(input_shape=(img_rows, img_cols)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dropout(drop_rate),
keras.layers.Dense(10, activation='softmax')
])
optimization_algorithm = keras.optimizers.Adam(lr=learning_rate,
beta_1=0.9,
beta_2=0.999,
epsilon=1e-08)
model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = optimization_algorithm,
metrics = ['accuracy'])
print('model.summary\n', model.summary)
early_stopping = keras.callbacks.EarlyStopping(monitor='loss', patience=10, verbose=1)
hist = model.fit(train_images,
train_labels,
batch_size = batch_size,
epochs = epochs,
callbacks = [early_stopping])
loss = hist.history['loss']
plt.rc('font', family='serif')
fig = plt.figure()
if CNN_flag:
mycolor = 'red'
else:
mycolor = 'blue'
plt.plot(np.arange(1, len(loss)+1), loss, label='loss', color=mycolor)
plt.xlabel('epochs')
plt.ylabel('loss')
print(len(loss))
print(type(len(loss)))
plt.xticks(np.arange(1, int(len(loss)+1), 1))
plt.ylim([0,1])
plt.grid()
plt.title(file_name)
plt.savefig(file_name + '_epochs.png')
plt.close()
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest loss:', test_loss)
print('Test accuracy:', test_acc)
predictions = model.predict(test_images)
if CNN_flag:
visualization(predictions, test_labels, test_images, test_images_bp)
else:
visualization(predictions, test_labels, test_images, test_images)
model.save(file_name + '_model.h5')
print('analysis time:{0:.3f} sec'.format(time.time() - start_time))
with open('result.txt', 'a') as f:
f.write(file_name + '_test_loss=' + str(test_loss) + '\n')
f.write(file_name + '_test_acc=' + str(test_acc) + '\n')
f.write(file_name + '_time=' + str(time.time() - start_time) + '\n')
if __name__ == '__main__':
print(tf.__version__)
CNN_flag = True
if CNN_flag:
file_name = 'CNN'
else:
file_name = 'NN'
epochs = 10
batch_size = 32
learning_rate = 0.001
drop_rate = 0.5
main()
以上
<広告>
リンク