機器學習中,一個 model 是一個帶有可訓練參數(shù)的函數(shù)。這個函數(shù)將輸入轉(zhuǎn)化為輸出。通俗的來說,這個函數(shù)表達了輸入和輸出之間的變換關(guān)系。我們通過在數(shù)據(jù)集上訓練模型來獲得最佳參數(shù)。訓練好的模型可以精確的將輸入數(shù)據(jù)轉(zhuǎn)換為我們想得到的輸出。
TensorFlow.js 有兩種創(chuàng)建機器學習的方法:
我們首先會用高層API:Layers API來建立模型。然后,我們會展示如何用Core API來搭建相同的模型。
Layers API有兩種方式創(chuàng)建模型:第一種是創(chuàng)建 sequential 模型,第二種是創(chuàng)建 functional 模型。下面兩段會分別解釋這兩種模型創(chuàng)建方式。
最常見的模型是 Sequential 模型。Sequential 模型將網(wǎng)絡(luò)的每一層簡單的疊在一起。您可以將需要的層按順序?qū)懺谝粋€列表里,然后將列表作為 sequential() 函數(shù)的輸入:
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'}));
注意:模型的第一層需要“輸入形狀”參數(shù)(inputShape)。不要在“輸入型狀”中包含 batch size(批次大小)。假設(shè)您要向模型輸入一個形狀為[B, 784]的張量(B 是任意batch size),您只需要將“輸入型狀”設(shè)為[784]。
您可以通過model.layers來使用模型中的每一層。例如,您可以用 model.inputLayers 和 model.outputLayers 來調(diào)用輸入層和輸出層。
我們也可以通過 tf.model() 來創(chuàng)建 LayersModel。tf.model() 和 tf.sequential() 的主要區(qū)別為,您可以用 tf.model() 來創(chuàng)建任何非閉環(huán)的計算圖。
以下是一段如何用 tf.model() API 建立和上文相同模型的列子:
// 用apply()方法創(chuàng)建任意計算圖
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(類似于張量,但不包含任何數(shù)值)
不同于 sequential model 使用 inputShape 來定義第一層的輸入,我們用 tf.input() 創(chuàng)建的 SymbolicTensor 作為第一層的輸入
如果您向 apply() 輸入一個數(shù)值張量,它會進行計算并返還一個數(shù)值張量:
const t = tf.tensor([-2, 1, 0, 5]);
const o = tf.layers.activation({activation: 'relu'}).apply(t);
o.print(); // [0, 1, 0, 5]
這個方式適用于單獨測試每一層并檢查它們的輸出。
和 sequential model 一樣,您可以通過 model.layers 來使用模型中的每一層。例如,您可以用 model.inputLayers 和 model.outputLayers 來調(diào)用輸入層和輸出層。
Sequential model和functional model都屬于 LayersModel類。使用 LayersModels 讓驗證更方便:它要求您定義輸入形狀,并用您定義的形狀來驗證您對模型的輸入。LayersModel 會自動計算模型中所有張量的形狀。知道張量的形狀后,模型就可以自動創(chuàng)建它所需要的參數(shù)。您也可以用形狀信息來判斷兩層相鄰的層是否相互兼容。
使用 model.summary() 可以顯示很多模型的重要信息,包括:
用前面定義的模型來做例子,我們可以在命令行中得到以下信息:
Layer (type) | Output shape | Param # |
dense_Dense1 (Dense) | [null,32] | 25120 |
dense_Dense2 (Dense) | [null,10] | 330 |
Total params: 25450 Trainable params: 25450 Non-trainable params: 0 |
注意:每一層的輸出形狀中都含有 null 值。模型的輸入形狀包含了批次大小,而批次大小是可以靈活更變的,所以批次的值在張量形狀中以 null 顯示。
相對于底端API而言,使用 LayersModel的另一個好處是方便存儲、加載模型。LayersModel 包含如下信息:
存儲和加載模型只需要一行代碼:
const saveResult = await model.save('localstorage://my-model-1');
const model = await tf.loadLayersModel('localstorage://my-model-1');
在這個例子中,模型被存儲在瀏覽器的本地存儲里。請訪問 model.save() 和 save and load 了解如何把模型保存在不同的媒介中(例如 file storage, IndexedDB, 觸發(fā)下載到瀏覽器等等)。
層是創(chuàng)建模型的基礎(chǔ)。如果您的模型需要定制化計算模塊,您可以寫一個自定義層并插入模型中。下面的例子是一個計算平方和的自定義層:
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
注意:如果您在模型中包含了自定義層,模型將不能序列化
本文開頭提到了兩種在 TensorFlow.js 中建立模型的方法。最常用的方式是使用 Layers API,因為它的模式是基于廣泛應(yīng)用的 Keras API(詳情見 best practices and reduces cognitive load)。Layers API 提供了大量方便的工具,例如權(quán)重初始化,模型序列化,訓練監(jiān)測,可遷移性和安全檢查。
當您遇到如下情況時,可能會需要使用 Core API:
用 Core API 寫的模型包含了一系列的函數(shù)。這些函數(shù)以一個或多個張量作為輸入,并輸出另一個張量。我們可以用 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 中,我們需要自己創(chuàng)建和初始化權(quán)重。每個權(quán)重都是一個 Variable,TensorFlow.js 會把 Variable 權(quán)重設(shè)為可訓練張量。您可以用 tf.variable() 創(chuàng)建 Variable 或把一個已存在的張量放到 Variable 中。
更多建議: