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