Naive Bayes — Probabilistic Text Classification
Bayes theorem applied to classification. Why the naive independence assumption works surprisingly well for spam filters and document classification.
A new email arrives. It contains the words "free", "win", "cash", "claim". How do you know it is spam before reading it fully?
You have seen thousands of emails before. From that experience you know: the word "free" appears in 80% of spam emails but only 5% of legitimate ones. "Win" appears in 70% of spam but 2% of legitimate. "Meeting" appears in 0.1% of spam but 40% of legitimate.
When a new email arrives, you look at the words it contains and ask: given these words, what is the probability this email is spam? You combine the evidence from each word to get an overall probability. If the probability of spam is above 50% you classify it as spam. That is the entire Naive Bayes algorithm.
The "naive" part is an assumption: we treat each word as independent. The presence of "free" and the presence of "cash" in the same email are treated as if they provide completely separate, unrelated evidence. In reality these words are correlated — spam emails often contain both. The assumption is wrong. But it simplifies the math enormously and somehow still works very well in practice.
A doctor diagnosing a patient. The patient has three symptoms: fever, cough, and fatigue. The doctor looks up: how common is fever in patients with flu? How common is cough? How common is fatigue? The doctor combines all three answers — treating each symptom as independent evidence — to reach a diagnosis.
In reality fever, cough, and fatigue are not independent — they often come together in flu. But treating them as independent gives a good enough estimate of "how likely is this flu vs cold vs allergies?" That is the naive assumption, and it works because the errors in each direction often cancel out.
Bayes theorem — update your belief when you see evidence
Bayes theorem (from Module 08) says: the probability of a hypothesis given evidence equals the probability of the evidence given the hypothesis, times the prior probability of the hypothesis, divided by the probability of the evidence. Written in plain English:
How likely is this email spam, given the words I see? equals How likely are these words in a spam email? times How common is spam overall? divided by How likely are these words in any email?
The naive extension — combining multiple features
An email has many words, not just one. To combine evidence from all words we use the naive independence assumption: the probability of seeing all the words together in a spam email equals the product of their individual probabilities. This is the "naive" assumption — words are treated as independent of each other.
We compute this for every class and pick the class with the highest value.
In practice: use log probabilities to avoid numerical underflow from multiplying many small numbers.
Three variants — one for each type of feature
"Naive Bayes" is not one algorithm — it is a family. The difference between variants is only in how they model P(feature | class) — the likelihood of seeing each feature value in each class. The right choice depends on what type of features you have.
Laplace smoothing — why a zero probability destroys everything
Imagine a word that appears in test data but never appeared in any spam email in training. Without smoothing, its probability given spam is exactly 0. When you multiply all word probabilities together — which is what Naive Bayes does — a single zero makes the entire product zero. One unseen word makes it impossible to classify the email as spam, no matter how many other spam indicators it contains.
Laplace smoothing (also called additive smoothing) fixes this by adding a small count to every word — even words that never appeared. Adding 1 to every word count (alpha=1) ensures no probability is ever exactly zero. The vocabulary expands to include all possible words, each with a small non-zero count.
GaussianNB — Naive Bayes for continuous features
When features are continuous numbers — like delivery distance, order value, or customer age — you cannot count occurrences. GaussianNB assumes each feature follows a Gaussian (normal) distribution within each class. During training it learns the mean and variance of each feature for each class. During prediction it computes how likely the observed feature value is given each class's Gaussian distribution.
Day-one task — build a DoorDash review sentiment classifier
Your first week at DoorDash's data team. The product manager asks: "Can you automatically classify customer reviews as positive or negative so we can route negative ones to customer support immediately?" 250,000 reviews per month. You need something fast, accurate enough, and deployable by end of week. Naive Bayes is the right answer.
Every common Naive Bayes error — explained and fixed
Five things people get wrong about Naive Bayes
The assumption — that every feature is conditionally independent given the class — is almost never literally true, and yet Naive Bayes routinely performs competitively on text classification. The reason is that classification only needs the model to rank the correct class highest, not to estimate the exact probability correctly. Correlated features get counted multiple times by the naive model, which distorts the magnitude of the posterior probability, but that distortion is often applied roughly equally across classes, so the ordering of which class scores highest survives even though the probabilities themselves are off. In practice this means Naive Bayes can make the right prediction while reporting a probability that is badly wrong — a subtlety worth stating explicitly rather than assuming a wrong assumption means a wrong answer.
Because Naive Bayes multiplies per-feature likelihoods together, correlated features effectively get counted more than once, which systematically pushes the winning class's posterior probability toward the extremes — predictions cluster near 0.99 or 0.01 even when the model's actual class-ranking confidence is much more modest. This is a calibration problem, not an accuracy problem: the predicted class is often correct, but the probability attached to it should not be read literally as "how likely this is." Any use case that depends on the probability value itself — risk scoring, ranking by confidence, deciding a threshold based on expected cost — needs a calibration step like CalibratedClassifierCV before those numbers can be trusted.
Without smoothing, any word that never appeared in a class during training gets an estimated likelihood of exactly zero for that class. Because Naive Bayes multiplies likelihoods together across every feature, one zero anywhere in that product makes the whole product zero — no matter how strongly every other word in the message points to that class. A single unseen word in a test example can silently make an entire class impossible to predict, which is a much bigger failure than a small accuracy hit. Laplace (additive) smoothing adds a small count to every possible feature value specifically to prevent this, which makes it closer to a mandatory correctness fix than an optional hyperparameter.
Naive Bayes earned its reputation on text — high-dimensional, sparse, mostly-independent word-count features are exactly the setting where the independence assumption does the least damage. On tabular numeric data with a handful of strongly correlated features, the same assumption causes real problems: correlated features get double-counted, and algorithms that model feature interactions directly, like logistic regression or gradient-boosted trees, usually win by a wide margin. The right lesson is not "Naive Bayes is good" or "Naive Bayes is bad" in general, but that its strength is tied to a specific data shape, and it should be picked for that reason rather than reached for by default.
They belong to two different families of models entirely. Naive Bayes is generative — it models how the data is produced, learning P(features given class) and P(class) separately and combining them with Bayes' theorem to get a prediction. Logistic Regression is discriminative — it skips modeling the data distribution altogether and directly learns P(class given features). This difference has real consequences: Naive Bayes needs less data to reach its typically higher asymptotic error rate because it makes stronger assumptions, which is why it can outperform Logistic Regression on small datasets and lose to it as data grows. A generative model can also do things a discriminative one cannot, like generate plausible synthetic examples of each class, because it actually models what the data looks like rather than only the decision boundary between classes.
Naive Bayes — 5 questions interviewers actually ask
For a new example, I want the class that maximizes P(class given features). Bayes' theorem rewrites that as P(features given class) times P(class), divided by P(features) — and since P(features) is the same for every class being compared, I can ignore it and just compare P(features given class) times P(class) across classes. The naive part is assuming the features are conditionally independent given the class, which lets P(features given class) collapse into a simple product of individual per-feature likelihoods, each of which is easy to estimate from training data by counting. In practice I compute this in log space — summing log-likelihoods instead of multiplying raw probabilities — to avoid numerical underflow from multiplying many small numbers together, then pick whichever class has the highest total.
Classification is a ranking problem, not a probability-estimation problem — the model only needs to put the correct class ahead of the others, not report the exact right probability. Violating independence distorts the magnitude of the computed posterior, often pushing it toward more extreme values than it should be, but that distortion tends to apply in a similar direction across classes, so the relative ordering — and therefore the predicted class — often survives even when the reported confidence does not. This is also why Naive Bayes does especially well on text: word features in a document are numerous, individually weak, and only mildly correlated with each other, which is close to the best-case scenario for this assumption to be a tolerable approximation rather than a fatal one.
Laplace, or additive, smoothing adds a small constant, usually one, to every feature count before computing probabilities, and adds a corresponding amount to the normalizing total so everything still sums to one. Without it, any feature value that never appeared for a given class during training gets a likelihood of exactly zero, and because Naive Bayes multiplies likelihoods across all features, a single zero anywhere collapses the entire product to zero regardless of how much other evidence supports that class. That is not a small accuracy cost, it is a correctness bug — it means the model can never predict a class if the test example happens to contain even one word it did not see paired with that class during training. Smoothing is typically treated as a hyperparameter to tune with cross-validation, but some nonzero amount of it is required for the model to behave sensibly at all.
A generative model learns the joint distribution of features and labels — effectively, what data from each class tends to look like — and derives the classification decision from that using Bayes' theorem. A discriminative model skips modeling the data distribution and directly learns the decision boundary, the conditional probability of the label given the features. The practical trade-off is a bias-variance one: Naive Bayes makes a strong independence assumption, which gives it higher bias but lower variance, so it tends to need less data to reach a decent error rate and can outperform Logistic Regression when training data is scarce. Logistic Regression makes fewer assumptions and can model feature interactions and correlations that Naive Bayes cannot, so it typically overtakes Naive Bayes in accuracy as the training set grows large enough for that flexibility to pay off.
I would avoid it whenever features are strongly correlated and the correlation itself carries predictive signal — think tabular business data where features like income and credit limit move together in ways that matter to the outcome. Naive Bayes will double-count that correlated evidence and typically underperforms Logistic Regression or a tree ensemble like Random Forest or XGBoost in that setting. I would also avoid it if I needed well-calibrated probabilities out of the box, since Naive Bayes' probability estimates skew toward extreme values without a calibration step. Where I would still reach for it: high-dimensional sparse text or count data, situations needing a fast, cheap, easily-retrained baseline, or genuinely small training sets where its stronger assumptions help rather than hurt.
You have now covered every major classical ML algorithm. Next: ensemble methods that combine them.
Linear Regression, Logistic Regression, Decision Trees, SVM, KNN, Naive Bayes — six algorithms, six different philosophies. Linear regression fits a line. Logistic regression finds a probability boundary. Decision trees grow a flowchart. SVMs maximise a margin. KNN asks its neighbours. Naive Bayes applies Bayes theorem. Each has a domain where it wins.
Module 28 — Random Forest — combines hundreds of decision trees through a technique called bagging. Each tree is trained on a random subset of data with a random subset of features. Their predictions are averaged. The result consistently beats any single tree on almost every tabular dataset. It is one of the first algorithms you should reach for in production.
Bagging, random feature subsets, out-of-bag evaluation, and why Random Forest beats a single tree on every real dataset.
🎯 Key Takeaways
- ✓Naive Bayes uses Bayes theorem to compute the probability of each class given the input features. It picks the class with the highest posterior probability. The "naive" part is treating each feature as independent — wrong in theory, works well in practice.
- ✓Three variants for three feature types: MultinomialNB for word counts and text (most common), BernoulliNB for binary presence/absence features especially in short texts, GaussianNB for continuous numeric features.
- ✓Laplace smoothing (alpha parameter) is essential. Without it, a single word that never appeared in training causes the entire probability to become zero. Alpha=1.0 is standard. Tune it with cross-validation — alpha=0.1 often outperforms the default on text.
- ✓Naive Bayes is one of the fastest ML algorithms — training is a single pass to count frequencies. Prediction is a few multiplications. For high-volume real-time classification (spam, sentiment, support ticket routing) it is often the most practical choice.
- ✓The independence assumption makes Naive Bayes probabilities overconfident — predictions cluster near 0 and 1. When you need calibrated probabilities, post-process with CalibratedClassifierCV(method="isotonic").
- ✓Naive Bayes genuinely wins for text classification with small datasets, real-time requirements, or high-dimensional sparse features. For tabular numeric data with strong feature correlations, Logistic Regression or Random Forest almost always outperforms it.
Discussion
0Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.