Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Hands-on TensorFlow JS in Machine Learning Models (Part 2)

Tags: const

TensorFlow JSHands-on TensorFlow JS in Machine Learning Models (Part II)

ArticleLearn how to implement Machine Learning models in JavaScript using the TensorFlow JS library.

Continue reading

TensorFlow JS

To implement machine learning models in JavaScript, the TensorFlow JS library was chosen.

It allows the development of machine learning models in JavaScript and uses machine learning directly in the browser or in Node.js. The reason this library was chosen is that it allows the user to train a machine-learning model using their own resources.

This means that a machine learning model on a website can be trained using a client’s computer with data generated in real-time from that user’s interaction with the site. Also, instead of constantly exchanging data between the client and the server, TensorFlow JS allows using the algorithm in real-time during its training.

The main concept to know about TensorFlow is that it uses its own data type called a tensor. According to the TensorFlow JS API, a tensor is a set of values shaped into an array of one or more dimensions with the following main properties:

• dtype – The data type
• rank – The number of dimensions
• shape – The size of each dimension

A Tensor can be created from the following data types:
• float32
• bool
• int32
• complex64
• string

To implement machine learning models in JavaScript, the TensorFlow JS library was chosen.

It allows the development of machine learning models in JavaScript and uses machine learning directly in the browser or in Node.js.

The reason this library was chosen is that it allows the user to train a machine-learning model using their own resources.

This means that a machine learning model on a website can be trained using a client’s computer with data generated in real-time from that user’s interaction with the site.

Also, instead of constantly exchanging data between the client and the server, TensorFlow JS allows using the algorithm in real-time during its training.

The main concept to know about TensorFlow is that it uses its own data type called a tensor.

According to the TensorFlow JS API, a tensor is a set of values shaped into an array of one or more dimensions with the following main properties:

• dtype – The data type
• rank – The number of dimensions
• shape – The size of each dimension

A Tensor can be created from the following data types:
• float32
• bool
• int32
• complex64
• string

KNN Implementation

This KNN code contains an implementation of the K-nearest neighbors algorithm.

const tf = require('@tensorflow/tfjs');
// Class constructor
class KNN {
constructor(features, labels, k,) { this.features = features this.labels = labels
this.k = k
}
// KNN algorithm using standartizations scaling
standartizationKNN(testPoint) {
// Converting variables to tensor
const tensorFeatures = tf.tensor(this.features) const tensorLabels = tf.tensor(this.labels) const predictionPoint = tf.tensor(testPoint)
// Calculating mean and vatiance for standartization
const { mean, variance } = tf.moments(this.features, 0);
// Standartization of query point
const scaledPrediction = predictionPoint.sub(mean).div(variance.pow(0.5));
return (
)
tensorFeatures
// STANDARTI ATION
.sub(mean)
.div(variance.pow(0.5))
// DISTANCE CALCULATION
.sub(scaledPrediction)
.pow(2)
.sum(1)
.pow(0.5)
// CONCAT FEATURES AND LABELS TOGETHER
.expandDims(1)
.concat(tensorLabels, 1)
// UNSTACK TO A JA ASCRIPT ARRAY
.unstack()
// SORT
.sort((tensorA, tensorB) => (tensorA.arraySync()[0] > tensorB.arraySync()[0]?1 : -1))
// TAKE TOP K RECORDS
.slice(0, this.k)
// A ERAGE OF K OF LABELS CLOSEST TO THE PREDICTION POINT
.reduce((acc, pair) => acc + pair.arraySync()[1], 0) / this.k
}
// KNN algorithm using normalization scaling
normalizationKNN(testPoint) {
// Converting variables to tensor
const normalizedArray = this.minMax(this.features, this.features[0].length, testPoint)
const tensorFeatures = tf.tensor(normalizedArray[0]) const scaledPoint = tf.tensor(normalizedArray[1]) const tensorLabels = tf.tensor(this.labels)
return ( tensorFeatures
// DISTANCE CALCULATION
.sub(scaledPoint)
.pow(2)
.sum(1)
.pow(0.5)
// CONCAT FEATURES AND LABELS TOGETHER
.expandDims(1)
.concat(tensorLabels, 1)
// UNSTACK TO A JA ASCRIPT ARRAY
.unstack()
// SORT
.sort((tensorA, tensorB) => (tensorA.arraySync()[0] > tensorB.arraySync()[0]?1 : -1))
)
// TAKE TOP K RECORDS
.slice(0, this.k)
// A ERAGE OF K OF LABELS CLOSEST TO THE PREDICTION POINT
.reduce((acc, pair) => acc + pair.arraySync()[1], 0) / this.k
}
// Min Max Normalization
minMax(data, featuresCount, point) {
const dataArr = []
for (let i = 0; i  arr.map((row) => row[n])
const min = Math.min.apply(Math, column(data, i))
const max = Math.max.apply(Math, column(data, i))
pointArr.push((point[i] - min) / (max - min))
for (let j = 0; j 

KNN Сode Explanation

This is a JavaScript class containing a K-Nearest Neighbor algorithm. It contains two KNN
methods that differ in the type of data scaling.
KNN class has the following properties:

  • Features – independent data.
  • Labels – dependent data.
  • K – number of data points used for calculation.

The “standardizationKNN” method implements the KNN algorithm using standardization
scaling (Liu 2022, 7):

Standardization is used when data follows a Gaussian distribution. Also, standardization does not affect outliers, since it has no bounding range. In the case of KNN, this can be useful so that outliers do not affect the calculations too much.

The “normalizationKNN” method implements the KNN algorithm using normalization
scaling:

Normalization is used when the data doesn’t have Gaussian Distribution, or the data distribution is unknown. Normalization is applied in the “minMax” method.

Linear Regression Implementation

The Linear Regression Code contains an implementation of the gradient descent algorithm for a linear regression model.

const tf = require('@tensorflow/tfjs');
const _ = require('lodash');
class LinearRegression {
constructor(features, labels,
options) {
// independent data
this.features = this.processFeatures(features);
// dependent data
this.labels = tf.tensor(labels);
// array with history of mean squared error
this.mseHistory = [];
// array with history of learning
rate this.learningRateHistory =
[]; this.options = Object.assign(
{ learningRate: 0.1, iterations:
100 }, options
);
// m and b values
this.weights = tf.zeros([this.features.shape[1], 1]);
}
gradientDescent(features, labels) {
// Calculating the slope of MSE with respect to m and b
(features* (features*weights)-labels)/observations
const currentGuesses = features.matMul(this.weights);
const differences = currentGuesses.sub(labels);
const slopes = features
.transpose()
.matMul(differences)
.div(features.shape[0]);
// Updating m and b
this.weights = this.weights.sub(slopes.mul(this.options.learningRate));
}
// Training loop
train() {
// Calculating number of batches
const batchQuantity = Math.floor(
this.features.shape[0] / this.options.batchSize
);
for (let i = 0; i 
this.mseHistory[this.mseHistory.length-2]) {
this.options.learningRate /= 2;
} else {
this.options.learningRate *= 1.05;
}
this.learningRateHistory.push(this.options.learningRate);
}
}
module.exports = LinearRegression;

Linear Regression Code Explanation

This is a JavaScript class for solving Linear Regression with a Gradient Descent algorithm. The following is a brief description of its methods. The “processFeatures” and “standardize” methods are used to apply standardization on features.

The “train” method is used to create a training loop and split the data into batches. Considering that in the following example, the model is trained on a small dataset, dividing the dataset into batches will provide a stable gradient descent convergence without increasing the training time and not being heavily dependent on computer resources.

The “gradientDescent” method is used to calculate the slope and update m and b values as shown in when Solving Linear Regression with Gradient Descent Algorithm. The  “updateLearningRate” and “recordMSE” methods are used to update the learning rate. Knowing the difference between the current and previous MSE values, the efficiency of the algorithm can be increased by adjusting the learning rate.

The “test” method is used for testing the model by calculating the coefficient of determination. The “predict” method is used to get predictions from the trained model.

Linear Regression Code Explanation

This is a JavaScript class for solving Linear Regression with a Gradient Descent algorithm. The following is a brief description of its methods.

The “processFeatures” and “standardize” methods are used to apply standardization on features.

The “train” method is used to create a training loop and split the data into batches.

Considering that in the following example, the model is trained on a small dataset, dividing the dataset into batches will provide a stable gradient descent convergence without increasing the training time and not being heavily dependent on computer resources.

The “gradientDescent” method is used to calculate the slope and update m and b values as shown in when Solving Linear Regression with Gradient Descent Algorithm.

The “updateLearningRate” and “recordMSE” methods are used to update the learning rate. Knowing the difference between the current and previous MSE values, the efficiency of the algorithm can be increased by adjusting the learning rate.

The “test” method is used for testing the model by calculating the coefficient of determination. The “predict” method is used to get predictions from the trained model.

Logistic Regression Implementation

This Logistic Regression Code contains an implementation of the gradient descent algorithm for a logistic regression model.

const tf = require('@tensorflow/tfjs'); const _ = require('lodash');
class LogisticRegression {
constructor(features, labels, options) {
// independent data
this.features = this.processFeatures(features);
// dependent data
this.labels = tf.tensor(labels);
// array with history of cost
this.costHistory = [];
this.options = Object.assign(
{ learningRate: 0.1, iterations: 1000, decisionBoundary:
0.5 }, options
);
// m and b values
this.weights = tf.zeros([this.features.shape[1], 1]);
}
gradientDescent(features, labels) {
// Calculating the slope of MSE with respect to m and b
const currentGuesses = features.matMul(this.weights).sigmoid();
const differences = currentGuesses.sub(labels);
const slopes = features
.transpose()
.matMul(differences)
.div(features.shape[0]);
// Updating m and b
this.weights = this.weights.sub(slopes.mul(this.options.learningRate));
}
// Training loop
train() {
// Calculating number of batches
const batchQuantity = Math.floor(
this.features.shape[0] / this.options.batchSize
);
for (let i = 0; i  this.costHistory[1]) {
this.options.learningRate /= 2;
} else {
this.options.learningRate *= 1.05;
}
}
}
module.exports = LogisticRegression;

Logistic Regression Code Explanation

This JavaScript class is designed to solve the Logistic Regression using the gradient descent algorithm. Although it shares similarities with the Linear Regression class, there are some significant differences. The first change is in the “gradientDescent” method, which utilizes a sigmoid function instead of a linear one. Additionally, a different loss function called Cross Entropy is used instead of MSE, as explained in section Solving Logistic Regression with Gradient descent Algorithm. Due to this difference, the “recordMSE” method is replaced by the
“recordCost” method.

Since Logistic Regression is a classification model, the approach to testing the model differs from regression models. Therefore, the “test” method calculates the percentage of correct predictions. It is worth noting that the addition of a new option to the parameters, called decisionBoundary, is the next major change in this class. This parameter is set to 0.5 by default. Therefore, predictions above this threshold will be classified as 1, and those below as 0. However, in some instances, this parameter may need to be adjusted based on the model’s purpose.

For example, in situations where human life is at risk, even the slightest chance of danger should be classified as dangerous. In such cases, the decisionBoundary parameter can be set to a lower value.

Finally, this class has two prediction methods. The “predict” method provides the probability of an event occurring, while the “predictRound” method rounds the probability and classifies the event based on the decisionBoundary parameter. These features are unique to Logistic Regression and make it an effective tool for solving classification problems.

Logistic Regression Code Explanation

This JavaScript class is designed to solve the Logistic Regression using the gradient descent algorithm.

Although it shares similarities with the Linear Regression class, there are some significant differences.

The first change is in the “gradientDescent” method, which utilizes a sigmoid function instead of a linear one.

Additionally, a different loss function called Cross Entropy is used instead of MSE, as explained in section Solving Logistic Regression with Gradient descent Algorithm.

Due to this difference, the “recordMSE” method is replaced by the
“recordCost” method.

Since Logistic Regression is a classification model, the approach to testing the model differs from regression models.

Therefore, the “test” method calculates the percentage of correct predictions.

It is worth noting that the addition of a new option to the parameters, called decisionBoundary, is the next major change in this class.

This parameter is set to 0.5 by default. Therefore, predictions above this threshold will be classified as 1, and those below as 0.

However, in some instances, this parameter may need to be adjusted based on the model’s purpose.

For example, in situations where human life is at risk, even the slightest chance of danger should be classified as dangerous.

In such cases, the decisionBoundary parameter can be set to a lower value.

Finally, this class has two prediction methods. The “predict” method provides the probability of an event occurring, while the “predictRound” method rounds the probability and classifies the event based on the decisionBoundary parameter.

These features are unique to Logistic Regression and make it an effective tool for solving classification problems.

Testing

This chapter demonstrates the work of the created machine learning classes using real-world examples. To do this, using the LightningСhart JS library, four applications were created that demonstrate both machine learning algorithms and visualization of the results of their work.

LightningChart JS

LightningChart JS is a WebGL-based JavaScript charting library. It is capable of displaying massive amounts of data inside the browser or web application while maintaining excellent performance with GPU acceleration & WebGL rendering. These qualities make this library well suited for use with machine learning models, which often require huge amounts of data and are highly dependent on both GPU and CPU performance.

KNN Classification App Example

Here is the code for an application that classifies data points based on their coordinates. This application uses a dataset with points on two-dimensional coordinates classified by two colors: red and blue.

This chapter demonstrates the work of the created machine learning classes using real-world examples.

To do this, using the LightningСhart JS library, four applications were created that demonstrate both machine learning algorithms and visualization of the results of their work.

LightningChart JS

LightningChart JS is a WebGL-based JavaScript charting library.

It is capable of displaying massive amounts of data inside the browser or web application while maintaining excellent performance with GPU acceleration & WebGL rendering.

These qualities make this library well suited for use with machine learning models, which often require huge amounts of data and are highly dependent on both GPU and CPU performance.

KNN Classification App Example

Here is the code for an application that classifies data points based on their coordinates. This application uses a dataset with points on two-dimensional coordinates classified by two colors: red and blue.

const lcjs = require("@arction/lcjs");
const KNN = require('./KNN');
const { lightningChart, PointShape, SolidFill, ColorHEX, translatePoint } = lcjs;
// Chart creation
const chart = lightningChart()
.ChartXY({
})
.setTitle("KNN classification test");
// Red point series
const redPoints = chart
.addPointSeries({ pointShape: PointShape.Circle })
.setPointSize(10)
.setPointFillStyle(new SolidFill({ color: ColorHEX('#F00') }))
// Blue point series
const bluePoints = chart
.addPointSeries({ pointShape: PointShape.Triangle })
.setPointSize(10)
.setPointFillStyle(new SolidFill({ color: ColorHEX('#344ceb') }))
// Fetch data from fileAppendix 1 shows the code for an application that classifies data points based on their coordinates.
fetch(
document.head.baseURI + "examples/assets/0015/testData.json"
)
.then((r) => r.json())
.then((data) => {
const features = []
const labels = []
// Assign data to features and labels
for (let i = 0;i {
const mouseLocationClient = { x: event.clientX, y: event.clientY }
// Translate mouse location to LCJS coordinate system for solving data points from series, and translating to Axes.
const mouseLocationEngine = chart.engine.clientLocation2Engine(mouseLocationClient.x, mouseLocationClient.y)
  // Translate mouse location to chart coordinate
const mouseLocationAxis = translatePoint(mouseLocationEngine, chart.engine.scale, {
x: chart.getDefaultAxisX(), y: chart.getDefaultAxisY(),
})
const mouseX = mouseLocationAxis.x
const mouseY = mouseLocationAxis.y
// Call a KNN method
const result = testKNN.normalizationKNN([mouseX,mouseY])
// Assign result to point series
if (Math.round(result) == 0){ redPoints.add({x:mouseX,y:mouseY})
}
else{
bluePoints.add({x:mouseX,y:mouseY})
}
})
})

FIGURE 6: KNN classification application.

When the coordinates are clicked, a new point is created and classified by color depending on its position in the coordinates. Figure 6 shows the newly added points, highlighted in green for convenience. Testing has shown that points are successfully classified depending on their location on the coordinate system.

FIGURE 7: KNN classification app (new classified data points).

In this application, coordinates are used as features, and red and blue colors will be represented as 0 and 1 and used as labels. Using the KNN class, the user only needs to take a few simple steps to implement the algorithm in their application.

  1. Fill two arrays of arrays: one with features and one with labels.
const features = []
const labels = []
// Assign data to features and labels
for (let i = 0;i

2. Create an object from the KNN class using features, labels, and k as parameters.

const testKNN = new KNN(features, labels, 10);

3. Call a “normalizationKNN” method using query features as parameters.

const result = testKNN.normalizationKNN([mouseX,mouseY])

Since the result of the algorithm is the average number of k labels, to classify a query point the result must be rounded.

// Assign result to point series
if (Math.round(result) == 0){
redPoints.add({x:mouseX,y:mous eY})
}
else{
bluePoints.add({x:mouseX,y:mouseY})
}

KNN Regression App Example

// Import LightningChartJS
const lcjs = require('@arction/lcjs')
const { lightningChart, ImageFill, ImageFitMode, translatePoint, PointShape,
SolidFill, AutoCursorModes, AxisTickStrategies } = lcjs
const tf = require('@tensorflow/tfjs')
const dashboard = lightningChart().Dashboard({ numberOfColumns: 4,
numberOfRows: 3,
})
const panel = dashboard.createUIPanel({ columnIndex: 3,
rowIndex: 0,
})
panel.onResize((chart, width, height, engineWidth, engineHeight) => { block.style.left = engineWidth - width + 'px'
})
const chart = dashboard
.createChartXY({ columnIndex: 0,
rowIndex: 0,
columnSpan: 3,
rowSpan: 3,
})
.setTitle('KNN Housing Price Test')
chart.getDefaultAxes().forEach((axis) => axis.setTickStrategy(AxisTickStrategies.Empty))
const blockDiv = document.createElement('div') blockDiv.id = 'block'
const sqft_lotText = document.createElement('input') sqft_lotText.id = 'textBox'
sqft_lotText.labels = 'slider' sqft_lotText.value = 4000 blockDiv.appendChild(sqft_lotText)
const sqft_lotSlider = document.createElement('input') sqft_lotSlider.type = 'range'
sqft_lotSlider.min = 4000
sqft_lotSlider.max = 30000 sqft_lotSlider.value = sqft_lotSlider.min sqft_lotSlider.id = 'slider' blockDiv.appendChild(sqft_lotSlider)
dashboard.engine.container.append(blockDiv)
const map = dashboard
.createChartXY({ columnIndex: 3,
rowIndex: 1,
rowSpan: 2,
})
.setTitle('') map.getDefaultAxes().forEach((axis) =>
axis.setTickStrategy(AxisTickStrategies.Empty))
const axisY = map.getDefaultAxisY()
const axisX = map.getDefaultAxisX()
const w = 320
const h =40
const zoom = 10 const lat = 4 .5112 const lng = -122.25
const apiKey = 'Enter Google Maps API key'
// //Function which calculates latitude and longitude coordinates from pixel on map picture.
function getPointLatLng(x, y) {
const parallelMultiplier = Math.cos((lat * Math.PI) / 1 0)
const degreesPerPixelX = 3 0 / Math.pow(2, zoom + )
const degreesPerPixelY = (3 0 / Math.pow(2, zoom + )) * parallelMultiplier
const pointLat = lat - degreesPerPixelY * (y - h / 2) const pointLng = lng + degreesPerPixelX * (x - w / 2) return { y: pointLat, x: pointLng }
}
axisX.setInterval(getPointLatLng(0, 0).x, getPointLatLng(w, 0).x, true, true) axisY.setInterval(getPointLatLng(0, h).y, getPointLatLng(0, 0).y, true, true)
// Load image from Google static maps const img = new Image() img.crossOrigin = 'anonymous'
img.src = `https://maps.googleapis.com/maps/api/staticmap language=en&size= {w}x {h}&zoom= {zoom}&center= {lat}, {lng}&key= {apiKey}`
//Set series background to image.
map.setSeriesBackgroundFillStyle(
new ImageFill({ source: img,
fitMode: ImageFitMode.Stretch,
})
)
map.onSeriesBackgroundMouseClick((_, event) => {
const mouseLocationClient = { x: event.clientX, y: event.clientY }
// Translate mouse location to LCJS coordinate system for solving data points from series, and translating to Axes.
const mouseLocationEngine = map.engine.clientLocation2Engine(mouseLocationClient.x, mouseLocationClient.y)
// Translate mouse location to chart coordinate
const mouseLocationAxis = translatePoint(mouseLocationEngine, map.engine.scale, { x: map.getDefaultAxisX(),
y: map.getDefaultAxisY(),
})
chart.dispose()
createMap(mouseLocationAxis.x, mouseLocationAxis.y)
})
function createMap(lng, lat) {
// Create chart
const chart = dashboard
.createChartXY({
columnIndex: 0,
rowIndex: 0,
columnSpan: 3,
rowSpan: 3,
})
.setTitle('KNN Housing Price Test')
.setMouseInteractionWheel oom(false)
.setMouseInteractionRectangle oom(false)
// Remove axes
chart.getDefaultAxes().forEach((axis) => axis.setTickStrategy(AxisTickStrategies.Empty))
// Create point series for predicted points
const pointSeries = chart
.addPointSeries({ pointShape: PointShape.Circle })
.setIndividualPoint alueEnabled(true)
.setPointSize(10)
.setPointFillStyle(new SolidFill({ color: lcjs.ColorHEX('#fc030b') }))
// Custom table for predicted points
.setCursorResultTableFormatter((tableBuilder, pointSeries, x, y, dataPoint) => {
return tableBuilder
.addRow(`Lng: `, '', dataPoint.x.toFixed(5))
.addRow(`Lat: `, '', dataPoint.y.toFixed(5))
.addRow(`Sqft lot: `, '', dataPoint.sqft_lot)
.addRow(`Price: `, '', ' ', dataPoint.value.toFixed(0))
})
//Create point series for original points
const pointSeriesData = chart
.addPointSeries({ pointShape: PointShape.Circle })
.setIndividualPoint alueEnabled(true)
.setPointSize(5)
.setPointFillStyle(new SolidFill({ color: lcjs.ColorHEX('#32 5a ') }))
.setCursorResultTableFormatter((tableBuilder, pointSeries, x, y, dataPoint) => {
return tableBuilder
.addRow(`Lng: `, '', dataPoint.x.toFixed(5))
.addRow(`Lat: `, '', dataPoint.y.toFixed(5))
.addRow(`Sqft lot: `, '', dataPoint.sqft_lot.toFixed(0))
.addRow(`Sqft living: `, '', dataPoint.sqft_living.toFixed(0))
.addRow(`Condition: `, '', dataPoint.condition.toFixed(0))
.addRow(`Price: `, '', ' ', dataPoint.value.toFixed(0))
})
//Get Google Maps screenshot
const axisY = chart.getDefaultAxisY()
const axisX = chart.getDefaultAxisX()
// Set parameters for Google Map and Chart
const w = 40 const h = 320 const zoom = 13
const apiKey = 'Enter Google Maps API key'
//Function which calculates latitude and longitude coordinates from pixel on map picture.
function getPointLatLng(x, y) {
const parallelMultiplier = Math.cos((lat * Math.PI) / 1 0)
const degreesPerPixelX = 3 0 / Math.pow(2, zoom + )
const degreesPerPixelY = (3 0 / Math.pow(2, zoom + )) * parallelMultiplier
const pointLat = lat - degreesPerPixelY * (y - h / 2) const pointLng = lng + degreesPerPixelX * (x - w / 2) return { y: pointLat, x: pointLng }
}
// Apply map parameters for Axes
axisX.setInterval(getPointLatLng(0, 0).x, getPointLatLng(w, 0).x, true, true) axisY.setInterval(getPointLatLng(0, h).y, getPointLatLng(0, 0).y, true, true)
const longStart = getPointLatLng(0, 0).x const longEnd = getPointLatLng(w, 0).x const latStart = getPointLatLng(0, h).y const latEnd = getPointLatLng(0, 0).y
// Load image from Google static maps const img = new Image() img.crossOrigin = 'anonymous'
img.src = `https://maps.googleapis.com/maps/api/staticmap language=en&size= {w}x {h}&zoom= {zoom}&center= {lat}, {lng}&key= {apiKey}`
//Set series background to image.
chart.setSeriesBackgroundFillStyle(
new ImageFill({ source: img,
fitMode: ImageFitMode.Stretch,
})
)
// Fetch original data
fetch(document.head.baseURI + 'examples/assets/1101/houseData.json')
.then((r) => r.json())
.then((data) => { sqft_lotSlider.oninput = () => {
sqft_lotText.value = sqft_lotSlider.value
}
const features = new Array()
const labels = new Array()
// Get features and labels from data, add original points to series
for (let i = 0; i  latStart) & (data[i].lat  longStart) & (data[i].long  {
const mouseLocationClient = { x: event.clientX, y: event.clientY }
// Translate mouse location to LCJS coordinate system for solving data points from series, and translating to Axes.
const mouseLocationEngine = chart.engine.clientLocation2Engine(mouseLocationClient.x, mouseLocationClient.y)
// Translate mouse location to chart coordinate
const mouseLocationAxis = translatePoint(mouseLocationEngine, chart.engine.scale,
{
x: chart.getDefaultAxisX(), y: chart.getDefaultAxisY(),
})
// Point for KNN
const testPoint = [mouseLocationAxis.x, mouseLocationAxis.y, sqft_lotText.value]
// Predict label and add predicted point to series
const result = knn(features, labels, testPoint, 20)
pointSeries.add({ x: mouseLocationAxis.x, y: mouseLocationAxis.y, sqft_lot:
sqft_lotText.value, value: result })
})
})
}
//KNN Algorithm
function knn(features, labels, testPoint, k) {
const normalizedArray = minMax(features, features[0].length, testPoint)
const tensorFeatures = tf.tensor(normalizedArray[0]) const scaledPoint = tf.tensor(normalizedArray[1]) const tensorLabels = tf.tensor(labels)
return ( tensorFeatures
// DISTANCE CALCULATION
.sub(scaledPoint)
.pow(2)
.sum(1)
.pow(0.5)
// CONCAT FEATURES AND LABELS TOGETHER
.expandDims(1)
.concat(tensorLabels, 1)
// UNSTACK TO A JA ASCRIPT ARRAY
.unstack()
// SORT
.sort((tensorA, tensorB) => (tensorA.arraySync()[0] > tensorB.arraySync()[0] 1
: -1))
// TAKE TOP K RECORDS
.slice(0, k)
// A ERAKE OF K OF LABELS CLOSEST TO THE PREDICTION POINT
.reduce((acc, pair) => acc + pair.arraySync()[1], 0) / k
)
}
function minMax(data, featuresCount, point) {
const dataArr = []
for (let i = 0; i  arr.map((row) => row[n])
const min = Math.min.apply(Math, column(data, i))
const max = Math.max.apply(Math, column(data, i)) pointArr.push((point[i] - min) / (max - min))
for (let j = 0; j 

Above is the code for an application that predicts the price of a house based on its size and coordinates. Figure 7 illustrates the application interface, which includes two maps and a UI panel. The smaller map located in the lower right-hand corner displays a map of Seattle.

When the user clicks on this map, the selected area of the city is zoomed in on the large map on the left-hand side. The blue points on the lefthand map indicate house objects that contain the house’s characteristics and its price. The location of these points on the chart corresponds to their actual location on the map.

To select the size of the house, the user can use the slider located in the upper righthand corner. Clicking on the map generates a data point with the estimated price of a house of the selected size at that location.

FIGURE 8: KNN regression application.

This app is built using the Google Maps API. The features are latitude, longitude, and the size of the house in square feet. House prices in Canadian dollars are used as labels. The algorithm uses only data points that are visible on the left map to speed up calculations. Also, standardization scaling is used in this application to limit the influence of very expensive houses on calculations.

The use of the KNN class is the same as the example described in the KNN Classification App Example. Testing has shown that the predicted price is very close to the real data in various areas of the city. It is expected that the denser the data points are located to the input data point, the more accurate the prediction is.

This app is built using the Google Maps API. The features are latitude, longitude, and the size of the house in square feet.

House prices in Canadian dollars are used as labels. The algorithm uses only data points that are visible on the left map to speed up calculations.

Also, standardization scaling is used in this application to limit the influence of very expensive houses on calculations.

The use of the KNN class is the same as the example described in the KNN Classification App Example.

Testing has shown that the predicted price is very close to the real data in various areas of the city.

It is expected that the denser the data points are located to the input data point, the more accurate the prediction is.

Linear Regression App Example 

const LinearRegression = require('./linear-regression');
const lcjs = require('@arction/lcjs')
const {lightningChart, translatePoint} = lcjs
// Creating dashboard
const dashboard = lightningChart().Dashboard({ numberOfColumns: 3,
numberOfRows: 2,
})
const dataChart = dashboard.createChartXY({
columnIndex: 0,
rowIndex: 0,
columnSpan: 2,
rowSpan: 2
})
.setTitle('Data Chart')
const axisY = dataChart.getDefaultAxisY()
const axisX = dataChart.getDefaultAxisX()
// Setting axis intervals axisX.setInterval(0, 500, true, true) axisY.setInterval(0, 3, true, true)
//Creating MSE chart
const MSEchart = dashboard.createChartXY({ columnIndex: 2,
rowIndex: 0,
columnSpan: 1,
rowSpan: 1
})
.setTitle('MSE Chart')
//Crating learning rate chart
const LRchart = dashboard.createChartXY({ columnIndex: 2,
rowIndex: 1,
columnSpan: 1,
rowSpan: 1
})
.setTitle('Learning Rate Chart')
const MSEseries = MSEchart.addLineSeries() const LRseries = LRchart.addLineSeries() const dataSeries = dataChart.addPointSeries()
//Creating custom table
.setCursorResultTableFormatter((tableBuilder, pointSeries, x, y, dataPoint) => {
return tableBuilder
.addRow(`Horsepower: `, '', dataPoint.x.toFixed(5))
.addRow(`Weight: `, '', dataPoint.y.toFixed(5))
.addRow(`MPG: `, '', dataPoint.mpg.toFixed(5))
})
fetch(
document.head.baseURI + "examples/assets/1110/cars.json"
)
.then((r) => r.json())
.then((data) => {
const features = []
const labels = []
// Assigning data to features and labels
for (let i = 0; i {
const mouseLocationClient = { x: event.clientX, y: event.clientY }
// Translate mouse location to LCJS coordinate system for solving data points from series, and translating to Axes.
const mouseLocationEngine = dataChart.engine.clientLocation2Engine(mouseLocationClient.x, mouseLocationClient.y)
// Translate mouse location to chart coordinate
const mouseLocationAxis = translatePoint(mouseLocationEngine, dataChart.engine.scale, {
x: dataChart.getDefaultAxisX(), y: dataChart.getDefaultAxisY(),
})
const mouseX = mouseLocationAxis.x
const mouseY = mouseLocationAxis.y
// Getting prediction
const prediction = regression.predict([[mouseX, mouseY]])
// Adding point with prediction to series
dataSeries.add({ x: mouseX, y: mouseY, mpg: prediction})
})
})

The code above is for an application that predicts a car’s MPG based on its weight and horsepower. Such an application can be useful for car manufacturers to predict certain parameters of a car.

Figure 8 illustrates the application interface, which consists of three charts: the left chart is used to create a query and display information, while the two charts on the right allow the user to track the performance of the model and adjust its parameters by displaying changes in MSE and learning rate over time.

The two-dimensional chart on the left consists of two axes: the x-axis represents horsepower, and the y-axis represents weight. When a point is clicked on the chart, it creates a data point with the corresponding parameters and the predicted MPG. Testing has shown that even using a small dataset, the predicted characteristics of cars are close to real ones.

For instance, if the user notices that the MSE does not change for a certain number of iterations, they can reduce the number of iterations to reduce the training time of the model. The two charts on the right allow the user to monitor the performance of the model and make necessary adjustments to improve its accuracy.

The code above is for an application that predicts a car’s MPG based on its weight and horsepower.

Such an application can be useful for car manufacturers to predict certain parameters of a car.

Figure 8 illustrates the application interface, which consists of three charts: the left chart is used to create a query and display information, while the two charts on the right allow the user to track the performance of the model and adjust its parameters by displaying changes in MSE and learning rate over time.

The two-dimensional chart on the left



This post first appeared on Arction Ltd - Webgl Charts Library, please read the originial post: here

Share the post

Hands-on TensorFlow JS in Machine Learning Models (Part 2)

×

Subscribe to Arction Ltd - Webgl Charts Library

Get updates delivered right to your inbox!

Thank you for your subscription

×