根據昨天的測試我們知道小畫家畫風的數字模型認不出來,那麼我們可以追加訓練讓它學習自己畫的字。
這次我決定再改一下資料格式,並用 tensorflow.keras 的內建函式讀取。
資料格式如下,一個資料夾代表一個標籤,image_dataset_from_directory 會自動的將資料夾名稱轉為標籤。
因為內建函式沒有黑白轉換那麼細的設定,所以我手動把圖片改成黑底白字了。
import tensorflow as tf
saved_model_path = "mnist"
model = tf.keras.models.load_model(saved_model_path)
# 讀取 img 資料夾,32 個一批,圖片大小轉 28*28,灰階模式,標籤是整數
# 不打亂,因為在打亂的情況拿資料會導致每次拿的順序都不同
raw_keras_ds = tf.keras.preprocessing.image_dataset_from_directory("img", batch_size=32, image_size=(28, 28), color_mode="grayscale", label_mode='int', shuffle=False)
這次改用 pandas 整理輸出資料
import pandas as pd
predictions, labels = tuple(zip(*raw_keras_ds))
results = model.predict(predictions)
results = [ [round(j, 2) for j in i] for i in results]
df = pd.DataFrame(results)
df.insert(0, 'label', labels[0])
df.insert(0, 'filepath', raw_keras_ds.file_paths)
print(df.to_markdown())
filepath | label | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | img\0\0.png | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | img\1\1.png | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | img\2\2.png | 2 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | img\3\3.png | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | img\4\4.png | 4 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
5 | img\5\5.png | 5 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
6 | img\6\6.png | 6 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
7 | img\7\7.png | 7 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | img\8\8.png | 8 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | img\9\9.png | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
6, 7, 8 的預測都錯誤。
而如果有人想問我為啥結果和昨天不一樣...我也不知道,也許 opencv 處理圖片的方式和 image_dataset_from_directory 的方式不同。
但錯的和昨天差不多,不過結果被四捨五入了。
batch_size 務必大於資料量,因為原本 image_dataset_from_directory 是使用 batch_size 一批一批的的拿資料。
但為了在結果展示更多資訊,我用了以下兩個方式拿 label 和 file_paths。
predictions, labels = tuple(zip(*raw_keras_ds))
raw_keras_ds.file_paths
如果 batch_size 只有 5 ,那麼他們只會拿到第一批的五筆資料。
說好的追加訓練其實只要一行
model.fit(raw_keras_ds, epochs=5)
追加訓練後的結果,只剩下 7 被認成 1 了。
filepath | label | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | img\0\0.png | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | img\1\1.png | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | img\2\2.png | 2 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | img\3\3.png | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | img\4\4.png | 4 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
5 | img\5\5.png | 5 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
6 | img\6\6.png | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
7 | img\7\7.png | 7 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | img\8\8.png | 8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
9 | img\9\9.png | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
雖然官方的函式庫的確很方便,但我還是比較習慣手刻。
因為不熟悉函式庫,很多都要上網查。