JavaScript: a naive Bayes text classifier

Naive Bayes classifies by Bayes' rule. The posterior probability of a class is proportional to its prior times the probability of the observed words given the class. The naive assumption is that words are independent given the class. It is false for real language, but the classifier often works well anyway.

JavaScript
const training = [
  ["spam", "win money now"],
  ["spam", "win a prize now"],
  ["ham", "meeting at noon"],
  ["ham", "lunch at noon now"],
];

const counts = { spam: new Map(), ham: new Map() };
const docs = { spam: 0, ham: 0 };
const vocabulary = new Set();
for (const [label, text] of training) {
  docs[label]++;
  for (const word of text.split(" ")) {
    vocabulary.add(word);
    counts[label].set(word, (counts[label].get(word) ?? 0) + 1);
  }
}

function score(label, text) {
  const total = [...counts[label].values()].reduce((a, b) => a + b, 0);
  let logProbability = Math.log(docs[label] / training.length);
  for (const word of text.split(" ")) {
    const seen = counts[label].get(word) ?? 0;
    logProbability += Math.log((seen + 1) / (total + vocabulary.size));
  }
  return logProbability;
}

for (const message of ["win prize now", "lunch meeting"]) {
  const spam = score("spam", message);
  const ham = score("ham", message);
  console.log(message + " -> " + (spam > ham ? "spam" : "ham") + " (spam " + spam.toFixed(2) + ", ham " + ham.toFixed(2) + ")");
}
Read the full lesson