MACHINE LEARNING

How to Build Deep Personalized Recommendation Systems Using Neural Networks in JavaScript

Go beyond traditional algorithms—use neural networks and TensorFlow.js to create highly personalized recommendation engines in the browser.

🧠 Why Use Neural Networks?

Traditional recommender systems use linear similarity scores or matrix factorization. Neural networks allow us to:

  • Capture non-linear patterns in user-item interactions
  • Use multiple features (genre, time, age, clicks)
  • Train end-to-end on raw data
  • Enable deep personalization at scale

⚙️ What We’ll Build

A Neural Collaborative Filtering (NCF) model in JavaScript using TensorFlow.js.

This model:

  • Takes a user ID and item ID
  • Learns embeddings for both
  • Passes them through hidden layers
  • Predicts rating or interaction score

🗃️ Step 1: Sample Dataset

const ratings = [
  { user: 0, item: 0, rating: 5 },
  { user: 0, item: 2, rating: 3 },
  { user: 1, item: 1, rating: 4 },
  { user: 1, item: 3, rating: 5 }
];

const numUsers = 2;
const numItems = 4;
const embeddingDim = 8;

🧱 Step 2: Define the Model

const tf = require('@tensorflow/tfjs-node');

function createModel(numUsers, numItems, embeddingDim) {
  const userInput = tf.input({ shape: [1], name: 'user' });
  const itemInput = tf.input({ shape: [1], name: 'item' });

  const userEmbedding = tf.layers.embedding({
    inputDim: numUsers,
    outputDim: embeddingDim
  }).apply(userInput);

  const itemEmbedding = tf.layers.embedding({
    inputDim: numItems,
    outputDim: embeddingDim
  }).apply(itemInput);

  const merged = tf.layers.concatenate().apply([
    tf.layers.flatten().apply(userEmbedding),
    tf.layers.flatten().apply(itemEmbedding)
  ]);

  const dense1 = tf.layers.dense({ units: 32, activation: 'relu' }).apply(merged);
  const dense2 = tf.layers.dense({ units: 16, activation: 'relu' }).apply(dense1);
  const output = tf.layers.dense({ units: 1 }).apply(dense2);

  return tf.model({ inputs: [userInput, itemInput], outputs: output });
}

🔁 Step 3: Prepare the Data

const userTensor = tf.tensor1d(ratings.map(r => r.user), 'int32');
const itemTensor = tf.tensor1d(ratings.map(r => r.item), 'int32');
const labelTensor = tf.tensor2d(ratings.map(r => r.rating), [ratings.length, 1]);

🚀 Step 4: Train the Model

const model = createModel(numUsers, numItems, embeddingDim);

model.compile({
  optimizer: tf.train.adam(0.01),
  loss: 'meanSquaredError'
});

async function train() {
  await model.fit([userTensor, itemTensor], labelTensor, {
    epochs: 200,
    batchSize: 2,
    callbacks: {
      onEpochEnd: (epoch, logs) => {
        if (epoch % 50 === 0) {
          console.log(`Epoch ${epoch}: loss = ${logs.loss.toFixed(4)}`);
        }
      }
    }
  });
}

🎯 Step 5: Make Predictions

async function recommendForUser(userId, topN = 2) {
  await train();
  const items = Array.from({ length: numItems }, (_, i) => i);
  const userInput = tf.tensor1d(items.map(() => userId), 'int32');
  const itemInput = tf.tensor1d(items, 'int32');

  const preds = model.predict([userInput, itemInput]);
  const scores = await preds.data();

  const recommendations = items
    .map((itemId, i) => ({ itemId, score: scores[i] }))
    .sort((a, b) => b.score - a.score)
    .slice(0, topN);

  console.log(`Top recommendations for User ${userId}:`, recommendations);
}

🧠 Why This is Powerful

  • Embeddings are learned automatically during training
  • Dense layers model complex relationships
  • Easily add side information (user age, item category, etc.)
  • Great for large sparse datasets

📦 Bonus: Add Contextual Features

Want to personalize based on time of day, location, or device?

Add them as additional inputs:

// Add categorical or numeric inputs like: 
// tf.input({shape: [1]}) -> embed or normalize -> concatenate into model

✅ Summary

With Neural Collaborative Filtering, you’ve built:

  • A full deep learning model for recommendation
  • End-to-end training and prediction in JavaScript
  • A scalable framework for real-time, personalized recommendations

Leave a Reply

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