All Articles

Getting Started with TensorFlow.js | Deep Learning for JavaScript Hackers (Part 0)

TL;DR Learn about the basics of Machine Learning with TensorFlow.js - Tensors, basic visualizations and train a simple model that converts kilograms to pounds

So what is this thing TensorFlow.js?

TensorFlow.js is a library for developing and training ML models in JavaScript, and deploying in browser or on Node.js

For our purposes, TensorFlow.js will allow you to build Machine Learning models (especially Deep Neural Networks) that you can easily integrate with existing or new web apps. Think of your ReactJs, Vue, or Angular app enhanced with the power of Machine Learning models.

Run the complete source code for this tutorial right in your browser:

Tensors

Tensors are the main building blocks of TensorFlow. They are n-dimensional data containers. You can think of them as multidimensional arrays in languages like PHP, JavaScript, and others. What that means is that you can use tensors as a scalar, vector, and matrix values, since they are a generalization of those.

Each Tensor contains the following properties

  • rank - number of dimensions
  • shape - size of each dimension
  • dtype - data type of the values

Let’s start by creating your first Tensor:

import * as tf from "@tensorflow/tfjs";

const t = tf.tensor([1, 2, 3]);

Check it’s rank:

console.log(t.rank);
1

That confirms that your Tensor is 1-dimensional. Let’s check the shape:

console.log(t.shape);
[3]

1-dimensional with 3 values. But how can you see the contents of this thing?

console.log(t);
Tensor {kept: false, isDisposedInternal: false}

Not what you’ve expected, right? Tensors are custom objects and have a print() method that output their values:

t.print();
Tensor
    [1, 2, 3]

Of course, the values don’t have to be just numeric. You can create tensors of strings:

const st = tf.tensor(["hello", "world"]);

You can use tensor2d() to create matrices (or 2-dimensional tensors):

const t2d = tf.tensor2d([[1, 2, 3], [4, 5, 6]]);
console.log(t2d.shape);
[2, 3]

There are some utility methods that will be handy when we start developing models. Let’s start with ones():

tf.ones([3, 3]).print();
Tensor
    [[1, 1, 1],
     [1, 1, 1],
     [1, 1, 1]]

You can use reshape() to change the dimensionality of a Tensor:

tf.tensor([1, 2, 3, 4, 5, 6])
  .reshape([2, 3])
  .print();
Tensor
    [[1, 2, 3],
     [4, 5, 6]]

Tensor Math

You can use add() to do element-wise addition:

const a = tf.tensor([1, 2, 3]);
const b = tf.tensor([4, 5, 6]);

a.add(b).print();
Tensor
    [5, 7, 9]

and dot() to compute the dot product of two tensors:

const d1 = tf.tensor([[1, 2], [1, 2]]);
const d2 = tf.tensor([[3, 4], [3, 4]]);
d1.dot(d2).print();
Tensor
    [[9, 12],
     [9, 12]]

Finally, let’s have a look at transpose():

tf.tensor([[1, 2], [3, 4]])
  .transpose()
  .print();
Tensor
    [[1, 3],
     [2, 4]]

You can think of the transpose as a flipped-axis version of the input Tensor.

Have a look at all arithmetic operations

Visualization with tfjs-vis

tfjs-vis is a small library for in browser visualization intended for use with TensorFlow.js.

Let’s start by creating a simple bar chart. Here’s what our data looks like:

import * as tfvis from "@tensorflow/tfjs-vis";

const data = [
  { index: "Jill", value: 10 },
  { index: "Jane", value: 20 },
  { index: "Ivan", value: 30 }
];

Now, let’s render the data using barchart():

const container = document.getElementById("barchart-cont");
tfvis.render.barchart(container, data, {
  xLabel: "Customer",
  yLabel: "Payment",
  height: 350,
  fontSize: 16
});

Note that we provide a DOM element to the renderer as a container for our chart, which might be handy when you want to embed the charts in your apps.

Let’s have a look at histogram() and create a sample chart:

const data = Array(20)
  .fill(0)
  .map(x => Math.random() * 50);

const container = document.getElementById("histogram-cont");
tfvis.render.histogram(container, data, {
  maxBins: 5,
  height: 450,
  fontSize: 16
});

The API is pretty consistent for those 2 charts. Let’s do a scatter plot:

const apples = Array(14)
  .fill(0)
  .map(y => Math.random() * 100 + Math.random() * 50)
  .map((y, x) => ({ x: x, y: y }));

const oranges = Array(14)
  .fill(0)
  .map(y => Math.random() * 100 + Math.random() * 150)
  .map((y, x) => ({ x: x, y: y }));

const series = ["Apples", "Oranges"];

const data = { values: [apples, oranges], series };

const container = document.getElementById("scatter-cont");
tfvis.render.scatterplot(container, data, {
  xLabel: "day",
  yLabel: "sales",
  height: 450,
  zoomToFit: true,
  fontSize: 16
});

Have a look at the complete tfjs-vis API

Train your first model

Time to put what you’ve learned into practice and build your first model. To make it somewhat realistic, we’ll try to approximate the conversion of kgs to lbs, which is described by this function:

const kgToLbs = kg => kg * 2.2;

Let’s use it to prepare our data and create 2000 training examples:

const xs = tf.tensor(Array.from({ length: 2000 }, (x, i) => i));
const ys = tf.tensor(Array.from({ length: 2000 }, (x, i) => kgToLbs(i)));

We’re going to use a style of Machine Learning known as Supervised Learning. In a nutshell, we need to provide 2 arrays to our model - X is the training features (kilograms), and y is the training labels (corresponding pounds).

TensorFlow.js allows you to build layered models using sequential(). We’re going to go extremely simple: 1 layer, input size of 1, and 1 learning parameter:

const model = tf.sequential();

model.add(tf.layers.dense({ units: 1, inputShape: 1 }));

and teach it to convert kilograms to pounds:

model.compile({
  loss: "meanSquaredError",
  optimizer: "adam"
});

await model.fit(xs, ys, {
  epochs: 100,
  shuffle: true
});

Your model needs a metric to know how well is doing. In our case that is Mean Squared Error (MSE). Once you know how to measure the error, you need something to know how to minimize it using the data. In our case, that is the Adam optimizer.

Finally, we use the data to train our model for 100 epochs (number of times our model sees the data) and request to shuffle it. Why shuffle? We don’t want our model to learn the ordering of the data, just the relationship between different examples.

After the training is complete (might take some time) you can use your model to predict what amount of pounds correspond to 10 kg:

const lbs = model
  .predict(tf.tensor([10]))
  .asScalar()
  .dataSync();

console.log("10 kg to lbs: " + lbs);
10 kg to lbs: 22.481597900390625

Seems to be doing good, right?

Conclusion

Congratulation on finishing the first part of your journey to Machine Learning understanding. You learned about:

  • Tensors: n-dimensional data containers
  • tfjs-vis: visualization library integrated with TensorFlow.js
  • predict pounds from kilograms using a simple model

Run the complete source code for this tutorial right in your browser:

I hope that this tutorial just made you thirsty for knowledge about what is possible with Machine Learning and JavaScript. Ready for the next one?