Introduction to Tensorflow.js
Tags: webdev, machinelearning, javascript, ai
Published: 2023-03-18 18:27:34

Tensorflow.js is a library that enables machine learning in web applications. It is a part of the [Tensorflow](https://www.tensorflow.org/) ecosystem, which is a deep learning framework written in C++ and provides a Python API.

Tensorflow.js was written from scratch to take advantage of web technologies. It runs on [WebGL](https://en.wikipedia.org/wiki/WebGL) and has an API that is similar to that of the actual Tensorflow library. It can also run on the server via [Node.js](https://nodejs.org/en). Additionally, Tensorflow has bindings for other languages such as Java, C++, and Rust.

## Why tensorflow.js?

Tensorflow.js has the unique advantage of running directly on the web among all the ML libraries. Traditionally, ML [models](https://dev.to/eteimz/introduction-to-machine-learning-237l#what-is-a-model) are trained and run directly on the server, and the client makes a request to the server when it is time to use the model. However, with Tensorflow.js, machine learning models can be run directly in the user's browser, eliminating the need for server requests and enabling real-time, interactive applications.

Tensorflow.js is not designed to train large models, but rather it is built for inference. Machine learning models trained in Python can be loaded into Tensorflow.js and used for inference in the user's browser.

Training machine learning models can require a large amount of computational resources. However, once a model has been trained, it can be reused multiple times for inference without requiring as much computation.

## Setting up Tensorflow.js

To use Tensorflow.js we can either use it via the script tag:

```js
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
```

or via npm:

```code
npm install @tensorflow/tfjs
```

or via yarn:

```code
yarn add @tensorflow/tfjs
```

The packages above were designed to be used in the web browser. To use Tensorflow.js on nodejs check out this [package](https://www.npmjs.com/package/@tensorflow/tfjs-node).

## The `Tensor` class

The main class in Tensorflow.js is the `Tensor`. It represents the [tensor](https://dev.to/eteimz/the-tensor-the-fundamental-data-structure-of-ml-3c99#what-is-a-tensor) data structure. The tensor data structure is [immutable](https://en.wikipedia.org/wiki/Immutable_object). Tensorflow.js contains various methods to work with and manipulate this data structure.

## Creating Tensors in tensorflow.js

Tensorflow.js provides several functions to help create tensors.

### tf.tensor

The `tf.tensor` function is a general function for creating tensors. It can create tensors of any shape and data type.

```javascript
tf.tensor(1); // creating a scalar 
tf.tensor([1,2,3,4]); // creating a vector
tf.tensor([[1,2],[3,4]]); // creating a matrix
```

### tf.scalar

The `tf.scalar` is a more specialized function. Its job is to create scalars([rank 0 tensors](https://dev.to/eteimz/the-tensor-the-fundamental-data-structure-of-ml-3c99#rank0-tensor)) and they can be of any type.

```javascript
tf.scalar(2)
```

It's encouraged to use this rather than `tf.tensor` when creating scalars. It helps with code readability.

### tf.tensor1d

The `tf.tensor1d` is used to create vectors([rank 1 tensors](https://dev.to/eteimz/the-tensor-the-fundamental-data-structure-of-ml-3c99#rank1-tensor)). Like `tf.scalar` it is more specialized but helps with code readability.

```javascript
tf.tensor1d([1,2,3,4]); // creating a vector
```

### tf.tensor2d

The `tf.tensor2d` is used to create matrices([rank 2 tensors](https://dev.to/eteimz/the-tensor-the-fundamental-data-structure-of-ml-3c99#rank2-tensor)).

```javascript
tf.tensor2d([[1,2],[3,4]]); // creating a matrix
```

### tf.tensor3d

The `tf.tensor3d` is used to create [rank 3 tensors](https://dev.to/eteimz/the-tensor-the-fundamental-data-structure-of-ml-3c99#rank3-tensor).

```javascript
tf.tensor3d([[[1], [2]], [[3], [4]]]); // creating a rank 3 tensor
```

Tensorflow.js has tensor creation functions up to rank 6. Check out their documentation [page](https://js.tensorflow.org/api/latest/#Tensors-Creation).

## tf.Variable

The `Tensor` data structure is immutable but mutability is essential to solve common problems. Tensorflow.js provides the `tf.Variable` class which is a mutable tensor.

The `tf.variable` function is used to create `tf.Variable` objects.

```javascript
const x = tf.variable(tf.tensor([1, 2, 3]));
```

In other to mutate them we use the `assign` method of the `tf.Variable` class.

```javascript
x.assign(tf.tensor([4, 5, 6]));
```

## Math operations

Basic mathematical operations like addition, subtraction, multiplication, and division can be performed on tensors.
Operators like `+`, `-`, `/`, and `*` don't work with tensors rather methods are used.

```js
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([5, 6, 7, 8]);

a.add(b) // tf.tensor1d([6, 8, 10, 12]) ✅
tf.add(a, b); // This also works: tf.tensor1d([6, 8, 10, 12]) ✅

a + b // This doesn't work ❌
```

To perform element-wise addition between tensors, they typically need to have the same shape. However, [broadcasting](https://numpy.org/doc/stable/user/basics.broadcasting.html) can be used to add together tensors of different shapes.

![broadcasting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr2bit3o6nks1vzngaua.png)

Broadcasting involves when a smaller tensor stretches to make its shape the same as the bigger tensor.

```js
const s = tf.scalar(2);
const a = tf.tensor1d([1, 2, 3]);

s.add(a); // tf.tensor1d([3, 4, 5]); 
```

In the code above `s` has smaller shape and it stretches to fit the shape of `a`. The result ends up having a shape equivalent to `a`.

```js
const s = tf.scalar(3);
const a = tf.tensor2d([[1, 2, 3, 4], [5, 6, 7, 8]]);

s.add(a); // tf.tensor2d([[4, 5, 6 , 7 ], [8, 9, 10, 11]]); 
```

The same rules of addition apply to other mathematical operations:

```js
// substraction
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([5, 6, 7, 8]);


b.sub(a) // tf.tensor1d([4, 4, 4, 4]) ✅
tf.sub(b, a); // This also works: tf.tensor1d([4, 4, 4, 4]) ✅

a - b // This doesn't work ❌

// substraction broadcasting
const s = tf.scalar(3);
const a = tf.tensor1d([1, 2, 3, 4]);

s.sub(a); // tf.tensor1d([2, 1, 0, -1])
```

```js
// multiplication
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([5, 6, 7, 8]);


b.mul(a) // tf.tensor1d([5, 12, 21, 32]) ✅
tf.mul(b, a); // This also works: tf.tensor1d([5, 12, 21, 32]) ✅

a * b // This doesn't work ❌

// multiplication broadcasting
const s = tf.scalar(3);
const a = tf.tensor1d([1, 2, 3, 4]);

s.mul(a); // tf.tensor1d([3, 6, 9, 12]);
```

```js
// division
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([5, 6, 7, 8]);


b.mul(a) // tf.tensor1d([5, 3, 2.3333335, 2]) ✅
tf.mul(b, a); // This also works: tf.tensor1d([5, 3, 2.3333335, 2]) ✅

a / b // This doesn't work ❌

// division broadcasting
const s = tf.scalar(3);
const a = tf.tensor1d([1, 2, 3, 4]);

s.div(a); // tf.tensor1d([3, 1.5, 1, 0.75]);
```

Tensorflow.js also supports other mathematical operations like [floordiv](https://js.tensorflow.org/api/latest/#floorDiv), [exponent](https://js.tensorflow.org/api/latest/#pow), and [modulus](https://js.tensorflow.org/api/latest/#mod) etc.

Javascript has an in-built [Math](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) object for working with [numbers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). Tensorflow.js provide equivalent methods but for tensors.

| Javascript  |Tensorflow.js|
| ----------- | ----------- |
| [Math.abs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/abs)      | [tf.abs](https://js.tensorflow.org/api/latest/#abs)  |
| [Math.acos](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acos)   | [tf.acos](https://js.tensorflow.org/api/latest/#acos)       |
| [Math.acosh](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/acosh)   | [tf.acosh](https://js.tensorflow.org/api/latest/#acosh)       |
| [Math.ceil](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil)   | [tf.ceil](https://js.tensorflow.org/api/latest/#ceil)       |
| [Math.cos](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cos)   | [tf.cos](https://js.tensorflow.org/api/latest/#cos)       |
| [Math.exp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/exp)   | [tf.exp](https://js.tensorflow.org/api/latest/#exp)       |
| [Math.floor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor)   | [tf.floor](https://js.tensorflow.org/api/latest/#floor)       |
| [Math.log](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log)   | [tf.log](https://js.tensorflow.org/api/latest/#log)       |
| [Math.sin](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sin)   | [tf.sin](https://js.tensorflow.org/api/latest/#sin)       |
| [Math.tan](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/tan)   | [tf.tan](https://js.tensorflow.org/api/latest/#tan)       |

Tensorflow.js has other operations that are not present in the Math object like the [relu](https://js.tensorflow.org/api/latest/#relu) and [sigmoid](https://js.tensorflow.org/api/latest/#sigmoid).

## Linear algebra

Linear algebra is a branch of mathematics that deals with the study of vectors and matrices and the transformations that can be performed on them. It is used heavily in the field of Machine Learning.Tensorflow.js has several methods for linear algebra.

### The dot product

The dot product also known as the scalar product is an operation that takes two vectors and produces a scalar.
It is represented mathematically as:

{% katex %}

\textbf{a} \cdot \textbf{b} = \sum_{i=1}^{n} {\textbf{a}_i\textbf{b}_i} = {\textbf{a}_1\textbf{b}_1} + {\textbf{a}_2\textbf{b}_2} + \cdots + {\textbf{a}_n\textbf{b}_n} 
{% endkatex %}

In Tensorflow.js, we have the `tf.dot` function for computing the dot product between two tensors.

```js
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([5, 6, 7, 8]);

tf.dot(a, b); // 70
```

`tf.Tensor` objects also have a `dot` method to perform dot products.

```js
a.dot(b);
```

### The Norm 

The norm also known as the **magnitude** is a mathematical concept used to measure the size or length of a vector. It is expressed mathematically as:

{% katex %}

|{x}|={\sqrt {x_{1}^{2}+x_{2}^{2}+\cdots +x_{n}^{2}}}

{% endkatex %}

Tensorflow.js provides the method `euclideanNorm` to calculate the norm of a tensor.

```js
const x = tf.tensor1d([1, 2, 3, 4]);

x.euclideanNorm() // 5.477225303649902
```

### Matrix multiplication

![Matrix multiplication](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5hur7r0dt98yev0bhib.png)

In linear algebra, there are several ways of performing multiplication each of them has its usage. One of them is matrix multiplication which defines how two matrices can be multiplied by each other.

In tensorflow.js, we can perform matrix multiplication using the `matMul` function.

```js
const a = tf.tensor2d([[1, 2],[3, 4]]);
const b = tf.tensor2d([[2, 4, 6],[8, 10, 12]]);

a.matMul(b); // [[18, 24, 30], [38, 52, 66]]
``` 

### Transpose

Transposing a matrix is an operation that involves reshaping it by swapping its rows with its columns.

![Transpose of a matrix](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e5qy5wa2i74684pgkvyo.png)

In tensorflow.js we have the `Transpose` function for performing transpose on a matrix.

```js
const a = tf.tensor2d([[1, 2, 3], [4, 5, 6]] );
tf.transpose(a); // result: [[1, 4],[2, 5],[3, 6]]
```

## Statistics

Tensorflow.js has several functions that can be used to perform statistical operations. One important concept in statistics is distribution, which determines how the data in a dataset is arranged. Tensorflow.js has functions for working with different types of distributions.

### Normal distribution

![Normal distribution](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gfko4gkjg8h7n4moybe.png)

The normal distribution is a probability distribution that models the way many natural phenomena are distributed. It is characterized by a bell-shaped curve, which indicates that the mean (average) value is more likely to occur than any other value. Tensorflow.js has the `mean` function for checking the mean of a tensor.

```js
const x = tf.tensor1d([1, 2, 3, 4]);

x.mean().print();  // result: 2.5
```

In addition to the mean, the concept of standard deviation is also important in statistics. It is a value that measures how spread out data points are relative to the mean. 

For example, in a room full of people, the average height is more likely to occur than either very tall or very short heights. Tensorflow.js has the `randomNormal` function that can be used to generate random values that are normally distributed.

```js
tf.randomNormal([2, 2]); // [[0.0635663, 1.2073363],[-1.681078, 0.1550148]]
```
The code above generates a tensor with normally distributed values of shape 2 by 2.

### Uniform distrubtion

In a uniform distribution, no values have a higher tendency of occurring. Rather all values are more likely to occur.
For example, flipping a coin, there's an equal chance of getting heads or tails. It is uniformly distributed, the same applies to a dice.

The `randomUniform` function of tensorflow.js can be used to generate random values that are uniformly distributed.

```js
tf.randomUniform([2, 2]); // [[0.7101336, 0.6085116],[0.5631702, 0.1648723]]
```

## Automatic differentiation

Automatic differentiation is one of the most important features of Tensorflow.js. Differentiation is the process of finding the rate of change of a function with respect to one of its variables. The derivative of a function describes how it changes as its input variable changes over time.

![Sigmoid function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/od604hmvr7yl9srstpi3.png)

For example, consider the graph above which plots two functions: the red one is the sigmoid function, while the green one is its derivative. The green function shows how the value of the sigmoid function changes over time, as its input variable changes.

![Square differentiation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npjgojalndazpvkcfb8h.png)

The graph plots the function {% katex inline %} x^2 {% endkatex %} in blue. We can easily calculate its derivative by using the [power rule](https://en.wikipedia.org/wiki/Power_rule): 

{% katex %} 

\frac{d}{dx}x^2 = nx^n-1

{% endkatex %}

Let's convert the equation above to JavaScript

```js
// Define the function y = x^n
function powerFunction(x, n) {
  return Math.pow(x, n);
}

// Define the derivative of y = x^n using the power rule
function powerRuleDerivative(x, n) {
  return n * Math.pow(x, n-1);
}

// Test the power rule for n = 2 and x = 3
let x = 3;
let n = 2;

let y = powerFunction(x, n);
console.log(y) // 9

// calculate its derivative 
let dydx = powerRuleDerivative(x, n);
console.log(dydx) // reusult: 6  
```

After using the formula above we find out the derivative is {% katex inline %} 2x {% endkatex %}. In other to calculate the derivative we needed to use the formula above. Tensorflow.js can calculate the derivative of any function but it doesn't use formulas rather it uses automatic differentiation.

The `tf.grad` is used to take the derivative of any function provided it returns a tensor.

```js

// f(x) = x ^ 2
const f = x => x.square();

// calculate the derivative of the function
const g = tf.grad(f);

const x = tf.tensor1d([3]);
g(x); // result 6
```

Automatic differentiation is a key component of the [backpropagation algorithm](https://en.wikipedia.org/wiki/Backpropagation) used to train [neural networks](https://en.wikipedia.org/wiki/Artificial_neural_network). It allows for the calculation of gradients efficiently without having to manually derive them using formulas.

<hr>

In this article, we got introduced to the Tensorflow.js library that brings machine learning to the web. We explored its APIs and discovered it is capable of all sorts of computations.

Tensors are great but ML practitioners rarely work with them they are a bit low level rather most ML practitioners work on a higher level. In the next article, we will build our first ML [model](https://dev.to/eteimz/introduction-to-machine-learning-237l#what-is-a-model) using Tensorflow.js.

## Useful resources
- Check out [Coding train](https://www.youtube.com/@TheCodingTrain) video on Tensorflow.js operations [here](https://www.youtube.com/watch?v=KzWF_wzx9PU).
- [Tensorflow.js API docs](https://js.tensorflow.org/api/latest/).
- Check out this [youtube playlist](https://www.youtube.com/watch?v=kjBOesZCoqc&list=PL2QY0xcsWhz6ghPUixeNQm47xapSKw4SM) on linear algebra.
- Check out this [youtube video](https://www.youtube.com/watch?v=9vKqVkMQHKk) on differentiation.
- To learn more about distribution watch [this](https://www.youtube.com/watch?v=bPFNxD3Yg6U)
- To learn more about the normal distribution watch [this](https://www.youtube.com/watch?v=rBjft49MAO8)