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.
