TensorFlow.js is a framework to define and run computations using tensors in JavaScript. A tensor is a generalization of vectors and matrices to higher dimensions.
Tensors
The central unit of data in TensorFlow.js is the tf.Tensor
: a set of values shaped into an array of one or more dimensions. tf.Tensor
s are very similar to multidimensional arrays.
A tf.Tensor
also contains the following properties:
rank
: defines how many dimensions the tensor containsshape
: which defines the size of each dimension of the datadtype
: which defines the data type of the tensor.
A tf.Tensor
can be created from an array with the tf.tensor()
method:
// 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();
By default, tf.Tensor
s will have a float32
dtype.
tf.Tensor
s can also be created with bool, int32, complex64, and string dtypes:
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 also provides a set of convenience methods for creating random tensors, tensors filled with a particular value, tensors from HTMLImageElement
s, and many more which you can find here.
Changing the shape of a Tensor
The number of elements in a tf.Tensor
is the product of the sizes in its shape. Since often times there can be multiple shapes with the same size, it's often useful to be able to reshape a tf.Tensor
to another shape with the same size. This can be achieved with the reshape()
method:
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();
Getting values from a Tensor
You can also get the values from a tf.Tensor
using the Tensor.array()
or Tensor.data()
methods:
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));
We also provide synchronous versions of these methods which are simpler to use, but will cause performance issues in your application. You should always prefer the asynchronous methods in production applications.
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());
Operations
While tensors allow you to store data, operations (ops) allow you to manipulate that data. TensorFlow.js also provides a wide variety of ops suitable for linear algebra and machine learning that can be performed on tensors.
Example: computing x2 of all elements in a tf.Tensor
:
const x = tf.tensor([1, 2, 3, 4]);
const y = x.square(); // equivalent to tf.square(x)
y.print();
Example: adding elements of two tf.Tensor
s element-wise:
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();
Because tensors are immutable, these ops do not change their values. Instead, ops return always return new tf.Tensor
s.
You can find a list of the operations TensorFlow.js supports here.
Memory
When using the WebGL backend, tf.Tensor
memory must be managed explicitly (it is not sufficient to let a tf.Tensor
go out of scope for its memory to be released).
To destroy the memory of a tf.Tensor, you can use the dispose()
method or tf.dispose()
:
const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose(); // Equivalent to tf.dispose(a)
It is very common to chain multiple operations together in an application. Holding a reference to all of the intermediate variables to dispose them can reduce code readability. To solve this problem, TensorFlow.js provides a tf.tidy()
method which cleans up all tf.Tensor
s that are not returned by a function after executing it, similar to the way local variables are cleaned up when a function is executed:
const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
const result = a.square().log().neg();
return result;
});
In this example, the result of square()
and log()
will automatically be disposed. The result of neg()
will not be disposed as it is the return value of the tf.tidy().
You can also get the number of Tensors tracked by TensorFlow.js:
console.log(tf.memory());
The object printed by tf.memory()
will contain information about how much memory is currently allocated. You can find more information here.