Introduction to TensorFlow.js and Core Concepts




TensorFlow is one of the popular libraries for developing machine learning and deep neural network models in various domains which is used within Google for research and product development. TensorFlow.js, web version of Tensorflow, is an open-source library that we can use to define, train, and run machine learning models entirely in the browser, using Javascript and a high-level layers API. This tutorial is an introduction to TensorFlow.js and its Core Concepts.

Contents

What is TensorFlow.js?

In-Browser Machine Learning

ML running in the browser means that our program runs on a webpage without need to install any libraries or drivers. TensorFlow.js automatically supports WebGL, and with GPU acceleration, our code can work better behind the scene.

User may also open the webpage from a mobile device, it gives us advantages:
– ML model can take advantage of mobile sensor data
– low-latency data inference and privacy preserving because all data stays on the client

General uses

Import an existing, pre-trained model for inference
Using model converters, we can convert an existing TensorFlow or Keras model (trained offline) into TensorFlow.js format, then load it into the browser for inference.

Re-train an imported model
We can augment an existing model trained offline using sensor data connected to the browser, or other client-side data. This way helps to train an accurate model quickly, when we have only a small amount of data.

Author ML models directly in browser
We can also use TensorFlow.js to define, build, train, and run models entirely from scratch in the browser using the low-level JavaScript linear algebra library or the high-level layers API.

TensorFlow.js API

tensorflow.js-api-diagram

Tensorflow.js has four layers:
– WebGL API for GPU-supported numerical operations
– Web browser for user interactions
– Low-level Core API (former deeplearn.js library) for hardware-accelerated linear algebra operations and automatic differentiation (Eager)
– Higher-level Layers API for building machine-learning models on top of Core which is modelled after Keras and implements similar functionality.

Tensorflow.js API allows to import Python trained models with Keras or TensorFlow SavedModel and use it for inference or transfer learning in the browser.

TensorFlow.js Core Concepts

Tensor

Tensor is the basic unit and a fundamental data structure in TensorFlow.
A tensor is an n-dimensional collection of numerical values, identified by rank, shape, and type.

Rank is the number of dimensions of a tensor.
Shape is the list denoting the size in each dimension.
For example:
+ a scalar is a tensor of rank 0 and thus has a shape of [1]
+ a vector or a one-dimensional array is a tensor of rank 1 and has a shape of [columns] or [rows] or [numberItems]
+ a matrix or a two-dimensional array is a tensor of rank 2 and has a shape of [rows, columns]
+ a three-dimensional array is a tensor of rank 3
+ an n-dimensional array is a tensor of rank n

Type: at the time of writing this tutorial, TensorFlow.js has 3 data types: float32, int32, bool.

Create Tensor

Common Case

tf.tensor (values, shape?, dtype?)

tf.scalar (value, dtype?)

tf.tensor1d (values, dtype?)

tf.tensor2d (values, shape?, dtype?)

tf.tensor3d (values, shape?, dtype?)

Elements with the same values

tf.zeros (shape, dtype?): all elements set to 0.
tf.zerosLike (x): all elements set to 0 with the same shape as the given tensor.

tf.ones (shape, dtype?): all elements set to 1.
tf.onesLike (x): all elements set to 1 with the same shape as the given tensor.

tf.fill (shape, value, dtype?): all elements set to a scalar value.

Elements from sequences

tf.linspace (start, stop, num): returns Tensor, its elements are evenly spaced sequence of numbers.

tf.range (start, stop, step?, dtype?): returns tf.Tensor1D filled with the numbers in the range(start,stop) provided.

Elements with random distribution

tf.randomNormal (shape, mean?, stdDev?, dtype?, seed?): returns Tensor with values sampled from a normal distribution.
+ shape (number[]): output tensor shape
+ mean (number)
+ stdDev (number): standard deviation
+ dtype (‘float32’|’int32’)
+ seed (number): seed for the random number generator

tf.truncatedNormal (shape, mean?, stdDev?, dtype?, seed?): returns Tensor with values sampled from a truncated normal distribution.
tf.randomUniform (shape, minval?, maxval?, dtype?): returns Tensor with values sampled from a uniform distribution.

Variable

While using TensorFlow to build and train models, we need to hold values in a memory location that can be updated/modified during the execution of the program. It is identified by variable in TensorFlow.

We can assign a new tensor to an existing variable with assign() method.

Operations

TensorFlow.js provides operations that can be performed on tensors.
These operations do not change the tensors’ values but return new tensors.

Arithmetic operations

tf.add (a, b), tf.sub (a, b), tf.mul (a, b), tf.div (a, b)
tf.mod (a, b)
tf.pow (base, exp)

tf.maximum (a, b), tf.minimum (a, b)

tf.squaredDifference (a, b): returns (a – b) * (a – b) element-wise.

Basic math operations

tf.reciprocal (x)
tf.square (x)
tf.sqrt (x)
tf.rsqrt (x): reciprocal of square root
tf.exp (x)
tf.log (x)

tf.abs (x)
tf.sign (x)
tf.neg (x): (-1 * x)
tf.round (x)
tf.floor (x)
tf.ceil (x)

tf.sigmoid, tf.logSigmoid
tf.elu (exponential linear), tf.selu (x) (scaled exponential linear)
tf.relu (x), tf.leakyRelu (x, alpha?), tf.prelu (x, alpha) (leaky rectified linear)
tf.erf (Gauss error function)

tf.cos, tf.acos, tf.cosh, tf.acosh
tf.sin, tf.asin, tf.sinh, tf.asinh
tf.tan, tf.atan, tf.tanh, tf.atanh

Matrix operations
tf.matMul

tf.matMul (a, b, transposeA?, transposeB?): dot product of two matrices (A * B)
If transpose param is true, the matrx is transposed before multiplication.

tf.outerProduct

tf.outerProduct (v1, v2)

tf.transpose

tf.transpose (x, perm?): permutes the dimensions according to perm.
The returned Tensor’s dimension i will correspond to the input dimension perm[i].
If perm is not given, it is set to [n-1...0], where n is the rank of the input Tensor.

For example: Input Tensor has shape=[1,3,4].
+ not giving perm: perm=[2,1,0] => returned Tensor has shape=[4,3,1]
+ perm=[0,2,1] => returned Tensor has shape=[1,4,3]
+ perm=[1,2,0] => returned Tensor has shape=[3,4,1]

tf.norm

tf.norm (x, ord?, axis?, keepDims?): computes several different vector norms (1-norm, Euclidean or 2-norm, inf-norm, p-norm with p > 0) and matrix norms (Frobenius, 1-norm, inf-norm).

ord norm (matrix) norm (vector)
‘euclidean’ Frobenius norm 2-norm
‘fro’ Frobenius norm
Infinity max(sum(abs(x), axis=1)) max(abs(x))
-Infinity min(sum(abs(x), axis=1)) min(abs(x))
1 max(sum(abs(x), axis=0)) sum(abs(x))
2 sum(abs(x)^2)^1/2

axis (number|number[]):
+ if axis is null (default): input is considered a vector, norm is computed over the entire set of values in the Tensor.
+ if axis is an integer: input is considered a batch of vectors, and axis determines the axis in x over which to compute vector norms.
+ if axis is a 2-tuple of integer: input is considered a batch of matrices, and axis determines the axes in NDArray over which to compute a matrix norm.

keepDims (boolean): if true, norm has the same dimensionality as the input.

– Example 1:

– Example 2:

– Example 3:

Logical operations

tf.equal (a, b)
tf.greater (a, b)
tf.greaterEqual (a, b)
tf.less (a, b)
tf.lessEqual (a, b)

tf.logicalAnd (a, b)
tf.logicalNot (a, b)
tf.logicalOr (a, b)
tf.logicalXor (a, b)

tf.where (condition, a, b): returns Tensor which each element is selected from a if condition is true, b if condition is false.

Models and Layers

Model

A model is just like a function in programming concept: We give it some input, it will produce some desired output.
There are two ways to create a model in TensorFlow.js.

Use operations directly

Use high-level API

We can think of model as a primary abstraction that consists of layers.
It can be trained, evaluated, and used for prediction.

There are two function for creating models:
tf.sequential(): returns a tf.Sequential (that extends tf.Model) object, use when outputs of one layer are the inputs to the next layer (supports only a linear stack of layers).
tf.model(): creates a tf.Model that supports an arbitrary graph (without cycles) of layers.

In TensorFlow.js, tf.Model is the basic unit of training, inference and evaluation.
It has some useful methods:
compile(): configures and prepares the model for training and evaluation with optimizer, loss, and/or metrics.
evaluate(): returns the loss value & metrics (that are specified during compile()) values for the model in test mode.
predict(), predictOnBatch(): generates output predictions for the input/a single batch of samples.
fit(): trains the model for a fixed number of epochs (iterations on a dataset).
getLayer(): retrieves a layer by its name or index.

For example, we construct a convolutional image classifier model using tf.sequential:

Layer

We can see that our model above includes a sequence of 6 layers:
– two-dimensional convolutional layer: slide a filter window over an image to learn transformations
– max pooling layer: downsample the result
– second convolutional layer, followed by another pooling layer: repeat layer structure
– flatten layer: output of the previous layer becomes a vector
– dense layer (aka fully connected layer): perform the final classification

So, what is layer?

They are the primary building block for constructing a model.
Each layer gets input, performs some computation, generates output. It automatically creates and initializes the various internal variables/weights for function.

There are many different types of layers available in TensorFlow.js:

Basic

tf.layers.activation
tf.layers.dense
tf.layers.dropout
tf.layers.embedding
tf.layers.flatten
tf.layers.repeatVector
tf.layers.reshape

Convolutional

tf.layers.conv1d
tf.layers.conv2d
tf.layers.conv2dTranspose
tf.layers.depthwiseConv2d
tf.layers.separableConv2d

Merge

tf.layers.add
tf.layers.average
tf.layers.concatenate
tf.layers.maximum
tf.layers.minimum
tf.layers.multiply

Normalization

tf.layers.batchNormalization

Pooling

tf.layers.averagePooling1d
tf.layers.averagePooling2d
tf.layers.globalAveragePooling1d
tf.layers.globalAveragePooling2d
tf.layers.globalMaxPooling1d
tf.layers.globalMaxPooling2d
tf.layers.maxPooling1d
tf.layers.maxPooling2d

Recurrent

tf.layers.gru
tf.layers.gruCell
tf.layers.lstm
tf.layers.lstmCell
tf.layers.rnn
tf.layers.simpleRNN
tf.layers.simpleRNNCell
tf.layers.stackedRNNCells

Advanced Activation

tf.layers.elu
tf.layers.leakyReLU
tf.layers.softmax
tf.layers.thresholdedReLU

For more details, please visit: TensorFlow.js Layers API.

Training

TensorFlow.js also provides API to perform training and compute gradients eagerly.
We provide a function that is a combination of operations and the API automatically differentiate that function’s output with respect to its inputs.

Gradients

tf.grad
tf.grads
tf.customGrad
tf.valueAndGrad
tf.valueAndGrads
tf.variableGrads

For example, gradients of f(a,b):

Optimizers

tf.train.sgd
tf.train.momentum
tf.train.adagrad
tf.train.adadelta
tf.train.adam
tf.train.adamax
tf.train.rmsprop

For example, construct an Optimizer with Stochastic Gradient Descent:

Result:

For more details, please visit: TensorFlow.js Training API

Memory Management

dispose

Calling dispose() on a tensor or variable will purge it and free up its GPU memory:

tf.memory

This method returns memory info object at the current time which has following properties:
numBytes: number of bytes allocated (undisposed).
numTensors: number of unique tensors allocated.
numDataBuffers: number of unique data buffers allocated (undisposed).For example, tensor that is created from myTensor.reshape(newShape) shares the same data buffer with myTensor, code>numDataBuffers is alwyas the numTensors.

Result:

tf.tidy

– executes the provided function f
– after it is executed, purges all intermediate tensors and free up their GPU memory allocated by f (except returned value by f)

*Notes:
f should be synchronous and also not return a Promise.
– should keep code that updates the UI or makes remote requests outside of tf.tidy().
tf.tidy() will not clean up variables. We can call dispose on them manually.

For example, a, b, and one will be cleaned up when the tidy ends.

Result:

tf.keep

This method keeps a tensor generated inside tf.tidy() from being disposed automatically.

Result: