深度學習在影像分類別領域展現出強大的能力,而多層感知器(MLP)作為一種基礎的神經網路模型,是理解深度學習的良好起點。本文將以 Fashion-MNIST 資料集為例,逐步建構一個 MLP 模型,並探討資料預處理、模型架構設計、訓練過程以及效能評估等關鍵環節。透過調整模型引數,例如層數、神經元數量、批次大小和最佳化器等,我們可以深入理解這些引數如何影響模型的學習能力和泛化效能,最終建立一個有效的影像分類別模型。

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split

# 載入 Fashion-MNIST 資料集
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()

# 資料預處理:正規化和展平
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
x_train = x_train.reshape(-1, 784)
x_test = x_test.reshape(-1, 784)

# 標籤預處理:One-hot 編碼
y_train = to_categorical(y_train, num_classes=10)
y_test = to_categorical(y_test, num_classes=10)

# 資料集分割:訓練集和驗證集
x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size=0.2, random_state=42)

# 建立 MLP 模型
model = Sequential([
    Dense(128, activation='relu', input_shape=(784,)),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])

# 編譯模型
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 訓練模型
history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_data=(x_val, y_val))

# 評估模型
loss, accuracy = model.evaluate(x_test, y_test)
print(f"測試集損失:{loss:.4f}")
print(f"測試集準確率:{accuracy:.4f}")

建立Fashion-MNIST的MLP模型基礎架構

本章節將指導如何使用ChatGPT建立一個簡單的多層感知器(MLP)模型,以對Fashion-MNIST資料集進行影像分類別。Fashion-MNIST是一個包含不同類別服飾影像的資料集,透過這個練習,可以深入瞭解如何利用MLP進行影像分類別。

將問題分解為功能特性

根據Fashion-MNIST資料集的特性,我們將從建立一個基礎的MLP模型開始。具體步驟如下:

  1. 建立基礎模型:引導使用者瞭解如何使用ChatGPT建構一個簡單的MLP模型進行影像分類別。涵蓋載入Fashion-MNIST資料集、預處理影像資料、分割資料為訓練集和測試集、定義模型架構、訓練模型、進行預測以及評估模型效能等步驟。

  2. 增加模型層數:在建立基礎模型後,使用者將學習如何嘗試在MLP架構中新增額外的層。探討增加模型的深度或寬度如何影響其效能和捕捉影像資料中複雜模式的能力。

  3. 實驗不同的批次大小:使用者將實驗不同的批次大小對模型訓練的影響,觀察其對訓練速度、收斂性和泛化效能的影響。探討不同批次大小如何在計算效率和模型穩定性之間進行權衡。

  4. 調整神經元數量:使用者將探索調整MLP模型中每個層的神經元數量的影響。透過增加或減少神經元數量,使用者可以觀察到模型容量的變化及其學習影像資料中複雜特徵的能力。

  5. 嘗試不同的最佳化器:最後,使用者將實驗不同的最佳化演算法,如SGD、Adam和RMSprop,以最佳化MLP模型的訓練過程。觀察不同的最佳化器如何影響訓練動態、收斂速度和最終的模型效能。

提示策略

為了利用ChatGPT進行機器學習,需要清楚瞭解如何實作特定的提示策略以生成機器學習程式碼。

策略1:任務-動作-(TAG)提示策略

  1. 任務:具體任務是為Fashion-MNIST資料集建立一個分類別模型。

  2. 動作:涉及建立分類別模型的關鍵步驟包括:

    • 資料預處理:歸一化畫素值、將影像展平為向量、編碼分類別標籤。
    • 資料分割:將資料集分成訓練集、驗證集和測試集。
    • 模型選擇:選擇MLP作為分類別模型。
    • 模型訓練:在訓練資料上訓練MLP。
    • 模型評估:使用準確率、精確度、召回率和混淆矩陣等指標評估模型的效能。
  3. ****:提供以下給ChatGPT:

    • 程式碼應相容Jupyter Notebook。
    • 確保每一行程式碼都有詳細的註解。
    • 在提供程式碼之前,詳細解釋每一行程式碼。

策略2:角色-指令-上下文(PIC)提示策略

  1. 角色:採用初學者的角色,需要逐步學習建立模型的過程,因此程式碼應一步一步生成。

  2. 指令:指定生成單層MLP模型的程式碼,並指示ChatGPT一步一步提供程式碼,等待使用者的反饋。

  3. 上下文:由於ChatGPT已經瞭解Fashion-MNIST資料集,因此不需要提供額外的上下文。

使用免費版ChatGPT建立MLP模型

由於ChatGPT的付費版本具有程式碼直譯器,但不支援Keras和TensorFlow等深度學習函式庫,因此本章節使用免費版本的ChatGPT。

功能特性1:建立基礎模型

首先,撰寫初始提示以建立基礎模型。

# 提示
我想要為Fashion-MNIST資料集建立一個簡單的分類別模型(TAG 1.1),該模型由單層MLP組成(PIC 2.2)。它應包含以下步驟(TAG 1.2),請一步一步提供程式碼,並等待使用者的反饋(PIC 2.2)。
- 資料預處理:歸一化畫素值、將影像展平為向量、編碼分類別標籤。
- 資料分割:將資料集分成訓練集、驗證集和測試集。
- 模型選擇:選擇多層感知器(MLP)作為分類別模型。
- 模型訓練:在訓練資料上訓練MLP。
- 模型評估:使用準確率、精確度、召回率和混淆矩陣等指標評估模型的效能。

我是初學者(PIC 2.1),因此請提供逐步的程式碼,並嚴格遵循以下指令(TAG 1.3):
- 程式碼應相容Jupyter Notebook。
- 確保每一行程式碼都有詳細的註解。
- 在提供程式碼之前,詳細解釋每一行程式碼,這些解釋將被複製到Notebook的文字區塊中。

ChatGPT回應

# 步驟1:資料預處理
import tensorflow as tf
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.utils import to_categorical

# 載入Fashion-MNIST資料集
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()

# 將畫素值歸一化到0到1之間
x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255

# 將影像展平為向量
x_train = x_train.reshape((-1, 784))
x_test = x_test.reshape((-1, 784))

# 對標籤進行one-hot編碼
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)

#### 內容解密:
1. `fashion_mnist.load_data()` 載入Fashion-MNIST資料集包括訓練和測試資料及其標籤
2. `astype('float32') / 255` 將畫素值從0-255歸一化到0-1之間有助於模型的收斂
3. `reshape((-1, 784))` 將28x28的影像展平為784維的向量因為MLP需要一維輸入
4. `to_categorical(y_train, 10)` 對標籤進行one-hot編碼使其適合多分類別問題

這段程式碼完成了資料預處理的第一步,包括載入資料、歸一化畫素值、展平影像以及對標籤進行one-hot編碼。接下來,我們將繼續完成資料分割的步驟。

建構適用於Fashion-MNIST的MLP模型:資料預處理與分割

資料預處理的重要性

在機器學習中,資料預處理是至關重要的步驟。透過各種轉換和正規化技術,我們能夠為訓練準備資料。在本步驟中,我們將對畫素值進行正規化,將影像展平為向量,並對分類別標籤進行編碼,以確保我們的模型能夠有效地學習。

畫素值正規化

將畫素值正規化至0到1之間的範圍,有助於神經網路在訓練過程中更快地收斂,並防止任何特定特徵主導學習過程。這是因為大多數神經網路對輸入資料的尺度敏感,正規化能夠提高模型的穩定性和效能。

影像展平為向量

由於MLP模型無法直接處理多維資料(如影像),因此我們需要將影像展平為一維向量,每個畫素值成為一個特徵。這種轉換使得模型能夠處理影像資料。

分類別標籤編碼

我們的標籤是分類別的(如不同型別的服裝專案),需要將它們編碼為數值,以便模型能夠理解和學習。透過使用LabelEncoder,我們可以將這些分類別標籤轉換為模型可接受的格式。

程式碼實作

import numpy as np
from tensorflow.keras.datasets import fashion_mnist
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split

# 載入Fashion-MNIST資料集
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()

# 正規化畫素值
def normalize_images(train_data, test_data):
    train_data = train_data.astype('float32')
    test_data = test_data.astype('float32')
    train_data /= 255.0
    test_data /= 255.0
    return train_data, test_data

# 將影像展平為向量
def flatten_images(train_data, test_data):
    train_data = train_data.reshape(train_data.shape[0], -1)
    test_data = test_data.reshape(test_data.shape[0], -1)
    return train_data, test_data

# 編碼分類別標籤
def encode_labels(train_labels, test_labels):
    label_encoder = LabelEncoder()
    train_labels = label_encoder.fit_transform(train_labels)
    test_labels = label_encoder.transform(test_labels)
    return train_labels, test_labels

# 套用資料預處理步驟
x_train, x_test = normalize_images(x_train, x_test)
x_train, x_test = flatten_images(x_train, x_test)
y_train, y_test = encode_labels(y_train, y_test)

# 列印預處理後的資料形狀
print("x_train shape:", x_train.shape)
print("y_train shape:", y_train.shape)
print("x_test shape:", x_test.shape)
print("y_test shape:", y_test.shape)

內容解密:

  1. 載入必要的函式庫:我們使用了NumPy進行數值運算,TensorFlow用於載入Fashion-MNIST資料集,以及scikit-learn進行資料預處理。
  2. 載入Fashion-MNIST資料集:使用fashion_mnist.load_data()方法載入資料集,並將其分割為訓練和測試集。
  3. 定義三個函式normalize_imagesflatten_imagesencode_labels,分別用於正規化畫素值、將影像展平為向量和編碼分類別標籤。
    • normalize_images中,我們將畫素值除以255,以縮放到0到1之間。
    • flatten_images中,我們重新調整影像形狀,將其轉換為一維向量。
    • encode_labels中,我們使用LabelEncoder將分類別標籤轉換為數值。
  4. 套用預處理步驟:對訓練和測試資料套用上述預處理步驟,並列印其形狀以驗證處理結果。

資料分割

在完成資料預處理後,下一步是將資料集分割為訓練集、驗證集和測試集。訓練集用於訓練模型的引數,驗證集用於調整超引數和防止過擬合,而測試集則用於評估模型在未見資料上的表現。

資料分割的實作

# 分割資料集為訓練、驗證和測試集
def split_dataset(train_data, train_labels, test_data, test_labels, validation_size=0.1, random_state=42):
    x_train, x_val, y_train, y_val = train_test_split(train_data, train_labels, test_size=validation_size, random_state=random_state)
    # 注意:此處應當直接傳回x_train, y_train, x_val, y_val和原始的x_test, y_test,而不是再次分割x_test和y_test
    return x_train, y_train, x_val, y_val, test_data, test_labels

# 套用資料分割
x_train, y_train, x_val, y_val, x_test, y_test = split_dataset(x_train, y_train, x_test, y_test)

內容解密:

  1. split_dataset函式:此函式用於將資料集分割為訓練、驗證和測試集。
  2. 使用train_test_split:我們使用train_test_split函式從原始訓練資料中分割出一部分作為驗證集。
  3. 傳回分割後的資料集:函式傳回訓練集、驗證集和測試集的特徵及標籤。
  4. 注意實作細節:在原始程式碼中,測試集被錯誤地再次分割。正確的做法是直接使用原始的測試集,而不應再次分割。

透過上述步驟,我們完成了Fashion-MNIST資料集的預處理和分割,為接下來的模型訓練做好了準備。這些步驟對於提高模型的效能和泛化能力至關重要。

建構 Fashion-MNIST 的 MLP 模型與 ChatGPT 的協作流程

資料集分割與驗證

首先,我們需要對 Fashion-MNIST 資料集進行適當的分割,以確保模型的訓練、驗證和測試過程能夠順利進行。以下程式碼展示瞭如何使用 train_test_split 函式來完成資料集的分割:

from sklearn.model_selection import train_test_split

def split_dataset(x_train, y_train, x_test, y_test, val_size=0.2, test_size=0.2, random_state=42):
    # 將訓練集進一步分割為訓練集和驗證集
    x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size=val_size, random_state=random_state)
    return x_train, x_val, y_train, y_val

# 分割資料集
x_train, x_val, y_train, y_val = split_dataset(x_train, y_train, x_test, y_test)

# 輸出分割後資料集的形狀以進行驗證
print("訓練集:")
print("x_train 形狀:", x_train.shape)
print("y_train 形狀:", y_train.shape)
print("\n驗證集:")
print("x_val 形狀:", x_val.shape)
print("y_val 形狀:", y_val.shape)
print("\n測試集:")
print("x_test 形狀:", x_test.shape)
print("y_test 形狀:", y_test.shape)

內容解密:

  1. 匯入必要的函式庫:使用 train_test_split 將資料集進行分割。
  2. 定義資料集分割函式split_dataset 函式負責將原始訓練資料進一步分割為訓練集和驗證集。
  3. 分割訓練資料:根據設定的 val_sizerandom_state 對訓練資料進行分割。
  4. 輸出資料集形狀:確認分割後的資料集形狀,以確保資料正確無誤。

建構單層 MLP 模型

接下來,我們需要定義一個單層的多層感知器(MLP)模型,以作為我們的基準模型。以下是相關程式碼:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

def create_single_layer_mlp(input_shape, num_classes):
    model = Sequential()
    # 新增單一隱藏層,包含 128 個神經元,並使用 ReLU 作為啟用函式
    model.add(Dense(128, activation='relu', input_shape=input_shape))
    # 新增輸出層,使用 softmax 啟用函式進行多類別分類別
    model.add(Dense(num_classes, activation='softmax'))
    return model

# 定義輸入形狀和類別數量
input_shape = x_train.shape[1:]
num_classes = len(np.unique(y_train))

# 建立單層 MLP 模型
model = create_single_layer_mlp(input_shape, num_classes)

# 輸出模型摘要
model.summary()

內容解密:

  1. 匯入 TensorFlow.keras 中的必要模組:使用 SequentialDense 層來定義 MLP 模型。
  2. 定義單層 MLP 模型建立函式create_single_layer_mlp 負責建立一個具有單一隱藏層的 MLP 模型。
  3. 新增隱藏層和輸出層:隱藏層包含 128 個神經元,使用 ReLU 啟用函式;輸出層使用 softmax 啟用函式進行多類別分類別。
  4. 指定輸入形狀和類別數量:根據訓練資料的形狀和標籤的唯一值數量來決定輸入形狀和輸出類別數量。
  5. 輸出模型架構摘要:透過 model.summary() 檢視模型的層級結構、輸出形狀和引數數量。

訓練 MLP 模型

在定義好模型之後,我們需要對其進行訓練。以下程式碼展示瞭如何使用 Adam 最佳化演算法和類別交叉熵損失函式來訓練模型:

# 編譯模型
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# 訓練模型
history = model.fit(x_train, y_train, epochs=10, batch_size=128, validation_data=(x_val, y_val))

內容解密:

  1. 編譯模型:指定損失函式為 sparse_categorical_crossentropy,最佳化演算法為 Adam,並監控準確率。
  2. 訓練模型:使用 fit 方法對模型進行訓練,設定訓練引數如 epoch 數量和 batch size,並使用驗證資料進行監控。