In this article, we are going to discuss tensors and their operation.
Introduction: TensorFlow.js is a library 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 are very similar to multidimensional arrays.
A tf.Tensor also contains the following properties:
- rank: Defines how many dimensions the tensor contains.
- shape: Which defines the size of each dimension of the data.
- dtype: Which defines the data type of the tensor.
Note: We will use the term “dimension” interchangeably with the rank. Sometimes in machine learning,
“dimensionally” of a tensor can also be referred to as the size of a particular dimension (e.g a matrix of shape[10, 5] is a rank-2 tensor or a 2-dimensional tensor. The dimensionality of the first dimension is 10. This can be confusing, but we put this note here because you will likely come across these dual uses of the term).
A tf.Tensor can be created from an array with the tf.Tensor() method.
JavaScript
// 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(); |
Output:
shape: 2,2 Tensor [[1, 2], [3, 4]] shape: 2,2 Tensor [[1, 2], [3, 4]]
By default, tf.Tensor will have a float32 dtype. tf.Tensor can also be created with bool, int32, complex64, and using dtypes:
JavaScript
const a = tf.tensor([[1,2], [3,4]], [2,2], 'int32' ); console.log( 'shape:' , a.shape); console.log( 'dtype' , a.dtype); a.print(); |
Output:
shape: 2, 2 dtype int32 Tensor [[1, 2], [3, 4]]
TensorFlow.js also provides a set of convenient methods for creating random tensors, tensors filled with a particular value, tensors from HTMLImageElement s, and many more.
Changing the shape of a Tensor: The number of elements in a tf.Tensor is the product of the size in its shape. Since oftentimes there can be multiple shapes of the same size, it’s often useful to be able to reshape a tf.Tensor to another shape of the same size. This can be achieved with the reshape() method.
JavaScript
const a = tf.tensor([[1,2], [3,4]]); console.log( 'a shape:' , a.shape); a.print(); const b = a.redshape([4,1]); console.log( 'b shape:' , b.shape); b.print(); |
Output:
a=array([1, 2, 3, 4])
Getting values from a Tensor: You can also get the values form a tf.Tensor using the Tensor.array() or Tensor.data() methods:
JavaScript
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)); |
Output:
Tensor [1, 2, 3, 4]
We also provide synchronous versions of this method which are simpler to use but will cause performance issues in your application. You should always prefer the synchronous methods in production applications.
JavaScript
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()); |
Output:
a = [1, 2, 3, 4]
Operations: While tensors allow you to store data, operations (ops) allow you to manipulate that data. TensorFlow.js provides a wide variety of ops suitable for linear algebra and machine learning that can be performed on tensors.
Example: Computing x^2 of al element in a tf.Tensor:
JavaScript
const x = tf.tensor([1,2,3,4]); // Equivalent to tf.square(x) const y = x.square(); y.print(); |
Output for the above code: y=x([1, 4, 9, 16 ] )
Example: Adding elements of two tf.Tensor element-wise:
JavaScript
const a = tf.tensor([1,2,3,4]); const b = tf.tensor([10,20,30,40]); // Equivalent to tf.add(a,b) const y = a.add(b); y.print(); |
Output:
numpy = array([ 11, 22, 33, 44 ])
Because tensors are immutable, these ops do not change their values. Instead, ops return always return new tf.Tensor s.
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():
It is very common to chain operations together in an application. Holding a reference to all of the intermediate variables to dispose of 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:
JavaScript
const a = tf.tensor([[1,2],[3,4]]); const y = tf.tidy(() => { const result = a.square().log().neg(); return result; }); |
Output:
In this example, the result of square() and log() will automatically be disposed of. The result of neg() will not be disclosed as it is the return value of the tf.tidy().
You can also get the number of Tensors tracked by TensorFlow.js:
JavaScript
console.log(tf.memory()); |
Output:
It will display a message on the console while debugging. e.g console.log("Hello World"); Now if we run this using -- node helloworld.js It will print--- Hello World
The object printed by tf.memory() will contain information about how much memory is currently allocated.