iT邦幫忙

2021 iThome 鐵人賽

DAY 4
1
AI & Data

機器學習與前端網頁系列 第 4

Day 4 tensorflow 模型的存取與 mnist 分類

混了兩天範例,該認真點了XD

今天要訓練模型,儲存模型,讀取模型,拿模型分類圖片,

以下程式碼是昨天的範例,但在最後加上 save ,來儲存模型。
為了自己測試方便,我把檔案副檔名改成了 Jupyter Notebook 的格式(ipynb)。

# a02_tf_mnist.ipynb
import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
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=5)

# 用測試資料評估
model.evaluate(x_test,  y_test, verbose=2)

# 將模型存在 mnist 資料夾
model.save("mnist")

資料夾格式如下,我目前的版本是tensorflow 2.6.0,
其他版本格式可能不同。

接下來再開一個新檔案,a03_tf_category.py

# a03_tf_category.ipynb

import tensorflow as tf
saved_model_path = "mnist"
# 讀取模型
model = tf.keras.models.load_model(saved_model_path)
# 顯示模型資訊
model.summary()

# 顯示模型的輸入輸出格式
print(model.input)
# KerasTensor(type_spec=TensorSpec(shape=(None, 28, 28), dtype=tf.float32, name='flatten_input'), name='flatten_input', description="created by layer 'flatten_input'")

print(model.output)
# KerasTensor(type_spec=TensorSpec(shape=(None, 10), dtype=tf.float32, name=None), name='dense_1/Softmax:0', description="created by layer 'dense_1'")

可以從以下資訊中得知,輸入是一個三維浮點數陣列
第一個維度沒有限制長度,而二三維長度限制是 28。
shape=(None, 28, 28), dtype=tf.float32

接下來看看最初怎麼訓練的。
mnist 是手寫數字集。
mnist.load_data() 會回傳 shape == (60000, 28, 28),且數值介於 0~255 的浮點數。
也就是 60000 張 28 x 28 的手寫數字。
https://www.tensorflow.org/api_docs/python/tf/keras/datasets/mnist/load_data
而在訓練前,範例將數值除以 255,變成介於 0~1 的浮點數。

x_train, x_test = x_train / 255.0, x_test / 255.0

那麼如果我們要用這個模型來分類,要做的預處理就是把圖片處理成 28x28,介於 0~1 的浮點數陣列。
安裝 opencv

conda install -c anaconda opencv

之後來處理圖片,這裡我畫了3張圖

使用 opencv ,讀取讀片,轉灰階,縮小為 28x28。

import cv2

# 讀取圖片 1
img = cv2.imread('1.png')
print(img.shape) # (100, 100, 3)

# 預設圖片讀進來是彩色,有RGB的維度,於是我在這裡把圖片轉灰階
imggray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(imggray.shape) # (100, 100)

# 縮小為 28x28
resized = cv2.resize(imggray, (28, 28))
print(resized.shape) # (28, 28)

# mnist 的圖集黑色是255,白色是 0,而圖片讀進來是 黑色是0,白色是 255
# 所以在這裡除255後,也順便把黑白翻轉過來。
resized = 1 - resized / 255.0

# 原本的格式是將 N 張圖片丟進去訓練,,所以預測時也不能直接丟,而是在外面包一層陣列。
# 最後將陣列化 resized 轉成 tensor 進行預測。
model(tf.constant([resized]))
# <tf.Tensor: shape=(1, 10), dtype=float32, numpy=
# array([[1.1365917e-04, 9.4607556e-01, 3.3843194e-03, 9.3289698e-03,
#         3.3142285e-03, 3.7603064e-03, 1.8111777e-03, 7.1768690e-04,
#         3.1470988e-02, 2.3163184e-05]], dtype=float32)>

# 科學記號不方便看,所以在這裡改為小數點後兩位。
# mnist 的順序是從 0 開始,所以 1.png 這張題片擺在第2位。
# 輸出是一組機率陣列。
[[round(float(j), 2) for j in i] for i in model(tf.constant([resized]))]
# [[0.0, 0.95, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.03, 0.0]]

接下來一次分類三張圖吧

def readimg(imgpath):
    img = cv2.imread(imgpath)
    imggray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    resized = cv2.resize(imggray, (28, 28))
    return 1 - resized / 255.0

imgfiles = ["1.png", "2.png", "3.png"]
imgs = [readimg(i) for i in imgfiles]

[[round(float(j), 2) for j in i] for i in model(tf.constant(imgs))]
# [[0.0, 0.95, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.03, 0.0],
#  [0.0, 0.0, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
#  [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]

上一篇
Day 3 跑一下 Tensorflow 範例
下一篇
Day 5 追加測試
系列文
機器學習與前端網頁30

1 則留言

0
阿瑜
iT邦新手 2 級 ‧ 2021-09-19 22:24:05

想看測試Input是6 或 9 模型的輸出!

johnting iT邦新手 5 級 ‧ 2021-09-20 01:32:04 檢舉

會寫在下一篇

我要留言

立即登入留言