模型和層

在機器學習中,「模型」是一個具有「可學習參數的函式,可將輸入對應至輸出。最佳參數是透過在資料上訓練模型而取得。訓練有素的模型將提供從輸入到所需輸出的精確對應。

在 TensorFlow.js 中,有兩種建立機器學習模型的方法

  1. 使用 Layers API,您可以使用「」來建構模型。
  2. 使用 Core API 與較低層級的運算,例如 tf.matMul()tf.add() 等。

首先,我們將研究 Layers API,這是用於建構模型的較高層級 API。然後,我們將示範如何使用 Core API 建構相同的模型。

使用 Layers API 建立模型

有兩種使用 Layers API 建立模型的方法:「循序」模型和「函式」模型。接下來的兩節將更仔細地探討每種模型類型。

循序模型

最常見的模型類型是 Sequential 模型,它是層的線性堆疊。您可以將層的清單傳遞至 sequential() 函式,藉此建立 Sequential 模型

const model = tf.sequential({
 layers: [
   tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
   tf.layers.dense({units: 10, activation: 'softmax'}),
 ]
});

或透過 add() 方法

const model = tf.sequential();
model.add(tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}));
model.add(tf.layers.dense({units: 10, activation: 'softmax'}));

重要事項:模型中的第一層需要 inputShape。提供 inputShape 時,請務必排除批次大小。例如,如果您計劃將形狀為 [B, 784] 的張量饋送至模型,其中 B 可以是任何批次大小,則在建立模型時,請將 inputShape 指定為 [784]

您可以透過 model.layers 存取模型的層,更具體而言,可以透過 model.inputLayersmodel.outputLayers 存取。

函式模型

建立 LayersModel 的另一種方法是透過 tf.model() 函式。tf.model()tf.sequential() 之間的主要區別在於,只要層沒有週期,tf.model() 就允許您建立層的任意圖形。

以下程式碼片段使用 tf.model() API 定義與上述相同的模型

// Create an arbitrary graph of layers, by connecting them
// via the apply() method.
const input = tf.input({shape: [784]});
const dense1 = tf.layers.dense({units: 32, activation: 'relu'}).apply(input);
const dense2 = tf.layers.dense({units: 10, activation: 'softmax'}).apply(dense1);
const model = tf.model({inputs: input, outputs: dense2});

我們在每個層上呼叫 apply(),以便將其連線到另一個層的輸出。apply() 在此案例中的結果是 SymbolicTensor,其作用類似於 Tensor,但沒有任何具體值。

請注意,與循序模型不同,我們透過 tf.input() 建立 SymbolicTensor,而不是為第一層提供 inputShape

如果您將具體的 Tensor 傳遞至 apply(),則 apply() 也可以提供您具體的 Tensor

const t = tf.tensor([-2, 1, 0, 5]);
const o = tf.layers.activation({activation: 'relu'}).apply(t);
o.print(); // [0, 1, 0, 5]

當在隔離狀態下測試層並查看其輸出時,這會很有用。

就像在循序模型中一樣,您可以透過 model.layers 存取模型的層,更具體而言,可以透過 model.inputLayersmodel.outputLayers 存取。

驗證

循序模型和函式模型都是 LayersModel 類別的執行個體。使用 LayersModel 的主要好處之一是驗證:它會強制您指定輸入形狀,並在稍後使用它來驗證您的輸入。LayersModel 也會在資料流經層時執行自動形狀推斷。預先知道形狀可讓模型自動建立其參數,並告訴您兩個連續層是否彼此不相容。

模型摘要

呼叫 model.summary() 以列印模型的實用摘要,其中包括

  • 模型中所有層的名稱和類型。
  • 每個層的輸出形狀。
  • 每個層的權重參數數量。
  • 如果模型具有一般拓撲 (如下所述),則每個層接收的輸入
  • 模型的可訓練和非可訓練參數總數。

對於我們在上面定義的模型,我們在主控台上取得下列輸出

層 (類型) 輸出形狀 Param #
dense_Dense1 (Dense) [null,32] 25120
dense_Dense2 (Dense) [null,10] 330
總參數:25450
可訓練參數:25450
非可訓練參數:0

請注意層輸出形狀中的 null 值:提醒您模型預期輸入具有批次大小作為最外層維度,在此案例中,由於 null 值,批次大小可以是彈性的。

序列化

與較低層級 API 相比,使用 LayersModel 的主要好處之一是能夠儲存和載入模型。LayersModel 知道

  • 模型的架構,讓您能夠重新建立模型。
  • 模型的權重
  • 訓練組態 (損失、最佳化工具、指標)。
  • 最佳化工具的狀態,讓您能夠繼續訓練。

儲存或載入模型只需要 1 行程式碼

const saveResult = await model.save('localstorage://my-model-1');
const model = await tf.loadLayersModel('localstorage://my-model-1');

上述範例會將模型儲存至瀏覽器中的本機儲存空間。請參閱 model.save() 文件儲存和載入指南,以瞭解如何儲存至不同的媒介 (例如檔案儲存空間、IndexedDB、觸發瀏覽器下載等)。

自訂層

層是模型的建構區塊。如果您的模型正在執行自訂計算,您可以定義自訂層,使其與其餘層良好互動。以下我們定義一個自訂層,計算平方和

class SquaredSumLayer extends tf.layers.Layer {
 constructor() {
   super({});
 }
 // In this case, the output is a scalar.
 computeOutputShape(inputShape) { return []; }

 // call() is where we do the computation.
 call(input, kwargs) { return input.square().sum();}

 // Every layer needs a unique name.
 getClassName() { return 'SquaredSum'; }
}

為了進行測試,我們可以使用具體張量呼叫 apply() 方法

const t = tf.tensor([-2, 1, 0, 5]);
const o = new SquaredSumLayer().apply(t);
o.print(); // prints 30

重要事項:如果您新增自訂層,您將失去序列化模型的能力。

使用 Core API 建立模型

在本指南的開頭,我們提到在 TensorFlow.js 中有兩種建立機器學習模型的方法。

一般經驗法則是始終先嘗試使用 Layers API,因為它是以廣泛採用的 Keras API 為模型,後者遵循最佳實務並降低認知負荷。Layers API 也提供各種現成的解決方案,例如權重初始化、模型序列化、監控訓練、可攜性和安全檢查。

在下列情況下,您可能會想要使用 Core API

  • 您需要最大的彈性或控制權。
  • 您不需要序列化,或可以實作自己的序列化邏輯。

Core API 中的模型只是接受一個或多個 Tensors 並傳回 Tensor 的函式。使用 Core API 寫入的相同模型如下所示

// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
  return x.matMul(w1).add(b1).relu().matMul(w2).add(b2).softmax();
}

請注意,在 Core API 中,我們負責建立和初始化模型的權重。每個權重都由 Variable 支援,這向 TensorFlow.js 發出訊號,表示這些張量是可學習的。您可以使用 tf.variable() 並傳入現有的 Tensor 來建立 Variable

在本指南中,您已熟悉使用 Layers 和 Core API 建立模型的不同方法。接下來,請參閱訓練模型指南,以瞭解如何訓練模型。