Tensorflow實作_阿拉伯手寫數字分類的實作_基本功常見操作

 本篇實作
使用python3.11
tensorflow2.20 ->這個裝好通常會自動把numpy2.4.6、tensorboard2.20、h5py也裝好
matplotlib3.11.1
numpy2.4.6
tensorboard2.20

第一次於專案裝會要等大概10~15分鐘,會要等好一陣子。


Phase1程式碼-載入mnist資料集
嘗試透過將像素值內容非0的統一轉為1,觀察圖像張量資料。

import tensorflow as tf
mnist = tf.keras.datasets.mnist

# 匯入 MNIST 阿拉伯數字訓練資料
(x_train, y_train),(x_test, y_test) = mnist.load_data()

# 訓練/測試資料的 X/y 維度
print("訓練資料X維度:{0}".format(x_train.shape))
print("訓練資料Y維度:{0}".format(y_train.shape))
print("測試資料X維度:{0}".format(x_test.shape))
print("測試資料X維度:{0}".format(y_test.shape))
# 訓練資料前10筆圖片的數字標準答案
print(y_train[:10])
print(x_train[0])#打印第一張訓練圖的像素值矩陣

data = x_train[0].copy()
data[data>0]=1#把非0的數字轉為1,顯示第1張圖片
print("==========================================")
#把轉換後二維矩陣內容印出來,可以隱約看出數字為5
text_image=[]
for i in range(data.shape[0]):
    text_image.append(''.join(str(data[i])))

for i, row in enumerate(text_image):
    if i < len(text_image) - 1:
        print(f" {repr(row)},")
    else:
        print(f" {repr(row)}")
print("==========================================")


輸出結果
60000 張圖片,每張解析度皆為 28 × 28
這邊把訓練數據集前10印出來,y_train就是(60000,)每張圖對應備標註的正確解答
index = 0 → label = 5
index = 1 → label = 0
index = 2 → label = 4
index = 3 → label = 1  
index = 4 → label = 9




Phase2程式碼-進行特徵縮放(正規化到0~1之間)


import tensorflow as tf
mnist = tf.keras.datasets.mnist

# 匯入 MNIST 阿拉伯數字訓練資料
(x_train, y_train),(x_test, y_test) = mnist.load_data()

# 訓練/測試資料的 X/y 維度
print("訓練資料X維度:{0}".format(x_train.shape))
print("訓練資料Y維度:{0}".format(y_train.shape))
print("測試資料X維度:{0}".format(x_test.shape))
print("測試資料X維度:{0}".format(y_test.shape))
# 訓練資料前10筆圖片的數字標準答案
print(y_train[:10])
print(x_train[0])#打印第一張訓練圖的像素值矩陣

data = x_train[0].copy()
data[data>0]=1#把非0的數字轉為1,顯示第1張圖片

# 進行特徵縮放,正規化公式 = (x - min) / (max - min)。由於像素亮度值範圍:0~255,所以簡化為 x / 255
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0
print(x_train_norm[0])

輸出結果


Phase3程式碼-進行訓練&繪製訓練過程準確度變化曲線

import tensorflow as tf
mnist = tf.keras.datasets.mnist

# 匯入 MNIST 阿拉伯數字訓練資料
(x_train, y_train),(x_test, y_test) = mnist.load_data()

# 訓練/測試資料的 X/y 維度
print("訓練資料X維度:{0}".format(x_train.shape))
print("訓練資料Y維度:{0}".format(y_train.shape))
print("測試資料X維度:{0}".format(x_test.shape))
print("測試資料X維度:{0}".format(y_test.shape))
# 訓練資料前10筆圖片的數字標準答案
print(y_train[:10])
print(x_train[0])#打印第一張訓練圖的像素值矩陣

data = x_train[0].copy()
data[data>0]=1#把非0的數字轉為1,顯示第1張圖片

# 進行特徵縮放,正規化公式 = (x - min) / (max - min)。由於像素亮度值範圍:0~255,所以簡化為 x / 255
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0
print(x_train_norm[0])
# 建立模型
model = tf.keras.models.Sequential([
  tf.keras.layers.Input((28, 28)), #輸入會是28*28=784二維張量
  tf.keras.layers.Flatten(), #扁平層會將二為數據給攤平為一維的784的張量
  tf.keras.layers.Dense(128, activation='relu'),#Dense Layer完全連接層,relu激活函數會把負數變0,正數或0維持原本結果。
  tf.keras.layers.Dropout(0.2),#校正過擬合,設置0.2比例隨意丟棄中間神經元。
  tf.keras.layers.Dense(10, activation='softmax')#輸出層,總共分類10個(0~9)的多元分類。輸出10個機率,用softmax激活函數。若為二元分類可用sigmoid。
])
#設置優化器、損失函數。指定衡量效能指標為Accuracy,也可設置多個用逗號間隔。
#設置loss為sparse_categorical_crossentropy,會在背後幫忙我們針對y單一數字label做one-hot encoding,每個數字變成10個digit表示。。
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
#訓練,拿20%作為validation用途。
history = model.fit(x_train_norm, y_train, epochs=5,validation_split=0.2)
print(history.history.keys())
# 繪製訓練過程準確度曲線
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], 'r')
plt.plot(history.history['val_accuracy'], 'g')
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.show()







紅色是訓練集的準確率
綠色是驗證集的準確率

Phase4程式碼-繪製訓練過程損失函數變化曲線,並進行模型分數評估,把模型另存出來並做整體模型的彙總資訊呈現


import tensorflow as tf
import numpy as np
mnist = tf.keras.datasets.mnist
# 匯入 MNIST 阿拉伯數字訓練資料
(x_train, y_train),(x_test, y_test) = mnist.load_data()

# 訓練/測試資料的 X/y 維度
print("訓練資料X維度:{0}".format(x_train.shape))
print("訓練資料Y維度:{0}".format(y_train.shape))
print("測試資料X維度:{0}".format(x_test.shape))
print("測試資料X維度:{0}".format(y_test.shape))
# 訓練資料前10筆圖片的數字標準答案
print(y_train[:10])
print(x_train[0])#打印第一張訓練圖的像素值矩陣

data = x_train[0].copy()
data[data>0]=1#把非0的數字轉為1,顯示第1張圖片

# 進行特徵縮放,正規化公式 = (x - min) / (max - min)。由於像素亮度值範圍:0~255,所以簡化為 x / 255
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0
print(x_train_norm[0])
# 建立模型
model = tf.keras.models.Sequential([
  tf.keras.layers.Input((28, 28)), #輸入會是28*28=784二維張量
  tf.keras.layers.Flatten(), #扁平層會將二為數據給攤平為一維的784的張量
  tf.keras.layers.Dense(128, activation='relu'),#Dense Layer完全連接層,relu激活函數會把負數變0,正數或0維持原本結果。
  tf.keras.layers.Dropout(0.2),#校正過擬合,設置0.2比例隨意丟棄中間神經元。
  tf.keras.layers.Dense(10, activation='softmax')#輸出層,總共分類10個(0~9)的多元分類。輸出10個機率,用softmax激活函數。若為二元分類可用sigmoid。
])
#設置優化器、損失函數。指定衡量效能指標為Accuracy,也可設置多個用逗號間隔。
#設置loss為sparse_categorical_crossentropy,會在背後幫忙我們針對y單一數字label做one-hot encoding,每個數字變成10個digit表示。。
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
#訓練,拿20%作為validation用途。
history = model.fit(x_train_norm, y_train, epochs=5,validation_split=0.2)
print(history.history.keys())
# 繪製訓練過程準確度曲線
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'], 'r')
plt.plot(history.history['val_accuracy'], 'g')
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.show()

plt.plot(history.history['loss'], 'r')
plt.plot(history.history['val_loss'], 'g')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()

#進行評估並打分數
score=model.evaluate(x_test_norm, y_test, verbose=0)
print("score:{0}".format(score))

# 實際預測前 30 筆
predictions = np.argmax(model.predict(x_test_norm, verbose=False), axis=-1)
# get prediction result
print('prediction:', predictions[0:30])
print('actual    :', y_test[0:30])
# 顯示模型的彙總資訊
model.summary()
# 模型存檔
model.save('model.keras')

# 顯示資料圖像
X2 = x_train[1,:,:]
plt.imshow(X2.reshape(28,28), cmap='gray')
plt.axis('off')
plt.show()
# 顯示錯誤的資料圖像
X2 = x_test[8,:,:]
plt.imshow(X2.reshape(28,28), cmap='gray')
plt.axis('off')
plt.show()




運行輸出效果,可以看到如下清楚呈現神經網路每一層參數與維度資訊

也可觀測到隨著訓練週期拉愈長,準確率提升相對損失就持續下降。


另存出來的模型,之後不用每次跑模型做分類還要重新訓練
也有人是存成model.h5 ,副檔名用.h5或.hdf5 。
.h5 是以前常見的格式,可同時儲存結構與權重,檔案的類別為HDF5。

不過這類通常會有版本相容不好情況要留意,比方TF1.x訓練存出來的.h5拿去給TF2.x載入用就會有問題。

用model.save()保存的完整模型(包含架構、權重、優化器狀態、損失函數配置等所有資訊)
之後用load_model載入完就能直接用。


索引編號的數字,原本手寫數字實際上是5被錯誤預測成6
拿經過正規化過後的測試資料,做模型分數評估為 97%分數

取測試資料第 9 張圖片該索引8)對應位置數值原始訓練的影像呈現出來
可以看到寫的5不太清楚,模型預測成 6,實際答案是 5,

Phase5程式碼-載入訓練好的model並存出模型架構圖

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
mnist = tf.keras.datasets.mnist
# 匯入 MNIST 阿拉伯數字訓練資料
(x_train, y_train),(x_test, y_test) = mnist.load_data()
# 訓練/測試資料的 X/y 維度
print("訓練資料X維度:{0}".format(x_train.shape))
print("訓練資料Y維度:{0}".format(y_train.shape))
print("測試資料X維度:{0}".format(x_test.shape))
print("測試資料X維度:{0}".format(y_test.shape))
x_train_norm, x_test_norm = x_train / 255.0, x_test / 255.0
# 模型載入
model = tf.keras.models.load_model('model.keras')
# 顯示模型的彙總資訊
model.summary()
#進行評估並打分數
score=model.evaluate(x_test_norm, y_test, verbose=0)
print("score:{0}".format(score))
# 實際預測前 30 筆
predictions = np.argmax(model.predict(x_test_norm, verbose=False), axis=-1)
# get prediction result
print('prediction:', predictions[0:30])
print('actual    :', y_test[0:30])
tf.keras.utils.plot_model(model, to_file='model.png')


效果



記得要先做以下動作才會產圖成功
Step1.額外裝graphviz (pip install graphviz)和pydotplus(pip install pydotplus)


Step2.Windows電腦要再裝graphviz軟體
https://www.graphviz.org/download/






Ref:
https://blog.gtwang.org/programming/keras-save-and-load-model-tutorial/
https://ithelp.ithome.com.tw/m/articles/10191627
https://blog.csdn.net/weixin_42629815/article/details/160646635

留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

外貿Payment Term 付款條件(方式)常見的英文縮寫與定義

鼎新ERP_會計系統_總帳管理_財務參數設定_傳票處理