Machine Learning Slides 📂 Introduction · 12 of 17 52 min read

Naive Bayes Classifier Explained — Bayes' Theorem, Variants, Smoothing & Log-Space

A visual, beginner-friendly guide to Naive Bayes — the probabilistic classifier that has powered spam filters and text categorisation for decades. Learn Bayes' theorem, the naive independence assumption, the three sklearn variants (Gaussian, Multinomial, Bernoulli), why we compute in log-space, Laplace smoothing to fix zero probabilities, worked spam examples, sklearn implementation and six golden rules.

🕵️

Naive Bayes Classifier

The probabilistic classifier that powered spam filters for two decades — Bayes' theorem, a wildly optimistic independence assumption, log-space arithmetic, and Laplace smoothing. Fast, tiny, and surprisingly hard to beat on text.
Bayes Theorem Naive Independence Spam Filter Classic Blazing Fast

Press Next → or use ← → arrow keys

Section 01

What Is Naive Bayes?

A doctor who asks about symptoms one at a time
A doctor sees a patient and asks: "How likely is flu, given a fever?" Then: "Given a cough?" Then: "Given fatigue?" She combines the answers, weights them by how common flu is in the population, and reaches a diagnosis. She does not ask "how often do fever + cough + fatigue appear together in flu patients?" — that combination might never have appeared in her records.

Naive Bayes works exactly this way. It computes the probability of each class one feature at a time, multiplies them (assuming they're independent), scales by the class prior, and picks the class with the highest score.
💡
The Working Definition

Naive Bayes is a probabilistic classifier that applies Bayes' theorem with a strong assumption: every feature contributes independently to the probability of the class. Absurd in theory, effective in practice.

P(y|x)Posterior probability
O(n)Training in one pass
3Variants — Gaussian · Multinomial · Bernoulli
2001SpamAssassin's engine
Section 02

Bayes' Theorem — The Whole Model In One Line

P(Class|Features) = P(Features|Class) · P(Class) P(Features) POSTERIOR what we want "probability of this class" "given what we observed" LIKELIHOOD learned from data "how often these features" "appear inside this class" PRIOR class base rate "how common is this class" "before we saw anything"
✂️
The Denominator Cancels Out

When comparing classes for the same input, P(Features) is identical across every class — so it cancels. Naive Bayes only computes the numerator (likelihood × prior) for each class and picks the largest. This trick removes the hardest term from the math entirely.

Section 03

The "Naive" Assumption — Features Are Independent

❌ The Honest Way — JOINT need to observe every feature combination Class y x₁ x₂ x₃ P(x₁, x₂, x₃ | y) — every combo ✅ The Naive Way — INDEPENDENT one feature at a time · multiply Class y x₁ x₂ x₃ P(x₁|y) · P(x₂|y) · P(x₃|y)
🎭
A Lie That Works

In real text, the words "free" and "money" almost always appear together — they are not independent. Naive Bayes assumes they are anyway. This assumption is usually wrong but it collapses an impossible computation into a trivial one, and it turns out that the classifier still picks the right class most of the time.

Section 04

The Full Formula & Why We Live In Log-Space

Naive Bayes Prediction Rule
ŷ = argmaxy P(y) · ∏ P(xᵢ | y)
Score each class by multiplying prior × product of per-feature likelihoods. Pick the winner.
Log-Space Version (always use this)
log score = log P(y) + Σ log P(xᵢ | y)
Turns products into sums. Prevents numerical underflow when multiplying hundreds of tiny probabilities.
🔢
Multiplying 500 Probabilities In A Row Breaks Everything

A text of 500 words means 500 probabilities multiplied together. Each word probability might be around 0.001. Multiply five hundred of those and the result is effectively zero to a computer — underflow. The fix is universal: take the log of everything, add instead of multiply, and compare log-scores. sklearn handles this automatically.

⚖️
MAP Rule
maximum a posteriori
Compare posteriors across classes, pick the largest. Since P(x) cancels, only likelihood × prior matters.
📉
Log-Space
avoid underflow
Products become sums. log(a·b) = log(a) + log(b). Numerically stable even for long documents.
🎯
Argmax
winner takes all
Return the class with the highest log-score. Predicted probabilities can be recovered by softmax over the log-scores.
Section 05

Worked Example — Spam Or Ham?

Training: 10 emails · 5 spam · 5 ham. New email contains "free" and "winner", no "meeting".

FeatureP( · | Spam )P( · | Ham )
Prior — P(class)0.500.50
"free" present0.800.20
"winner" present0.600.10
"meeting" absent1.000.40
Spam score 0.240 0.50 × 0.80 × 0.60 × 1.00 = 0.240 Ham score 0.004 0.50 × 0.20 × 0.10 × 0.40 = 0.004 🚨 PREDICT: SPAM
🎯
Spam Score Is 60× Larger — Decision Is Emphatic

Multiply the prior by all three feature likelihoods for each class. Spam wins 0.240 to 0.004. The email is classified as spam with very high confidence. That's Naive Bayes in one calculation — no gradient descent, no iterations, no matrix inversions.

Section 06

Three Variants — Match The Distribution To Your Data

Gaussian NB continuous features learns μ, σ² per class age · glucose · BMI · income Multinomial NB count / TF-IDF features word counts per document spam · docs · reviews · topics Bernoulli NB binary present / absent 1 0 1 0 0 1 1 0 explicitly rewards absence short docs · flags · presence
⚠️
Match The Variant To Your Feature Type

Using Multinomial NB on continuous data, or Gaussian NB on word counts — the model still runs, but silently gives worse answers. Continuous → Gaussian. Word counts → Multinomial. Binary flags → Bernoulli. This is the single most common Naive Bayes mistake.

Section 07

Gaussian NB — Two Bell Curves, One Decision

Glucose level (mg/dL) → density P(x | class) → 80 100 140 180 Healthy · μ=100 Diabetic · μ=160 new patient · glucose = 130 P(130 | Diabetic) is HIGHER → predict Diabetic
🔔
One Bell Per Class Per Feature

For each continuous feature, Gaussian NB fits a bell curve to each class. To classify a new point, it reads the height of every class's bell at the observed value, multiplies by the priors, and picks the tallest score. Elegant, fast, exact — as long as the features really are bell-shaped.

Section 08

Laplace Smoothing — The Zero-Probability Rescue

What if a word never appeared in a class during training? Its likelihood is exactly zero, and one zero in the product wipes the whole class out — regardless of every other feature.

❌ WITHOUT smoothing P("winner"|Ham) = 0/5 = 0.00 Spam 0.240 Ham 0.000 Ham eliminated — one zero destroyed everything ✅ WITH Laplace α=1 P("winner"|Ham) = (0+1)/(5+3) = 0.125 Spam 0.235 Ham 0.006 Ham stays comparable — decision still spam, honestly
Without smoothing
P(word | Class) = count / N
One zero destroys the entire class probability. Fragile.
Laplace / Additive Smoothing
P(word | Class) = (count + α) / (N + α · V)
Add α (usually 1) to every count. V = vocabulary size. No probability can ever be zero.
🛡️
Always Enable Smoothing

α=1.0 is the safe default and almost always enabled in libraries. Tune α on a log grid (0.01 – 2.0) via cross-validation for the last bit of performance. Setting α=0 silently reintroduces the zero-frequency trap.

Section 09

Advantages — Why Naive Bayes Still Ships

Blazing Fast
Training is a single pass over the data — just count. Inference multiplies pre-computed probabilities. Millions of predictions per second.
📉
Tiny Data Friendly
Works with just a few hundred samples per class. No gradient descent, no early stopping, no epochs.
📚
Text ML Baseline
Scales trivially to millions of sparse features. The classic first-model for spam, sentiment, topic classification.
📏
No Scaling Required
Probabilities are unit-free. Gaussian NB learns per-feature μ and σ; scale differences don't matter.
🔍
Interpretable Probabilities
You can read every P(word|class) from the trained model and explain each decision word-by-word.
🎯
Great Baseline
If a fancy model can't beat Naive Bayes by a meaningful margin, the fancy model has a problem — not the data.
Section 10

Disadvantages — Where It Falls Short

🎭
Independence Lie
features correlate
"Free" and "money" always co-occur — NB treats them as independent, double-counting evidence.
📊
Poor Calibration
confidence too extreme
Predicted probabilities cluster near 0 and 1. Not trustworthy for risk-scored decisions without calibration.
🚫
No Feature Interactions
by design
Cannot capture "X only matters when Y is present." For interaction-heavy problems use trees or boosting.
🔔
Gaussian Only If Bell-Shaped
skew ruins it
Gaussian NB breaks on heavily skewed or multi-modal continuous features. Log-transform first, or switch variant.
🥉
Beaten On Most Tabular
by boosting
On rich tabular data, gradient boosting and logistic regression usually win. NB shines on text and small data.
📝
Bag-Of-Words Only
order ignored
"Dog bites man" and "man bites dog" look identical to NB. For sequence-sensitive problems, use RNNs / transformers.
Section 11

Where Naive Bayes Wins In Production

📧
Email Spam Filtering
The classic use case. Runs at wire-speed inside mail servers, easily retrains on user feedback.
💬
Sentiment Analysis
Product reviews, social media firehose, brand monitoring. Multinomial NB on TF-IDF is a strong baseline.
🩺
Medical Diagnosis
Symptom-to-disease screening when patient records are sparse. Interpretable probabilities help clinicians.
📰
News & Topic Categorisation
Sports · Business · Politics · Tech. Handles many classes gracefully; new categories retrain quickly.
🌐
Language Detection
Character-n-gram features feed multinomial NB — a few hundred bytes are enough to classify a language.
📥
Real-Time Streaming ML
Incremental updates via partial_fit. Ideal when data arrives continuously and models must stay fresh.
🥇
The Text-First Family Rule

For any text classification project, start with Multinomial Naive Bayes on TF-IDF. It takes ten lines of code, trains in seconds, and sets the accuracy floor every deeper model must clear before being worth the complexity.

Section 12

Implementation — Sklearn In A Handful Of Lines

from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.calibration import CalibratedClassifierCV

# ── Continuous features (glucose, BMI, age) ─────
gnb = GaussianNB()
gnb.fit(X_train, y_train)

# ── Text classification — the classic combo ─────
spam_pipe = Pipeline([
    ('tfidf', TfidfVectorizer(ngram_range=(1, 2), min_df=2)),
    ('nb',    MultinomialNB(alpha=1.0)),           # Laplace smoothing on
])
spam_pipe.fit(emails_train, labels_train)
print(spam_pipe.predict_proba(["Free winner prize!!"]))

# ── Binary presence/absence flags ───────────────
bnb = BernoulliNB(alpha=1.0).fit(X_train_binary, y_train)

# ── Fix over-confident probabilities ────────────
calibrated = CalibratedClassifierCV(spam_pipe, method='isotonic', cv=5)
calibrated.fit(emails_train, labels_train)

# ── Streaming / online learning ─────────────────
mnb = MultinomialNB()
for batch_X, batch_y in stream:
    mnb.partial_fit(batch_X, batch_y, classes=[0, 1])
🧪
Two Non-Negotiable Steps For Text

Wrap the vectoriser and classifier in a Pipeline so cross-validation refits both per fold (no leakage). Wrap in CalibratedClassifierCV when you need honest probability estimates for decisions or thresholds. Skipping either leaves accuracy or trust on the table.

Section 13

Common Pitfalls — What Silently Sinks Naive Bayes

🚫
Wrong Variant
the #1 mistake
Gaussian NB on word counts, Multinomial on continuous data. Match variant to feature type — always.
0️⃣
Disabled Smoothing
α = 0 silent failure
One unseen word → whole class score collapses to zero. Keep α ≥ 0.01. Default 1.0 is safe.
📊
Trusting Raw Probabilities
poor calibration
NB probabilities cluster at 0 and 1. Wrap in CalibratedClassifierCV before using for risk decisions.
🔢
Underflow
from-scratch bug
Multiplying hundreds of probabilities gives 0.0. Always compute in log-space. sklearn does this for you.
🔗
Correlated Features
double-counting
Highly correlated features (bigrams of the same trigram) inflate one class's score. Deduplicate or use ngram tuning.
📉
Skipping α Tuning
leaving accuracy on the table
Default α = 1 is safe but rarely optimal. Sweep [0.01, 0.1, 1, 2] via CV — often a 1–3% boost.
Section 14

Golden Rules — Six Habits For Naive Bayes

🕵️ NAIVE BAYES DISCIPLINE
1
Match the variant to your feature type. Continuous → Gaussian. Word counts / TF-IDF → Multinomial. Binary presence flags → Bernoulli. Mismatch = silently wrong probabilities.
2
Always keep Laplace smoothing on. Default α = 1 is safe. Tune α across a log grid via cross-validation for the last bit of performance. Never disable it.
3
Use it as your mandatory baseline for text. If BERT can't beat MultinomialNB + TF-IDF by a meaningful margin, the fancy model isn't earning its latency or compute cost.
4
Do the arithmetic in log-space. Products of hundreds of small probabilities underflow to zero. Sums of logs are numerically stable. sklearn handles this; custom code must remember.
5
Calibrate before you trust probabilities. NB scores are extreme by construction. Wrap in CalibratedClassifierCV when the number matters — thresholds, cost-sensitive decisions, ranking.
6
Accept the independence lie — but check accuracy, not calibration. The independence assumption is violated in almost every real dataset. Classification accuracy usually survives. Probabilities usually don't. Judge NB on the metric that matches your use case.
FINAL

Naive Bayes — Simple, Fast, Surprisingly Sharp

P(y|x)Bayes' theorem in one line
∏ P(xᵢ|y)Independent feature product
3Variants for 3 data types
α=1Laplace saves the day
logSpace that avoids underflow
6Golden rules
🎯
The Foundation Is Set

You now understand Bayes' theorem, the naive independence assumption, the three sklearn variants, log-space arithmetic, and Laplace smoothing. Naive Bayes is the tiny, embarrassingly-fast classifier that still wins on text — and the baseline every other model has to beat before deployment.

📚
Where To Go Next

Study Logistic Regression next — same probabilistic framing, no independence assumption. Then Linear SVM for max-margin text classification, and Calibration curves to fix NB's probability quirk. Practise on Kaggle's Spam Detection or IMDB Sentiment datasets.

🕵️ End of tutorial · Press to review, or click Restart