深度學習框架 Keras 提供了多種方式建構神經網路模型,包含 Sequential API、Functional API 和 Model Subclassing。Sequential API 適用於簡單的線性堆積疊模型,Functional API 則更具彈性,可建構更複雜的網路結構。Model Subclassing 提供最大的客製化能力,允許開發者完全控制模型的前向傳播和其他行為。選擇哪種方法取決於模型的複雜度和開發者的需求。構建模型後,需要編譯模型,指定最佳化器、損失函式和評估指標。接著使用訓練資料進行模型訓練,並使用驗證資料監控模型的泛化能力。訓練完成後,使用測試資料評估模型的最終效能,例如準確率和損失值。模型的預測結果可以是 logits 或經過 softmax 啟用函式後的機率分佈,需要根據模型的設計進行解讀。TensorBoard 提供了視覺化工具,可以監控模型的訓練過程、繪製損失和準確率曲線,以及視覺化模型結構,有助於理解模型的行為和效能。

神經網路模型的引數數量

如果我們的模型有三個層次,第一個層次有 128 個神經元,第二個層次有 128 個神經元,第三個層次有 10 個神經元,那麼整個模型就有 118,282 個引數需要學習。

視覺化神經網路模型

為了更好地理解神經網路模型的結構,我們可以使用 plot_model 函式來視覺化模型。這個函式可以將模型的結構儲存為影像檔案。以下是使用 plot_model 函式的示例:

tf.keras.utils.plot_model(model, to_file='model.png', show_shapes=True, show_dtype=True, dpi=100)

這個函式可以將模型的結構儲存為 model.png 檔案,並顯示每個層次的形狀和資料型別訊息。

定義神經網路模型

我們可以使用 tf.keras.models.Sequential 來定義神經網路模型。以下是定義一個具有三個層次的模型的示例:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.InputLayer((784,)))
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))

這個模型有四個層次:輸入層、兩個隱藏層和輸出層。每個隱藏層都有 128 個神經元,輸出層有 10 個神經元。

內容解密:

  • tf.keras.models.Sequential 是用於定義神經網路模型的類別。
  • tf.keras.layers.InputLayer 是用於定義輸入層的類別。
  • tf.keras.layers.Dense 是用於定義密集層的類別。
  • activation 引數是用於指定啟用函式的類別。
  • tf.keras.utils.plot_model 是用於視覺化神經網路模型的函式。

圖表翻譯:

以下是模型的視覺化圖表:

  graph LR
    A[輸入層] --> B[隱藏層1]
    B --> C[隱藏層2]
    C --> D[輸出層]

這個圖表顯示了模型的結構,包括輸入層、隱藏層和輸出層。每個層次都有其自己的神經元和啟用函式。

使用 Keras 的 Flatten 層和功能性 API 建立神經網路模型

在之前的影像預處理章節中,我們學習了兩種方法來將影像矩陣扁平化為向量。現在,我們將使用 Keras 的 Flatten 層來實作這一功能。

首先,讓我們建立一個簡單的神經網路模型,使用 Flatten 層作為第一層。輸入的形狀為 28x28,代表影像的大小。接下來,我們將使用兩個隱藏層,各包含 128 個神經元,最後是輸出層,包含 10 個神經元。

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

在這個例子中,我們使用了 tf.keras.layers.Flatten 來扁平化輸入的影像矩陣。接下來,我們使用 tf.keras.layers.Dense 來建立隱藏層和輸出層。

另外,我們也可以使用功能性 API 來建立模型。功能性 API 比序列 API 更加靈活,允許我們建立更複雜的模型架構。

inputs = tf.keras.Input((784,))
hidden_1 = tf.keras.layers.Dense(128, activation='relu')(inputs)
hidden_2 = tf.keras.layers.Dense(128, activation='relu')(hidden_1)
outputs = tf.keras.layers.Dense(10)(hidden_2)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

在這個例子中,我們使用 tf.keras.Input 來定義輸入的形狀,然後使用 tf.keras.layers.Dense 來建立隱藏層和輸出層。最後,我們使用 tf.keras.Model 來建立模型。

內容解密:

  • tf.keras.layers.Flatten 用於扁平化輸入的影像矩陣。
  • tf.keras.layers.Dense 用於建立隱藏層和輸出層。
  • tf.keras.Input 用於定義輸入的形狀。
  • tf.keras.Model 用於建立模型。

圖表翻譯:

  graph LR
    A[輸入] -->|28x28|> B[Flatten]
    B -->|784|> C[隱藏層 1]
    C -->|128|> D[隱藏層 2]
    D -->|128|> E[輸出層]
    E -->|10|> F[輸出]

這個圖表展示了模型的架構,從輸入的影像矩陣到輸出的結果。

使用 Keras 的 Model Subclassing 建立神經網路模型

在 Keras 中,有三種方式可以建立神經網路模型:Sequential API、Functional API 和 Model Subclassing。前兩種方式相對容易使用,但對於一些複雜的模型架構,可能需要更大的彈性和客製化。這時,Model Subclassing 就成了最佳選擇。

Model Subclassing 的優點

Model Subclassing 提供了最大的彈性和客製化能力。透過建立一個繼承自 tf.keras.Model 的子類別,開發者可以完全控制模型的前向傳遞(forward pass)和其他行為。這使得開發者可以建立出非常複雜和特殊的模型架構。

建立自訂模型類別

要使用 Model Subclassing,首先需要建立一個繼承自 tf.keras.Model 的子類別。這個子類別需要覆寫 call() 方法,該方法定義了模型的前向傳遞。以下是建立一個簡單模型的例子:

import tensorflow as tf

class MyModel(tf.keras.Model):
    def __init__(self, input_shape, target_classes):
        super(MyModel, self).__init__()
        self.inputs = tf.keras.layers.InputLayer(input_shape)
        self.dense1 = tf.keras.layers.Dense(64, activation='relu')
        self.dense2 = tf.keras.layers.Dense(target_classes, activation='softmax')

    def call(self, inputs):
        x = self.dense1(inputs)
        outputs = self.dense2(x)
        return outputs

在這個例子中,MyModel 類別繼承自 tf.keras.Model,並定義了兩個全連線層(dense layer)。call() 方法定義了模型的前向傳遞,首先將輸入傳遞給第一個全連線層,然後將輸出傳遞給第二個全連線層。

建立模型例項和編譯

建立好模型類別後,需要建立模型例項和編譯模型。以下是如何做到的:

model = MyModel((784,), 10)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

在這個例子中,建立了一個 MyModel 例項,輸入形狀為 (784,),目標類別數為 10。然後,使用 compile() 方法編譯模型,指定最佳化器、損失函式和評估指標。

圖表翻譯:
  classDiagram
    class MyModel {
        +__init__(input_shape, target_classes)
        +call(inputs)
    }
    class tf.keras.Model {
        +__init__()
    }
    MyModel --|> tf.keras.Model

這個圖表展示了 MyModel 類別和 tf.keras.Model 類別之間的關係。MyModel 類別繼承自 tf.keras.Model 類別,並覆寫了 call() 方法。

建立自訂神經網路模型

在 TensorFlow 中,建立自訂神經網路模型可以透過繼承 tf.keras.Model 類別來實作。以下是建立一個簡單的神經網路模型的範例:

import tensorflow as tf

class MyModel(tf.keras.Model):
    def __init__(self, input_shape, target_classes):
        super(MyModel, self).__init__()
        self.inputs = tf.keras.layers.Dense(128, activation='relu', input_shape=input_shape)
        self.hidden_1 = tf.keras.layers.Dense(128, activation='relu')
        self.hidden_2 = tf.keras.layers.Dense(128, activation='relu')
        self.outputs = tf.keras.layers.Dense(target_classes)

    def call(self, x):
        x = self.inputs(x)
        x = self.hidden_1(x)
        x = self.hidden_2(x)
        x = self.outputs(x)
        return x

# 建立模型
model = MyModel((784,), 10)

在這個範例中,MyModel 類別繼承了 tf.keras.Model 類別,定義了模型的架構和行為。__init__ 方法是類別的建構子,負責初始化模型的層次和引數。call 方法定義了模型的前向傳播過程。

模型架構

模型的架構由多個全連線層(Dense)組成,每個層次都有自己的啟用函式。輸入層的輸入形狀為 (784,),代表 MNIST 資料集的 28x28 影像。模型的輸出層有 10 個單位,代表 10 個類別。

前向傳播

call 方法中,模型的前向傳播過程被定義。輸入的 x 值先經過輸入層的處理,然後經過兩個隱藏層的處理,最後經過輸出層的處理。每個層次的輸出都會作為下一個層次的輸入。

內容解密:

  • tf.keras.Model 是 TensorFlow 中的基礎模型類別,提供了基本的模型功能。
  • super(MyModel, self).__init__() 是用來呼叫父類別的建構子,初始化父類別的屬性和方法。
  • tf.keras.layers.Dense 是全連線層的實作,可以用來建立輸入層、隱藏層和輸出層。
  • activation 引數用來指定層次的啟用函式,在這個範例中使用的是 ReLU 啟用函式。
  • input_shape 引數用來指定輸入層的輸入形狀。

圖表翻譯:

  graph LR
    A[輸入層] --> B[隱藏層 1]
    B --> C[隱藏層 2]
    C --> D[輸出層]

這個圖表展示了模型的架構,輸入層的輸出作為隱藏層 1 的輸入,隱藏層 1 的輸出作為隱藏層 2 的輸入,隱藏層 2 的輸出作為輸出層的輸入。

訓練和評估人工神經網路(ANN)模型

在前面的章節中,我們已經學習瞭如何定義人工神經網路(ANN)模型的架構。現在,我們將學習如何訓練和評估這個模型。

編譯模型

在定義好模型架構後,我們需要編譯模型。編譯模型的過程包括定義最佳化器、損失函式、評估指標等。在 TensorFlow 中,我們可以使用 compile() 方法來編譯模型。

model.compile(
    optimizer=tf.keras.optimizers.Adam(0.001),
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=[tf.keras.metrics.SparseCategoricalAccuracy()]
)

在上面的程式碼中,我們使用 Adam 最佳化器,設定學習率為 0.001。損失函式使用的是稀疏分類別交叉熵(Sparse Categorical Crossentropy),並且設定 from_logits 引數為 True,表示輸出值為 logit 值,而不是機率分佈。

訓練模型

編譯好模型後,我們可以使用 fit() 方法來訓練模型。訓練模型需要提供輸入資料、目標資料、批次大小、epoch 數等引數。

history = model.fit(
    x_train,
    y_train,
    batch_size=32,
    epochs=50,
    validation_data=(x_test, y_test)
)

在上面的程式碼中,我們設定批次大小為 32,epoch 數為 50,並且提供驗證資料。

評估模型

訓練好模型後,我們可以使用 evaluate() 方法來評估模型的效能。

loss, accuracy = model.evaluate(x_test, y_test)
print(f"Loss: {loss}, Accuracy: {accuracy}")

在上面的程式碼中,我們使用 evaluate() 方法來評估模型在測試資料上的效能,得到損失值和準確率。

預測

我們也可以使用 predict() 方法來預測新的資料。

y_pred = model.predict(x_test)

在上面的程式碼中,我們使用 predict() 方法來預測測試資料的輸出值。

圖表翻譯:

  graph LR
    A[訓練資料] --> B[模型]
    B --> C[編譯模型]
    C --> D[訓練模型]
    D --> E[評估模型]
    E --> F[預測]

圖表翻譯:上面的圖表展示了訓練和評估人工神經網路模型的過程。首先,我們需要提供訓練資料,然後編譯模型,接著訓練模型,然後評估模型的效能,最後使用模型進行預測。

深入探討模型預測過程

在前面的例子中,我們看到模型預測的結果是如何得出的。讓我們更深入地探討這個過程。

預測值的產生

模型的最後一層是具有 10 個神經元的密集層(Dense Layer),並且沒有使用任何啟用函式。這意味著輸出是原始的加權和,沒有經過任何非線性轉換。這種原始的加權和被稱為 logit。

Logit 和啟用函式

如果一個神經元學習了一個線性函式 (f(x) = w_0 + w_1 \cdot x_1 + w_2 \cdot x_2),並且應用了一個啟用函式 (g(x)),那麼最終的輸出將是 (y = g(f(x)))。由於我們的模型架構中,最後一層沒有啟用函式,輸出就是原始的加權和 (f(x)),沒有經過 (g(x)) 的轉換。

預測類別的取得

由於最後一層傳回的是 logit,我們需要從這個 logit 陣列中找到最大元素的索引,以得到預測的類別。這個過程是必要的,因為 logit 可以是任意實數,而我們需要的是類別標籤。

使用 Softmax 啟用函式

另一個選擇是對最後一層應用 softmax 啟用函式。Softmax 函式可以將 logit 陣列轉換為一個機率分佈,其中每個元素都在 0 到 1 之間。如果我們在最後一層使用了 softmax 函式,我們就需要將 SparseCategoricalCrossentropy 損失函式中的 from_logits 引數設為 False。這樣,當我們列印預 y_pred 時,預測結果將是一個機率分佈,我們需要找到機率最高的索引作為預測類別。

迴歸問題的解決

如果我們要解決一個迴歸問題,即預測每個輸入資料點的一個連續值,我們需要在輸出層增加一個單位,並且不使用任何啟用函式。這樣,模型就可以直接輸出連續值。

繪製損失和指標值

我們可以使用 fit() 函式傳回的 history 物件來繪製損失和指標(準確率)隨著 epochs 的變化。history 物件包含一個字典,其中的鍵包括 losssparse_categorical_accuracyval_lossval_sparse_categorical_accuracy。我們可以使用這些值來繪製訓練和驗證過程中的損失和準確率。

# 繪製模型準確率
plt.plot(history.history["sparse_categorical_accuracy"])
plt.plot(history.history["val_sparse_categorical_accuracy"])

這樣,我們就可以視覺化地看到模型在訓練和驗證過程中的表現,從而更好地理解模型的行為和效果。

深入模型評估與視覺化

在深度學習模型的訓練過程中,瞭解模型的效能和行為是非常重要的。這不僅有助於我們評估模型的好壞,也能夠提供寶貴的訊息,幫助我們對模型進行調整和最佳化。其中,模型的準確率和損失函式是兩個最為重要的指標。

準確率的重要性

準確率是評估模型效能的一個基本指標,它直接反映了模型對資料的預測能力。透過觀察訓練集和測試集上的準確率,可以對模型的泛化能力有所瞭解。如果模型在訓練集上的準確率很高,但在測試集上的準確率很低,可能表明模型過度擬合(overfitting),需要進行正則化或增加資料的多樣性。

損失函式的作用

損失函式(Loss Function)是用來衡量模型預測值與真實值之間的差異。它是模型最佳化的目標,最佳化演算法的任務就是最小化這個損失函式。觀察損失函式的變化,可以瞭解模型的學習過程和收斂情況。如果損失函式下降得太慢或停滯不前,可能需要調整學習率或最佳化演算法。

視覺化模型的效能

使用matplotlib這樣的函式庫,可以輕松地將模型的準確率和損失函式視覺化。這種視覺化不僅能夠直觀地展示模型的效能,也能夠幫助我們快速地發現可能存在的問題。

import matplotlib.pyplot as plt

# 假設history是一個包含模型訓練過程中準確率和損失函式值的物件
# Model Accuracy Plot
plt.plot(history.history["accuracy"])
plt.plot(history.history["val_accuracy"])
plt.title("Model Accuracy Plot")
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.legend(["Train", "Test"], loc="upper left")
plt.show()

# Model Loss Plot
plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.title("Model Loss Plot")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend(["Train", "Test"], loc="upper left")
plt.show()

圖表翻譯:

上述程式碼生成了兩個圖表,一個是模型的準確率隨著epoch的變化,另一個是模型的損失函式值隨著epoch的變化。透過這兩個圖表,可以清晰地看到模型在訓練過程中的效能變化。如果模型的準確率在訓練集上不斷提高,但在測試集上停滯不前,可能需要考慮過度擬合的問題。同樣,觀察損失函式的變化,可以判斷模型是否已經收斂或需要調整最佳化引數。

內容解密:

  • history.history["accuracy"]history.history["val_accuracy"]分別代表了模型在訓練集和驗證集上的準確率。
  • history.history["loss"]history.history["val_loss"]分別代表了模型在訓練集和驗證集上的損失函式值。
  • plt.plot()用於繪製圖表,plt.title()、plt.xlabel()、plt.ylabel()用於設定圖表的標題、x軸標籤和y軸標籤。
  • plt.legend()用於增加圖例,loc="upper left"指定了圖例的位置。
  • plt.show()用於顯示圖表。

使用TensorBoard進行模型視覺化

TensorBoard是一個強大的視覺化工具,能夠幫助我們瞭解模型的訓練過程和效能。下面是如何使用TensorBoard進行模型視覺化的步驟。

安裝TensorBoard

首先,需要安裝TensorBoard。可以使用以下命令安裝:

pip install tensorboard

載入TensorBoard

接下來,需要載入TensorBoard。可以使用以下命令載入:

%load_ext tensorboard

建立TensorBoard日誌

TensorBoard需要日誌來儲存結果以進行視覺化和測量。可以使用以下命令建立日誌:

%tensorboard --logdir ./logs

定義TensorBoard回呼函式

需要定義一個TensorBoard回呼函式來建立和儲存日誌。可以使用以下命令定義回呼函式:

tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=1)

訓練模型

可以使用以下命令訓練模型:

model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test), callbacks=[tensorboard_callback])

啟動TensorBoard

可以使用以下命令啟動TensorBoard:

%tensorboard --logdir ./logs

檢視視覺化結果

可以使用TensorBoard檢視視覺化結果,包括損失和準確率的變化、模型圖、資料集等。

從技術架構視角來看,本文深入淺出地介紹了使用 TensorFlow 和 Keras 建立、訓練和評估神經網路模型的各種方法,涵蓋了 Sequential API、Functional API 和 Model Subclassing 等多種模型建立方式,以及模型編譯、訓練、評估和預測的完整流程。同時,文章也詳細闡述了模型預測過程中的logit、啟用函式和softmax的應用,並提供了使用 matplotlib 和 TensorBoard 進行模型視覺化的實務技巧。然而,文章並未深入探討不同模型架構的優缺點及適用場景,例如卷積神經網路 (CNN) 和迴圈神經網路 (RNN) 等,也沒有提及模型最佳化過程中可能遇到的問題,例如過擬合和梯度消失等。對於初學者,建議由淺入深地學習不同模型架構,並關注模型訓練過程中的各項指標,才能更有效地構建和調校神經網路模型。展望未來,隨著深度學習技術的持續發展,更便捷高效的模型構建和訓練工具將不斷湧現,進一步降低深度學習的應用門檻。對於開發者而言,持續學習和掌握新的技術和工具至關重要。玄貓認為,深入理解模型架構和訓練原理,並結合實務經驗,才能在深度學習領域持續精進。