張量與運算

TensorFlow.js 是一個使用 JavaScript 中的張量定義及執行運算的架構。「張量」是向量和矩陣推廣至更高維度的概念。

張量

TensorFlow.js 中的核心資料單位是 tf.Tensor:一組值,塑造成一或多維陣列。tf.Tensor 與多維陣列非常相似。

tf.Tensor 也包含下列屬性

  • rank:定義張量包含的維度數量
  • shape:定義資料各維度的大小
  • dtype:定義張量的資料類型。

可以使用 tf.tensor() 方法從陣列建立 tf.Tensor

// Create a rank-2 tensor (matrix) matrix tensor from a multidimensional array.
const a = tf.tensor([[1, 2], [3, 4]]);
console.log('shape:', a.shape);
a.print();

// Or you can create a tensor from a flat array and specify a shape.
const shape = [2, 2];
const b = tf.tensor([1, 2, 3, 4], shape);
console.log('shape:', b.shape);
b.print();

預設情況下,tf.Tensordtype 會是 float32tf.Tensor 也可以使用 bool、int32、complex64 和字串 dtype 建立

const a = tf.tensor([[1, 2], [3, 4]], [2, 2], 'int32');
console.log('shape:', a.shape);
console.log('dtype', a.dtype);
a.print();

TensorFlow.js 也提供一組便利方法,可用於建立隨機張量、填滿特定值的張量、來自 HTMLImageElement 的張量等等,您可以在這裡找到更多資訊。

變更張量的形狀

tf.Tensor 中的元素數量是其形狀中大小的乘積。由於通常會有許多大小相同的形狀,因此通常可以將 tf.Tensor 重新塑造成另一個大小相同的形狀會很有用。這可以使用 reshape() 方法達成

const a = tf.tensor([[1, 2], [3, 4]]);
console.log('a shape:', a.shape);
a.print();

const b = a.reshape([4, 1]);
console.log('b shape:', b.shape);
b.print();

從張量取得值

您也可以使用 Tensor.array()Tensor.data() 方法從 tf.Tensor 取得值

 const a = tf.tensor([[1, 2], [3, 4]]);
 // Returns the multi dimensional array of values.
 a.array().then(array => console.log(array));
 // Returns the flattened data that backs the tensor.
 a.data().then(data => console.log(data));

我們也提供這些方法的同步版本,這些版本更易於使用,但會在您的應用程式中造成效能問題。在生產應用程式中,您應一律偏好使用非同步方法。

const a = tf.tensor([[1, 2], [3, 4]]);
// Returns the multi dimensional array of values.
console.log(a.arraySync());
// Returns the flattened data that backs the tensor.
console.log(a.dataSync());

運算

張量可讓您儲存資料,而運算 (op) 可讓您操縱該資料。TensorFlow.js 也提供各種適用於線性代數和機器學習的運算,這些運算可在張量上執行。

範例:計算 tf.Tensor 中所有元素的 x2

const x = tf.tensor([1, 2, 3, 4]);
const y = x.square();  // equivalent to tf.square(x)
y.print();

範例:逐元素相加兩個 tf.Tensor 的元素

const a = tf.tensor([1, 2, 3, 4]);
const b = tf.tensor([10, 20, 30, 40]);
const y = a.add(b);  // equivalent to tf.add(a, b)
y.print();

由於張量是不可變的,因此這些運算不會變更其值。相反地,運算一律會傳回新的 tf.Tensor

您可以在這裡找到 TensorFlow.js 支援的運算清單。

記憶體

使用 WebGL 後端時,必須明確管理 tf.Tensor 記憶體 (僅讓 tf.Tensor 超出範圍不足以釋放其記憶體)。

若要銷毀 tf.Tensor 的記憶體,您可以使用 dispose() 方法或 tf.dispose()

const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose(); // Equivalent to tf.dispose(a)

在應用程式中將多個運算串連在一起是很常見的做法。保留所有中繼變數的參照以處置它們可能會降低程式碼可讀性。為了解決這個問題,TensorFlow.js 提供了 tf.tidy() 方法,此方法會清除函式執行後未傳回的所有 tf.Tensor,這類似於函式執行時清除區域變數的方式

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});

在此範例中,square()log() 的結果將自動處置。neg() 的結果將不會處置,因為它是 tf.tidy() 的傳回值。

您也可以取得 TensorFlow.js 追蹤的張量數量

console.log(tf.memory());

tf.memory() 列印的物件將包含目前配置多少記憶體的相關資訊。您可以在這裡找到更多資訊。