TensorFlow JS in Browser

TensorFlow.js (TF.js) runs TensorFlow models directly in a web browser using JavaScript. A trained Python model converts to TF.js format and runs on the user's device — no server required, no data ever leaves the browser. This enables real-time image classification, webcam-based applications, and interactive machine learning demos that run offline. TF.js also supports training models entirely in the browser using WebGL GPU acceleration.

Why Run ML in the Browser

Server-side ML:                        Browser-side ML (TF.js):
  Data sent to server ────────────►      Data stays on device
  Server processes it                    Model runs locally in browser
  Prediction sent back                   Privacy preserved
  Latency: 100–500ms                     Latency: 20–50ms
  Requires internet                      Works offline
  Scales with server capacity            Scales infinitely (each user runs their own)
  Privacy concern for sensitive data     No privacy concern

Installing TF.js

Option 1 — CDN (for quick start in HTML):
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>

Option 2 — npm (for Node.js or bundled projects):
npm install @tensorflow/tfjs

Option 3 — Node.js with native bindings (faster CPU/GPU):
npm install @tensorflow/tfjs-node
npm install @tensorflow/tfjs-node-gpu   # For NVIDIA GPU

Converting a Python Model to TF.js

# In Python — install the converter
pip install tensorflowjs

# Convert from SavedModel
tensorflowjs_converter \
  --input_format=tf_saved_model \
  my_saved_model/ \
  tfjs_model/

# Convert from Keras .keras file
tensorflowjs_converter \
  --input_format=keras \
  my_model.keras \
  tfjs_model/
Resulting files:
tfjs_model/
├── model.json          ← Architecture and weight manifest
├── group1-shard1of3.bin  ← Weight data (split into shards for parallel download)
├── group1-shard2of3.bin
└── group1-shard3of3.bin

Loading and Running a Model in JavaScript

<!-- HTML file -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>

<script>
async function runModel() {
  // Load the converted model
  const model = await tf.loadLayersModel('tfjs_model/model.json');
  console.log('Model loaded');
  model.summary();

  // Create a sample input tensor
  // For an image classifier expecting (1, 224, 224, 3):
  const inputTensor = tf.zeros([1, 224, 224, 3]);

  // Run prediction
  const prediction = model.predict(inputTensor);
  prediction.print();

  // Get the class with highest probability
  const classIndex = prediction.argMax(-1).dataSync()[0];
  console.log('Predicted class:', classIndex);

  // Always dispose tensors to free WebGL memory
  inputTensor.dispose();
  prediction.dispose();
}

runModel();
</script>

Real-Time Webcam Classification

<video id="webcam" autoplay playsinline width="224" height="224"></video>
<p id="result">Loading...</p>

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script>
const CLASS_NAMES = ['cat', 'dog', 'bird'];

async function main() {
  // Load model
  const model = await tf.loadLayersModel('tfjs_model/model.json');

  // Start webcam
  const video = document.getElementById('webcam');
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  video.srcObject = stream;

  // Classify every 500ms
  setInterval(async () => {
    const tensor = tf.browser.fromPixels(video)
      .resizeBilinear([224, 224])       // Resize to model input size
      .toFloat()
      .div(255.0)                       // Normalize to [0,1]
      .expandDims(0);                   // Add batch dimension (1,224,224,3)

    const predictions = await model.predict(tensor).data();
    const topIndex = predictions.indexOf(Math.max(...predictions));
    const confidence = (predictions[topIndex] * 100).toFixed(1);

    document.getElementById('result').textContent =
      `${CLASS_NAMES[topIndex]}: ${confidence}%`;

    tensor.dispose();
  }, 500);
}

main();
</script>

Tensor Operations in TF.js

// Creating tensors
const a = tf.tensor([1, 2, 3, 4], [2, 2]);
const b = tf.tensor([[5, 6], [7, 8]]);

// Operations
const sum  = a.add(b);
const prod = tf.matMul(a, b);

// Read values (async)
sum.print();
const values = await sum.data();   // Returns Float32Array
console.log(values);               // [6, 8, 10, 12]

// Always dispose to prevent memory leaks
a.dispose();
b.dispose();
sum.dispose();

Using Pre-built TF.js Models

// MobileNet — image classification (no conversion needed)
import * as mobilenet from '@tensorflow-models/mobilenet';

const model = await mobilenet.load();
const img   = document.getElementById('my-image');

const predictions = await model.classify(img);
predictions.forEach(p => {
  console.log(`${p.className}: ${(p.probability * 100).toFixed(1)}%`);
});

// Other pre-built TF.js models:
// @tensorflow-models/coco-ssd       Object detection
// @tensorflow-models/pose-detection  Human pose estimation
// @tensorflow-models/face-detection  Face detection
// @tensorflow-models/hand-pose-detection  Hand tracking
// @tensorflow-models/toxicity        Toxic text classification
// @tensorflow-models/universal-sentence-encoder  Text embeddings

Training a Model in the Browser

// Train a simple model entirely in the browser
const model = tf.sequential({
  layers: [
    tf.layers.dense({ units: 64, activation: 'relu', inputShape: [10] }),
    tf.layers.dense({ units: 1, activation: 'sigmoid' })
  ]
});

model.compile({ optimizer: 'adam', loss: 'binaryCrossentropy' });

// Training data
const xs = tf.randomNormal([100, 10]);
const ys = tf.randomUniform([100, 1]).round();

await model.fit(xs, ys, {
  epochs: 10,
  callbacks: {
    onEpochEnd: (epoch, logs) =>
      console.log(`Epoch ${epoch}: loss=${logs.loss.toFixed(4)}`)
  }
});

// Save to browser's IndexedDB
await model.save('indexeddb://my-trained-model');

// Load back
const saved = await tf.loadLayersModel('indexeddb://my-trained-model');

Performance Tips for TF.js

Use tf.tidy() to automatically dispose intermediate tensors:
  const result = tf.tidy(() => {
    const a = tf.tensor([1, 2, 3]);
    const b = a.square();         // Intermediate — auto-disposed
    return b.add(1);              // Only return value is kept
  });

Use tf.memory() to debug memory leaks:
  console.log(tf.memory());
  // { numTensors: 5, numBytes: 4096 }

Process frames with requestAnimationFrame for smooth video:
  async function loop() {
    const result = classify(video);
    displayResult(result);
    requestAnimationFrame(loop);
  }

TensorFlow.js opens machine learning to the 3.5 billion people with a web browser. Privacy-preserving classification, interactive educational demos, and real-time video analysis all become possible without any backend infrastructure. The next topic covers model optimization — quantization, pruning, and other techniques that make models run faster and use less memory across all deployment platforms.

Leave a Comment

Your email address will not be published. Required fields are marked *