Posted on

建立模型與並使用模型來預測資料

從本機圖片建立模型的簡單範例

以下為從classify資料夾內載入圖片並建構分類模組的範例。圖片資料夾的結構如下:

其中daisy、dandelion、roses、sunflowers、tulips為標籤名稱,在各個資料夾內為圖片

然後使用 image_dataset_from_directory 函數載入圖片,需要傳遞以下參數:

  • directory:包含圖片的目錄。
  • labels:標籤的名稱。預設情況下,每個圖片所在的子目錄將被當作標籤。
  • class_names:標籤的名稱列表。
  • label_mode:標籤的格式。可以是 ‘int’(預設值)、’binary’ 或 ‘categorical’。
  • batch_size: 用於指定每個批次中包含的圖片數量。

在載入圖片時,tf.keras.utils.image_dataset_from_directory 函數會使用 RGB 色彩空間。

tf.keras.utils.image_dataset_from_directory 函數中的 seed 參數用於設置隨機數生成器的種子。

如果指定了 seed 參數,則在載入資料集時,將使用指定的種子初始化隨機數生成器,這樣可以保證每次載入資料集的順序都是一致的。

# TensorFlow and tf.keras
import tensorflow as tf
import pathlib
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
from keras.callbacks import Callback
print(tf.__version__)

batch_size = 32
img_height = 150
img_width = 150

data_dir = pathlib.Path('flower_photos')
# 從資料集中取出訓練資料,需要將 subset 參數設置為 'training'。
train_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)
# 同時設定了 subset 參數和 validation_split 參數,則會從資料集中取出指定的子集作為驗證集。
val_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)

image_batch, label_batch = next(iter(train_ds))

num_classes = len(class_names)

model = tf.keras.Sequential([
    # 對輸入的張量進行縮放。將輸入的張量除以 255,這將會將輸入的值縮放到 0 到 1 之間。
    tf.keras.layers.Rescaling(1./255),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(num_classes)
])
model.compile(
    optimizer='adam',
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy'])

model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=3
)

model.save('model.h5')

然後按下complier之後,會有下面的樣建模的資訊

因為我們在model.compile的metrics選擇了accuracy,因此評估模型的評估方式會以accuracy作為標準

將資料集分割為訓練集和測試集

上面的程式碼我們呼叫了兩次image_dataset_from_directory來分別載入訓練集和測試集
但也可以只載入一次,然後再將資料集分割為訓練集和測試集

範例程式如下

import tensorflow as tf

# 建立圖片資料集
dataset = tf.keras.utils.image_dataset_from_directory(
    'image_directory',
    labels='inferred',
    class_names=None,
    label_mode='int'
)

# 計算資料集的大小
dataset_size = tf.data.experimental.cardinality(dataset).numpy()

# 計算訓練集和測試集的大小
test_size = int(0.2 * dataset_size)
train_size = dataset_size - test_size

# 將資料集分割為訓練集和測試集
train_dataset = dataset.take(train_size)
test_dataset = dataset.skip(train_size)

用 Keras 載入模型並預測答案

以下為一個簡單範例,使用keras.preprocessing.image.load_img所載入的圖片預設格式為 RGB 圖片

import numpy as np
import tensorflow as tf
from tensorflow import keras
import os
import re
import pathlib
# 載入模型
rank_model = keras.models.load_model('model.h5')
# 讓模型輸出的機率值分布在0-1之間
probability_rank_model = tf.keras.Sequential([rank_model, tf.keras.layers.Softmax()])

class_names = ['daisy','dandelion','roses','sunflowers','tulips']

img = keras.preprocessing.image.load_img('./test.jpg', target_size=(150, 150))
if img is None:
    continue
x = keras.preprocessing.image.img_to_array(img)
x = np.expand_dims(x, axis=0)
pred = probability_rank_model.predict(x)[0]
print(path)
top_inds = pred.argsort()[::-1][:5]
if pred[top_inds[0]] > 0.8:
    print('result is: ' + class_names[top_inds[0]])
# 印出機率分布
for data in top_inds:
    print('    {:.3f}  {}'.format(pred[data], class_names[data]))

上面是使用keras.preprocessing.image.load_img來載入圖片
我們也可以使用OpenCV來載入圖片使用

# 使用 OpenCV 讀取圖片
image = cv2.imread('image.jpg')

# 將圖片轉換為 RGB 格式
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = PIL.Image.fromarray(image)
x = keras.preprocessing.image.img_to_array(image)
probability_rank_model.predict(x.tolist())

如何關掉預測時吐出的log

在使用 predict 方法進行預測時,Keras 模型可能會輸出一些訓練過程中的訊息,如果你想要避免輸出這些訊息,則可以在建立模型時設置 verbose 參數。

例如,如果你想要在預測時停止輸出訓練過程中的訊息,則可以在建立模型時使用以下代碼:

# 預測
predictions = model.predict(x_test, verbose=0)

這樣,在進行預測時就不會再輸出任何訓練過程中的訊息了。