<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h1>TensorFlow JavaScript</h1> <h3>Creating a tensor with a shape:</h3>
<div id="demo"></div>
<script> const tensorA = tf.tensor([1, 2, 3, 4], [2, 2]); document.getElementById("demo").innerHTML = tensorA; </script>
</body> </html>
- Add
- Subtract
- Multiply
- Divide
- Square
- Reshape
|
Tensor Addition
You can add two tensors using tensorA.add(tensorB):
Example
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h2>JavaScript</h2> <p>Adding tensors with tensorflow.js</p>
<div id="demo"></div>
<script> const tensorA = tf.tensor([[1, 2], [3, 4], [5, 6]]); const tensorB = tf.tensor([[1,-1], [2,-2], [3,-3]]);
// Tensor Addition const tensorNew = tensorA.add(tensorB);
// Result: [ [2, 1], [5, 2], [8, 3] ] document.getElementById("demo").innerHTML = tensorNew; </script>
</body> </html>
|
|
Tensor Subtraction
You can subtract two tensors using tensorA.sub(tensorB):
Example
const tensorA = tf.tensor([[1, 2], [3, 4], [5, 6]]); const tensorB = tf.tensor([[1,-1], [2,-2], [3,-3]]);
// Tensor Subtraction const tensorNew = tensorA.sub(tensorB);
// Result: [ [0, 3], [1, 6], [2, 9] ]
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h2>JavaScript</h2> <p>Subtracting tensors with tensorflow.js</p>
<div id="demo"></div>
<script> const tensorA = tf.tensor([[1, 2], [3, 4], [5, 6]]); const tensorB = tf.tensor([[1,-1], [2,-2], [3,-3]]);
// Tensor Subtraction const tensorNew = tensorA.sub(tensorB);
// Result: [ [0, 3], [1, 6], [2, 9] ] document.getElementById("demo").innerHTML = tensorNew; </script>
</body> </html>
|
|
Tensor Multiplication
You can multiply two tensors using tensorA.mul(tensorB):
Example
const tensorA = tf.tensor([1, 2, 3, 4]); const tensorB = tf.tensor([4, 4, 2, 2]);
// Tensor Multiplication const tensorNew = tensorA.mul(tensorB);
// Result: [ 4, 8, 6, 8 ]
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h2>JavaScript</h2> <p>Multiplying tensors with tensorflow.js</p>
<div id="demo"></div>
<script> const tensorA = tf.tensor([1, 2, 3, 4]); const tensorB = tf.tensor([4, 4, 2, 2]);
// Tensor Multiplication const tensorNew = tensorA.mul(tensorB);
// Result: [ 4, 8, 6, 8 ] document.getElementById("demo").innerHTML = tensorNew; </script>
</body> </html>
|
|
Tensor Division
You can divide two tensors using tensorA.div(tensorB):
Example
const tensorA = tf.tensor([2, 4, 6, 8]); const tensorB = tf.tensor([1, 2, 2, 2]);
// Tensor Division const tensorNew = tensorA.div(tensorB);
// Result: [ 2, 2, 3, 4 ]
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h2>JavaScript</h2> <p>Dividing tensors with tensorflow.js</p>
<div id="demo"></div>
<script> const tensorA = tf.tensor([2, 4, 6, 8]); const tensorB = tf.tensor([1, 2, 2, 2]);
// Tensor Division const tensorNew = tensorA.div(tensorB);
// Result: [ 2, 2, 3, 4 ] document.getElementById("demo").innerHTML = tensorNew; </script>
</body> </html>
|
|
Tensor Square
You can square a tensor using tensor.square():
Example
const tensorA = tf.tensor([1, 2, 3, 4]);
// Tensor Square const tensorNew = tensorA.square();
// Result [ 1, 4, 9, 16 ]
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h2>JavaScript</h2> <p>Tensor square with tensorflow.js</p>
<div id="demo"></div>
<script> const tensorA = tf.tensor([1, 2, 3, 4]);
// Tensor Square const tensorNew = tensorA.square();
// Result [ 1, 4, 9, 16 ] document.getElementById("demo").innerHTML = tensorNew; </script>
</body> </html>
|
|
Tensor Reshape
The number of elements in a tensor is the product of the sizes in the shape.
Since there can be different shapes with the same size, it is often useful to reshape a tensor to other shapes with the same size.
You can reshape a tensor using tensor.reshape():
Example
const tensorA = tf.tensor([[1, 2], [3, 4]]); const tensorB = tensorA.reshape([4, 1]);
// Result: [ [1], [2], [3], [4] ]
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <body>
<h2>JavaScript</h2> <p>Reshape a tensor with tensorflow.js</p>
<div id="demo"></div>
<script> const tensorA = tf.tensor([[1, 2], [3, 4]]); const tensorB = tensorA.reshape([4, 1]);
// Result [ [1], [2], [3], [4] ] document.getElementById("demo").innerHTML = tensorB; </script>
</body> </html>
|
|
TesorFlow.js
A JavaScript Library for
Training and Deploying Machine Learning Models In the Browser
|
Tensorflow Models
Models and Layers are important building blocks in Machine Learning.
For different Machine Learning tasks you must combine different types of Layers into a Model that can be trained with data to predict future values.
TensorFlow.js is supporting different types of Models and different types of Layers.
A TensorFlow Model is a Neural Network with one or more Layers.
A Tensorflow Project
A Tensorflow project has this typical workflow:
- Collecting Data
- Creating a Model
- Adding Layers to the Model
- Compiling the Model
- Training the Model
- Using the Model
Example
Suppose you knew a function that defined a strait line:
Y = 1.2X + 5
Then you could calculate any y value with the JavaScript formula:
To demonstrate Tensorflow.js, we could train a Tensorflow.js model to predict Y values based on X inputs.
The TensorFlow model does not know the function. |
// Create Training Data const xs = tf.tensor([0, 1, 2, 3, 4]); const ys = xs.mul(1.2).add(5);
// Define a Linear Regression Model const model = tf.sequential(); model.add(tf.layers.dense({units:1, inputShape:[1]}));
// Specify Loss and Optimizer model.compile({loss:'meanSquaredError', optimizer:'sgd'});
// Train the Model model.fit(xs, ys, {epochs:500}).then(() => {myFunction()});
// Use the Model function myFunction() { const xArr = []; const yArr = []; for (let x = 0; x <= 10; x++) { xArr.push(x); let result = model.predict(tf.tensor([Number(x)])); result.data().then(y => { yArr.push(Number(y)); if (x == 10) {plot(xArr, yArr)}; }); } } |
<html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tfjs-vis.umd.min.js"></script> <body> <h2>TensorFlow.js</h2> <p id="message">Model is training!</p>
<div id="myPlot" style="width:100%;max-width:700px"></div>
<script> // Create Training Data const xs = tf.tensor([0, 1, 2, 3, 4]); const ys = xs.mul(1.2).add(5);
// Define a Linear Regression Model const model = tf.sequential(); model.add(tf.layers.dense({units:1, inputShape:[1]}));
// Specify Loss and Optimizer model.compile({loss: 'meanSquaredError', optimizer:'sgd'});
// Train the Model model.fit(xs, ys, {epochs:500}).then(() => {myFunction()});
// Use the Model function myFunction() { const xMax = 10; const xArr = []; const yArr = []; for (let x = 0; x <= xMax; x++) { let result = model.predict(tf.tensor([Number(x)])); result.data().then(y => { xArr.push(x); yArr.push(Number(y)); if (x == xMax) {plot(xArr, yArr)}; }); } document.getElementById('message').style.display="none"; }
function plot(xArr, yArr) { // Define Data const data = [{x:xArr,y:yArr,mode:"markers",type:"scatter"}];
// Define Layout const layout = { xaxis: {range: [0, 10]}, yaxis: {range: [0, 20]}, };
// Display Plot Plotly.newPlot("myPlot", data, layout); } </script> </body> </html>
|
TensorFlow.js
|
The example is explained below:
Collecting Data
Create a tensor (xs) with 5 x values:
const xs = tf.tensor([0, 1, 2, 3, 4]); |
Create a tensor (ys) with 5 correct y answers (multiply xs with 1.2 and add 5):
const ys = xs.mul(1.2).add(5); |
Creating a Model
Create a sequential mode:.
const model = tf.sequential(); |
In a sequential model, the output from one layer is the input to the next layer. |
Adding Layers
Add one dense layer to the model.
The layer is only one unit (tensor) and the shape is 1 (one dimentional):
model.add(tf.layers.dense({units:1, inputShape:[1]}));
in a dense the layer, every node is connected to every node in the preceding layer. |
Compiling the Model
Compile the model using meanSquaredError as loss function and sgd (stochastic gradient descent) as optimizer function:
model.compile({loss:'meanSquaredError', optimizer:'sgd'}); |
Tensorflow Optimizers
- Adadelta -Implements the Adadelta algorithm.
- Adagrad - Implements the Adagrad algorithm.
- Adam - Implements the Adam algorithm.
- Adamax - Implements the Adamax algorithm.
- Ftrl - Implements the FTRL algorithm.
- Nadam - Implements the NAdam algorithm.
- Optimizer - Base class for Keras optimizers.
- RMSprop - Implements the RMSprop algorithm.
- SGD - Stochastic Gradient Descent Optimizer.
Training the Model
Train the model (using xs and ys) with 500 repeats (epochs):
model.fit(xs, ys, {epochs:500}).then(() => {myFunction()}); |
After the model is trained, you can use it for many different purposes.
This example predicts 10 y values, given 10 x values, and calls a function to plot the predictions in a graph:
function myFunction() { const xArr = []; const yArr = []; for (let x = 0; x <= 10; x++) { let result = model.predict(tf.tensor([Number(x)])); result.data().then(y => { xArr.push(x); yArr.push(Number(y)); if (x == 10) {display(xArr, yArr)}; }); } } |
<html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tfjs-vis.umd.min.js"></script> <body> <h2>TensorFlow.js</h2> <p id="message">Model is training!</p>
<div id="myPlot" style="width:100%;max-width:700px"></div>
<script> // Create Training Data const xs = tf.tensor([0, 1, 2, 3, 4]); const ys = xs.mul(1.2).add(5);
// Define a Linear Regression Model const model = tf.sequential(); model.add(tf.layers.dense({units:1, inputShape:[1]}));
// Specify Loss and Optimizer model.compile({loss: 'meanSquaredError', optimizer:'sgd'});
// Train the Model model.fit(xs, ys, {epochs:500}).then(() => {myFunction()});
// Use the Model function myFunction() { const xMax = 10; const xArr = []; const yArr = []; for (let x = 0; x <= xMax; x++) { let result = model.predict(tf.tensor([Number(x)])); result.data().then(y => { xArr.push(x); yArr.push(Number(y)); if (x == xMax) {plot(xArr, yArr)}; }); } document.getElementById('message').style.display="none"; }
function plot(xArr, yArr) { // Define Data const data = [{x:xArr,y:yArr,mode:"markers",type:"scatter"}];
// Define Layout const layout = { xaxis: {range: [0, 10]}, yaxis: {range: [0, 20]}, };
// Display Plot Plotly.newPlot("myPlot", data, layout); } </script> </body> </html>
|
TensorFlow.js
|
This example predicts 10 y values, given 10 x values, and calls a function to display the values:
function myFunction() { const xArr = []; const yArr = []; for (let x = 0; x <= 10; x++) { let result = model.predict(tf.tensor([Number(x)])); result.data().then(y => { xArr.push(x); yArr.push(Number(y)); if (x == 10) {display(xArr, yArr)}; }); } } |
<html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script> <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> <body> <h2>TensorFlow.js</h2> <p id="message">Model is training!</p>
<div id="myPlot" style="width:100%;max-width:700px"></div>
<script> // Create Training Data const xs = tf.tensor([0, 1, 2, 3, 4]); const ys = xs.mul(1.2).add(5);
// Define a Linear Regression Model const model = tf.sequential(); model.add(tf.layers.dense({units:1, inputShape:[1]}));
// Specify Loss and Optimizer model.compile({loss: 'meanSquaredError', optimizer:'sgd'});
// Train the Model model.fit(xs, ys, {epochs:500}).then(() => {myFunction()});
// Use the Model function myFunction() { const xMax = 20; const xArr = []; const yArr = []; for (let x = 10; x <= xMax; x++) { let result = model.predict(tf.tensor([Number(x)])); result.data().then(y => { xArr.push(x); yArr.push(Number(y)); if (x == xMax) {display(xArr,yArr)}; }); }
}
function display(xArr, yArr) { let text = "Correct Predicted<br>"; for (let i = 0; i < xArr.length; i++) { text += (xArr[i]*1.2+5).toFixed(4) + " " + yArr[i].toFixed(4) + "<br>"; } document.getElementById('message').innerHTML = text; } </script> </body> </html>
|
TensorFlow.js
Model is training!
|
- TensorFlow Visor is a graphic tools for visualizing Machine Learning
- It contains functions for visualizing TensorFlow Models
- Visualizations can be organized in Visors (modal browser windows)
- Can be used with Custom Tools likes d3, Chart.js, and Plotly.js
- Often called tfjs-vis
|
Using tfjs-vis
To use tfjs-vis, add the following script tag to your HTML file(s):
Example
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis"></script>
|
Scatter Plots
Example
const surface = document.getElementById('demo'); const series = ['First', 'Second'];
const serie1 = []; const serie2 = []; for (let i = 0; i < 100; i++) { serie1[i] = {x:i, y:Math.random() * 100}; serie2[i] = {x:i, y:Math.random() * 100}; }
const data = {values: [serie1, serie2], series}
tfvis.render.scatterplot(surface, data); |
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tfjs-vis.umd.min.js"></script> <body>
<h2>TensorFlow Visor</h2> <div id="demo"></div>
<script>
const surface = document.getElementById('demo'); const series = ['First', 'Second'];
const serie1 = []; const serie2 = []; for (let i = 0; i < 100; i++) { serie1[i] = {x:i, y:Math.random() * 100}; serie2[i] = {x:i, y:Math.random() * 100}; }
const data = {values: [serie1, serie2], series} tfvis.render.scatterplot(surface, data);
</script> </body> </html>
|
|
Visualizations can be organized in a Visor (a modal browser window):
Example with a Visor
const series = ['First', 'Second'];
const serie1 = []; const serie2 = []; for (let i = 0; i < 100; i++) { serie1[i] = {x:i, y:Math.random() * 100}; serie2[i] = {x:i, y:Math.random() * 100}; }
const data = {values: [serie1, serie2], series}
tfvis.render.scatterplot({name: "my Plots"}, data);
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tfjs-vis.umd.min.js"></script> <body>
<h2>TensorFlow Visor</h2>
<script>
const series = ['First', 'Second'];
const serie1 = []; const serie2 = []; for (let i = 0; i < 100; i++) { serie1[i] = {x:i, y:Math.random() * 100}; serie2[i] = {x:i, y:Math.random() * 100}; }
const data = {values: [serie1, serie2], series}
tfvis.render.scatterplot({name: "my Plots"}, data);
</script> </body> </html>
|
TensorFlow Visor
|
Bar Graphs
Example
const surface = document.getElementById('demo'); const data = [ {index: 0, value: 100}, {index: 1, value: 200}, {index: 2, value: 150}, {index: 2, value: 250}, ];
tfvis.render.barchart(surface, data);
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tfjs-vis.umd.min.js"></script> <body>
<h2>Tensorflow Visor</h2> <div id="demo"></div>
<script> const surface = document.getElementById('demo');
const data = [ {index: 0, value: 100}, {index: 1, value: 200}, {index: 2, value: 150}, {index: 3, value: 250}, ];
tfvis.render.barchart(surface, data); </script>
</body> </html>
|
|
Visualizations can be organized in a Visor (a modal browser window):
Example with a Visor
const data = [ {index: 0, value: 100}, {index: 1, value: 200}, {index: 2, value: 150}, {index: 2, value: 250}, ];
tfvis.render.barchart({name:"my Graphs"}, data);
|
<!DOCTYPE html> <html> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tfjs-vis.umd.min.js"></script> <body>
<h2>Tensorflow Visor</h2>
<script> const data = [ {index: 0, value: 100}, {index: 1, value: 200}, {index: 2, value: 150}, {index: 3, value: 250}, ];
tfvis.render.barchart({name:"my Graphs"}, data); </script>
</body> </html>
|
TensorFlow Data Collection
The data used in Example 1, is a list of car objects like this:
{ "Name": "chevrolet chevelle malibu", "Miles_per_Gallon": 18, "Cylinders": 8, "Displacement": 307, "Horsepower": 130, "Weight_in_lbs": 3504, "Acceleration": 12, "Year": "1970-01-01", "Origin": "USA" }, { "Name": "buick skylark 320", "Miles_per_Gallon": 15, "Cylinders": 8, "Displacement": 350, "Horsepower": 165, "Weight_in_lbs": 3693, "Acceleration": 11.5, "Year": "1970-01-01", "Origin": "USA" }, |
The dataset is a JSON file stored at:
Cleaning Data
When preparing for machine learning, it is always important to:
- Remove the data you don't need
- Clean the data from errors
Remove Data
A smart way to remove unnecessary data, it to extract only the data you need.
This can be done by iterating (looping over) your data with a map function.
The function below takes an object and returns only x and y from the object's Horsepower and Miles_per_Gallon properties:
function extractData(obj) { return {x:obj.Horsepower, y:obj.Miles_per_Gallon}; } |
Remove Errors
Most datasets contain some type of errors.
A smart way to remove errors is to use a filter function to filter out the errors.
The code below returns false if on of the properties (x or y) contains a null value:
function removeErrors(obj) { return obj.x != null && obj.y != null; } |
Fetching Data
When you have your map and filter functions ready, you can write a function to fetch the data.
async function runTF() { const jsonData = await fetch("cardata.json"); let values = await jsonData.json(); values = values.map(extractData).filter(removeErrors); } |
Plotting the Data
Here is some code you can use to plot the data:
function tfPlot(values, surface) { tfvis.render.scatterplot(surface, {values:values, series:['Original','Predicted']}, {xLabel:'Horsepower', yLabel:'MPG'}); } |
Shuffle Data
Always shuffle data before training.
When a model is trained, the data is divided into small sets (batches). Each batch is then fed to the model. Shuffling is important to prevent the model getting the same data over again. If using the same data twice, the model will not be able to generalize the data and give the right output. Shuffling gives a better variety of data in each batch.
TensorFlow Tensors
To use TensorFlow, input data needs to be converted to tensor data:
// Map x values to Tensor inputs const inputs = values.map(obj => obj.x); // Map y values to Tensor labels const labels = values.map(obj => obj.y);
// Convert inputs and labels to 2d tensors const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]); const labelTensor = tf.tensor2d(labels, [labels.length, 1]); |
Data Normalization
Data should be normalized before being used in a neural network.
A range of 0 - 1 using min-max are often best for numerical data:
const inputMin = inputTensor.min(); const inputMax = inputTensor.max(); const labelMin = labelTensor.min(); const labelMax = labelTensor.max(); const nmInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin)); const nmLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin)); |
Tensorflow Model
A Machine Learning Model is an algorithm that produces output from input.
This example uses 3 lines to define a ML Model:
const model = tf.sequential(); model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true})); model.add(tf.layers.dense({units: 1, useBias: true})); |
Sequential ML Model
const model = tf.sequential(); |
creates a Sequential ML Model.
In a sequential model, the input flows directly to the output. Other models can have multiple inputs and multiple outputs. Sequential is the easiest ML model. It allows you to build a model layer by layer, with weights that correspond to the next layer.
TensorFlow Layers
model.add() is used to add two layers to the model.
tf.layer.dense is a layer type that works in most cases. It multiplies its inputs by a weight-matrix and adds a number (bias) to the result.
Shapes and Units
inputShape: [1] because we have 1 input (x = horsepower).
units: 1 defines the size of the weight matrix: 1 weight for each input (x value).
Compiling a Model
Compile the model with a specified optimizer and loss function:
model.compile({loss: 'meanSquaredError', optimizer:'sgd'}); |
The compiler is set to use the sgd optimizer. It is simple to use and quite effective.
meanSquaredError is the function we want to use to compare model predictions and true values.
Training Function
async function trainModel(model, inputs, labels, surface) { const batchSize = 25; const epochs = 100; const callbacks = tfvis.show.fitCallbacks(surface, ['loss'], {callbacks:['onEpochEnd']}) return await model.fit(inputs, labels, {batchSize, epochs, shuffle:true, callbacks:callbacks} ); }
|
epochs defines how many iterations (loops) the model will do.
model.fit is the function that runs the loops.
callbacks defines the callback function to call when the model wants to redraw the graphics.
Test the Model
When a model is trained, it is important to test and evaluate it.
We do this by inspecting what the model predicts for a range of different inputs.
But, before we can do that, we have to un-normalize the data:
Un Normalize
let unX = tf.linspace(0, 1, 100); let unY = model.predict(unX.reshape([100, 1]));
const unNormunX = unX.mul(inputMax.sub(inputMin)).add(inputMin); const unNormunY = unY.mul(labelMax.sub(labelMin)).add(labelMin);
unX = unNormunX.dataSync(); unY = unNormunY.dataSync(); |
Then we can look at the result:
Plot the Result
const predicted = Array.from(unX).map((val, i) => { return {x: val, y: unY[i]} });
// Plot the Result tfPlot([values, predicted], surface1) |
Input Data
| | |