yProcessingClub

すみません、許してください

Keras, TensorFlowをやってみた

はじめに

現在は機械学習の学習をやっている.
今回はニューラルネットワークフレームワークであるKeras及びTensorFlowを触ってみることにする.

www.tensorflow.org
上記のチュートリアルを使用し,適宜コメントなどを追加して理解を深めていく.




実装

データの読み込み

#https://www.tensorflow.org/tutorials/keras/classification?hl=ja
# に勉強のために適宜コメントを追加
# TensorFlow と tf.keras のインポート
import tensorflow as tf
from tensorflow import keras
# ヘルパーライブラリのインポート
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)

2.6.0

# Fashion-MNIST
# ファッション写真のデータセットをロード
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

データの可視化

# 訓練データは6万枚,テストデータは1万枚
print(train_images.shape)
print(test_images.shape)

# 1枚目の画像を表示
import matplotlib.pyplot as plt
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

# 黒が255,白が0,28×28の画像
# 一般的な画像は白が255なので逆

(60000, 28, 28)
(10000, 28, 28)
f:id:Yuri-Processing-Club:20210918143456p:plain



# ラベルは10種類
print(train_labels.shape)
print(np.unique(train_labels))

# ラベルは[0 1 2 3 4 5 6 7 8 9]のようになっている
# 手動でラベル名を設定しておく
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

(60000,)
[0 1 2 3 4 5 6 7 8 9]



# データの正規化(0~1にする)
train_images = train_images / 255.0
test_images = test_images / 255.0
# 訓練データの先頭25枚を表示
plt.figure(figsize=(10,10))
for i in range(25):
    # 5×5に並べて表示
    # subplot(5,5,6)と指定すると,2行1列目部分にプロット
    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:Yuri-Processing-Club:20210918143719p:plain


モデルの構築

# モデルの構築
model = keras.Sequential([
    # 入力層 = 28×28の二次元配列を1次元(28*28=784)に平坦化する
    keras.layers.Flatten(input_shape=(28, 28)),
    # 出力が128個の中間層,活性化関数はReLU
    keras.layers.Dense(128, activation='relu'),
    # 出力が10個の出力層,活性化関数はsoftmax
    keras.layers.Dense(10, activation='softmax')
])

ポンチ絵を描いてみた.
おそらくこんな感じだと思われる.
f:id:Yuri-Processing-Club:20210918145511p:plain

出力層の活性化関数にSoftmax関数を使うのは各出力の総和を1にするため.
各出力を確率として表せる.

例えば['T-shirt/top', 'Trouser', 'Pullover', ...] = [0.7, 0.1, 0.02, ...]という出力になったら,Tシャツの確率が70%であると言える.

# 最適化アルゴリズムはadam
# 誤差関数はクロスエントロピー
# 評価関数は正解率
model.compile(optimizer='adam', 
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

最適化アルゴリズムは誤差関数が小さくなるようにネットワークの重みを更新していくアルゴリズム
局所最適解に陥らないように上手い事やる

誤差関数はモデルが出力した結果と正解との差
3値以上の分類にはクロスエントロピーが用いられる

評価関数はモデルの性能(予測精度)を定量的に表すための関数
今回は分類問題の基本的な評価指標であるところのaccuracy(正解率)を使用
keras.io

学習

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

Epoch 1/5
1875/1875 [==============================] - 2s 742us/step - loss: 0.4980 - accuracy: 0.8238
Epoch 2/5
1875/1875 [==============================] - 1s 698us/step - loss: 0.3736 - accuracy: 0.8659
Epoch 3/5
1875/1875 [==============================] - 1s 731us/step - loss: 0.3346 - accuracy: 0.8796
Epoch 4/5
1875/1875 [==============================] - 1s 699us/step - loss: 0.3123 - accuracy: 0.8866
Epoch 5/5
1875/1875 [==============================] - 1s 698us/step - loss: 0.2928 - accuracy: 0.8919
1エポックあたり1秒くらいで学習が終わった.

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\nTest accuracy:', test_acc)

313/313 - 0s - loss: 0.3604 - accuracy: 0.8720

Test accuracy: 0.871999979019165

引数のverboseって何じゃろと検索したところ
www.tensorflow.org

verbose 0 or 1. Verbosity mode. 0 = silent, 1 = progress bar.

とあって0 or 1を取る値とのこと.
何で2を入れてるねんと思ってverbose=1にしたところ以下のようになった.

313/313 [==============================] - 0s 471us/step - loss: 0.3604 - accuracy: 0.8720

Test accuracy: 0.871999979019165

verbose=1だとプログレスバー及びステップごとの計算時間も表示された.
欲しいのは正解率などの指標なので,verbose=2がこの場合は良いっぽい.


予測

# 予測する
predictions = model.predict(test_images)
# 予測結果の1個目を表示
predictions[0]

array([9.9368699e-06, 1.2327422e-07, 1.6504961e-07, 9.8506057e-09,
5.9519666e-06, 3.3276793e-02, 2.7124054e-06, 2.4480930e-01,
3.0131891e-05, 7.2186488e-01], dtype=float32)

pred_0 = np.argmax(predictions[0])
print(f'予測:{class_names[pred_0]}')
print(f'正解:{class_names[test_labels[0]]}')

# 1枚目の画像を表示
import matplotlib.pyplot as plt
plt.figure()
plt.imshow(test_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

予測:Ankle boot
正解:Ankle boot
f:id:Yuri-Processing-Club:20210918162934p:plain
となり,1個目は正解した.

predictions[0].sum()
# = 1.0

なお,結果の合計値を計算してみると確かに1.0になっており,Softmax関数による確率表現となっている.

def plot_image(i, predictions_array, true_label, img):
    predictions_array, true_label, img = predictions_array[i], 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):
    predictions_array, true_label = predictions_array[i], 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')

結果を表示する関数を実装.

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions,  test_labels)
plt.show()

f:id:Yuri-Processing-Club:20210918164110p:plain

i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions,  test_labels)
plt.show()

f:id:Yuri-Processing-Club:20210918164127p:plain
88%の確率でサンダルです!っつって間違ってしまっている.

# X個のテスト画像,予測されたラベル,正解ラベルを表示します.
# 正しい予測は青で,間違った予測は赤で表示しています.
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)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions, test_labels)
plt.show()

f:id:Yuri-Processing-Club:20210918164707p:plain


まとめ

今回はKeras及びTensorFlowのチュートリアルを進めた.
中間層が1つしか無いが,正解率87%という良い結果を得られた.

Kerasのおかげで大分実装が簡単になっている.
層とか評価関数を引数として指定するだけだからね.

ニューラルネットワークの実装はKerasがやってくれるため,
私の方ではデータや結果の可視化をしっかりとやっていく必要があると感じた.
また,スニーカーの画像を自信満々(88%)にサンダルと言って間違うということもあり,そこはせめて迷って欲しかった.
(サンダル60%,スニーカー40%の確率で判定した,とか)