Foundations Updated 2026-09 View as Markdown

TensorFlow.js Transfer Learning Tutorial

Transfer learning allows you to take a pre-trained model and adapt it for your specific use case with minimal training data.

Transfer Learning with TensorFlow.js#

Transfer learning allows you to take a pre-trained model and adapt it for your specific use case with minimal training data. This is one of the most powerful techniques in modern machine learning.

What You'll Learn#

  • Understanding transfer learning concepts
  • Using pre-trained models as feature extractors
  • Fine-tuning existing models for custom datasets
  • Building image classifiers with minimal data
  • Real-time webcam classification

Installation#

javascript
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/knn-classifier"></script>

1. Understanding Transfer Learning#

javascript
<script>
function explainTransferLearning() {
  const explanation = `
    <h4>๐Ÿง  Transfer Learning Explained:</h4>
    <div style="background: #f0f8ff; padding: 20px; border-radius: 8px; margin: 15px 0;">
      <h5>What is Transfer Learning?</h5>
      <p>Transfer learning uses knowledge from a pre-trained model (trained on millions of images) 
      and applies it to your specific task with just a few examples.</p>
      
      <h5>Why is it Powerful?</h5>
      <ul>
        <li><strong>Less Data:</strong> Need only 10-20 examples per class</li>
        <li><strong>Faster Training:</strong> Minutes instead of hours/days</li>
        <li><strong>Better Results:</strong> Leverages proven feature extraction</li>
        <li><strong>Lower Compute:</strong> Runs in browser without GPU</li>
      </ul>
      
      <h5>How it Works:</h5>
      <ol>
        <li>Load pre-trained MobileNet (trained on ImageNet)</li>
        <li>Remove the final classification layer</li>
        <li>Use it as a feature extractor</li>
        <li>Train a simple classifier on extracted features</li>
      </ol>
    </div>
  `;
  
  document.getElementById('explanation-output').innerHTML = explanation;
}

explainTransferLearning();
</script>
<div id="explanation-output"></div>

2. Feature Extraction with MobileNet#

javascript
<script>
let mobilenet;
let isModelLoaded = false;

async function loadMobileNet() {
  const statusDiv = document.getElementById('mobilenet-status');
  statusDiv.innerHTML = '<p>๐Ÿ”„ Loading MobileNet for feature extraction...</p>';
  
  try {
    mobilenet = await tf.loadLayersModel('https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/4/default/1', {fromTFHub: true});
    isModelLoaded = true;
    statusDiv.innerHTML = '<p>โœ… MobileNet loaded! Ready for feature extraction.</p>';
    console.log('MobileNet loaded for transfer learning');
  } catch (error) {
    console.log('Using alternative loading method...');
    // Alternative: Use the mobilenet package
    mobilenet = await mobilenet.load({version: 2, alpha: 1.0});
    isModelLoaded = true;
    statusDiv.innerHTML = '<p>โœ… MobileNet loaded via alternative method!</p>';
  }
}

async function extractFeatures(imageElement) {
  if (!isModelLoaded) {
    throw new Error('MobileNet not loaded yet');
  }
  
  // Preprocess image
  const tensor = tf.browser.fromPixels(imageElement)
    .resizeNearestNeighbor([224, 224])
    .toFloat()
    .div(255.0)
    .expandDims();
  
  // Extract features (remove last classification layer)
  let features;
  if (mobilenet.predict) {
    // Using the layers model
    features = mobilenet.predict(tensor);
  } else {
    // Using mobilenet package - get intermediate activations
    features = mobilenet.infer(tensor, 'conv_preds');
  }
  
  tensor.dispose();
  return features;
}

async function demonstrateFeatureExtraction() {
  if (!isModelLoaded) {
    await loadMobileNet();
  }
  
  const output = document.getElementById('features-output');
  output.innerHTML = '<p>๐Ÿ”„ Extracting features from sample images...</p>';
  
  // Create sample images
  const images = [
    'https://images.unsplash.com/photo-1546598300-f5d62e0b7b9b?w=224&h=224&fit=crop',
    'https://images.unsplash.com/photo-1495052384700-271d7c5f5e8c?w=224&h=224&fit=crop',
    'https://images.unsplash.com/photo-1503803548695-c2a7b4a5b875?w=224&h=224&fit=crop'
  ];
  
  const labels = ['Dog', 'Cat', 'Car'];
  
  let resultHTML = '<h4>Feature Extraction Results:</h4>';
  resultHTML += '<div style="display: flex; gap: 15px; flex-wrap: wrap;">';
  
  for (let i = 0; i  {
      img.onload = async () => {
        try {
          const features = await extractFeatures(img);
          const featureVector = features.dataSync();
          
          resultHTML += `
            <div style="border: 1px solid #ddd; padding: 10px; border-radius: 8px; text-align: center;">
              <img src="${images[i]}" width="100" height="100" style="object-fit: cover; border-radius: 4px;">
              <h6>${labels[i]}</h6>
              <p>Features: ${featureVector.length}D vector</p>
              <p>Sample values: [${featureVector.slice(0, 3).map(v => v.toFixed(3)).join(', ')}...]</p>
            </div>
          `;
          
          features.dispose();
          resolve();
        } catch (error) {
          console.error('Feature extraction failed:', error);
          resolve();
        }
      };
      img.src = images[i];
    });
  }
  
  resultHTML += '</div>';
  resultHTML += '<p><em>These feature vectors can now be used to train a custom classifier!</em></p>';
  
  output.innerHTML = resultHTML;
}

loadMobileNet();
</script>

<div id="mobilenet-status"></div>
<button onclick="demonstrateFeatureExtraction()" 
        style="padding: 10px 20px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; margin: 10px 0;">
  Extract Features from Sample Images
</button>
<div id="features-output"></div>

3. K-Nearest Neighbors Classifier#

javascript
<script>
let knnClassifier;
let customModel = {
  mobilenet: null,
  knn: null,
  isReady: false
};

async function initializeKNN() {
  const output = document.getElementById('knn-output');
  output.innerHTML = '<p>๐Ÿ”„ Initializing KNN classifier...</p>';
  
  try {
    // Load MobileNet for feature extraction
    customModel.mobilenet = await mobilenet.load();
    
    // Initialize KNN classifier
    customModel.knn = knnClassifier.create();
    customModel.isReady = true;
    
    output.innerHTML = `
      <div style="background: #e8f5e8; padding: 15px; border-radius: 8px;">
        <h4>โœ… Custom Classifier Ready!</h4>
        <p>You can now train your own image classifier by adding examples below.</p>
        <p><strong>Instructions:</strong></p>
        <ol>
          <li>Click "Add Example" buttons to train on different categories</li>
          <li>Add at least 3-5 examples per category</li>
          <li>Test your classifier with new images</li>
        </ol>
      </div>
    `;
    
    setupTrainingInterface();
  } catch (error) {
    output.innerHTML = '<p>โŒ Error initializing classifier. Please refresh and try again.</p>';
    console.error('KNN initialization error:', error);
  }
}

function setupTrainingInterface() {
  const container = document.getElementById('training-interface');
  container.innerHTML = `
    <div style="border: 2px solid #ddd; padding: 20px; border-radius: 8px; margin: 20px 0;">
      <h4>๐ŸŽฏ Train Your Custom Classifier</h4>
      
      <div style="margin: 15px 0;">
        <h5>Category 1: Dogs</h5>
        <button onclick="addTrainingExample(0, 'https://images.unsplash.com/photo-1546598300-f5d62e0b7b9b?w=224')" 
                style="padding: 8px 16px; background: #FF9800; color: white; border: none; border-radius: 4px; margin: 5px;">
          Add Dog Example 1
        </button>
        <button onclick="addTrainingExample(0, 'https://images.unsplash.com/photo-1548199973-03cce0bbc87b?w=224')" 
                style="padding: 8px 16px; background: #FF9800; color: white; border: none; border-radius: 4px; margin: 5px;">
          Add Dog Example 2
        </button>
        <button onclick="addTrainingExample(0, 'https://images.unsplash.com/photo-1561037404-61cd46aa615b?w=224')" 
                style="padding: 8px 16px; background: #FF9800; color: white; border: none; border-radius: 4px; margin: 5px;">
          Add Dog Example 3
        </button>
        <span id="dog-count" style="margin-left: 10px; font-weight: bold;">Examples: 0</span>
      </div>
      
      <div style="margin: 15px 0;">
        <h5>Category 2: Cats</h5>
        <button onclick="addTrainingExample(1, 'https://images.unsplash.com/photo-1495052384700-271d7c5f5e8c?w=224')" 
                style="padding: 8px 16px; background: #9C27B0; color: white; border: none; border-radius: 4px; margin: 5px;">
          Add Cat Example 1
        </button>
        <button onclick="addTrainingExample(1, 'https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba?w=224')" 
                style="padding: 8px 16px; background: #9C27B0; color: white; border: none; border-radius: 4px; margin: 5px;">
          Add Cat Example 2
        </button>
        <button onclick="addTrainingExample(1, 'https://images.unsplash.com/photo-1516728778615-2d590ea185ee?w=224')" 
                style="padding: 8px 16px; background: #9C27B0; color: white; border: none; border-radius: 4px; margin: 5px;">
          Add Cat Example 3
        </button>
        <span id="cat-count" style="margin-left: 10px; font-weight: bold;">Examples: 0</span>
      </div>
      
      <div style="margin: 20px 0; padding: 15px; background: #f9f9f9; border-radius: 6px;">
        <h5>๐Ÿงช Test Your Classifier</h5>
        <button onclick="testClassifier('https://images.unsplash.com/photo-1543466835-00a7907e9de1?w=224')" 
                style="padding: 8px 16px; background: #2196F3; color: white; border: none; border-radius: 4px; margin: 5px;">
          Test Dog Image
        </button>
        <button onclick="testClassifier('https://images.unsplash.com/photo-1519052537078-e6302a4968d4?w=224')" 
                style="padding: 8px 16px; background: #2196F3; color: white; border: none; border-radius: 4px; margin: 5px;">
          Test Cat Image
        </button>
      </div>
    </div>
    
    <div id="training-results"></div>
  `;
}

let dogCount = 0;
let catCount = 0;

async function addTrainingExample(classId, imageUrl) {
  if (!customModel.isReady) {
    alert('Model not ready yet. Please wait...');
    return;
  }
  
  const resultsDiv = document.getElementById('training-results');
  resultsDiv.innerHTML = '<p>๐Ÿ”„ Adding training example...</p>';
  
  try {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    
    img.onload = async () => {
      // Get features from MobileNet
      const features = customModel.mobilenet.infer(img, true);
      
      // Add example to KNN classifier
      customModel.knn.addExample(features, classId);
      
      // Update counters
      if (classId === 0) {
        dogCount++;
        document.getElementById('dog-count').textContent = `Examples: ${dogCount}`;
      } else {
        catCount++;
        document.getElementById('cat-count').textContent = `Examples: ${catCount}`;
      }
      
      resultsDiv.innerHTML = `
        <p>โœ… Added example for ${classId === 0 ? 'Dogs' : 'Cats'}! 
        Total examples: Dogs(${dogCount}), Cats(${catCount})</p>
      `;
      
      features.dispose();
    };
    
    img.src = imageUrl;
  } catch (error) {
    resultsDiv.innerHTML = '<p>โŒ Error adding example. Please try again.</p>';
    console.error('Training error:', error);
  }
}

async function testClassifier(imageUrl) {
  if (!customModel.isReady) {
    alert('Model not ready yet. Please wait...');
    return;
  }
  
  if (dogCount === 0 || catCount === 0) {
    alert('Please add training examples for both categories first!');
    return;
  }
  
  const resultsDiv = document.getElementById('training-results');
  resultsDiv.innerHTML = '<p>๐Ÿง  Classifying image...</p>';
  
  try {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    
    img.onload = async () => {
      // Extract features
      const features = customModel.mobilenet.infer(img, true);
      
      // Classify
      const prediction = await customModel.knn.predictClass(features);
      
      const className = prediction.label === '0' ? 'Dog' : 'Cat';
      const confidence = Object.values(prediction.confidences);
      const maxConfidence = Math.max(...confidence) * 100;
      
      resultsDiv.innerHTML = `
        <div style="background: #e3f2fd; padding: 15px; border-radius: 8px; margin: 10px 0;">
          <h4>๐ŸŽฏ Classification Result</h4>
          <div style="display: flex; align-items: center; gap: 15px;">
            <img src="${imageUrl}" width="100" height="100" style="object-fit: cover; border-radius: 4px;">
            <div>
              <p><strong>Prediction: ${className}</strong></p>
              <p>Confidence: ${maxConfidence.toFixed(1)}%</p>
              <p>Dog: ${(prediction.confidences['0'] * 100).toFixed(1)}%</p>
              <p>Cat: ${(prediction.confidences['1'] * 100).toFixed(1)}%</p>
            </div>
          </div>
        </div>
      `;
      
      features.dispose();
    };
    
    img.src = imageUrl;
  } catch (error) {
    resultsDiv.innerHTML = '<p>โŒ Error classifying image. Please try again.</p>';
    console.error('Classification error:', error);
  }
}

// Initialize when page loads
initializeKNN();
</script>

<div id="knn-output"></div>
<div id="training-interface"></div>
Exercise

Try it

ready

Get the JavaScript agent pack

A battle-tested AGENTS.md, the review checklist, and the failure-mode cheat sheet for JavaScript. One email, then occasional updates when the tooling shifts. No course pitch.

Unsubscribe in one click. We never sell the list. Or just take the AGENTS.md now โ€” no email needed.