Naive Bayes › Visualizing Naive Bayes

Michael BrenndoerferOctober 26, 20265 min read
Machine Learning from ScratchAll chapters
Part 7 of 15Supervised Learning Beyond Linear Models
Chapter 54Naive Bayes › Visualizing Naive Bayes
Reading section 5 of 10 · Visualizing Naive Bayes · 5 minSection 5 of 10 · 5 min

Section 5 of 10 · 5 min read

Naive Bayes › Visualizing Naive BayesSection view · Sections in this chapter5 / 10 ↓
Reading tools Definitions, links & notes

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Notes & comments

The first figure shows decision regions of a two-dimensional Gaussian naive Bayes classifier. Each class gets its own mean and variance for each feature. The background color is the predicted probability of class 1. The decision boundary is where the two class scores tie. Because the class variances differ, the boundary can curve. The model is not using the correlation between the two features; it fits two separate one-dimensional Gaussians per class.

PythonIn [5]
CollapseExpand
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy.special import logsumexp
from sklearn.calibration import calibration_curve
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score, brier_score_loss, log_loss
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB, MultinomialNB

# Generate a two-feature, two-class problem for the decision-region figure.
X_vis, y_vis = make_classification(
    n_samples=300,
    n_features=2,
    n_informative=2,
    n_redundant=0,
    n_classes=2,
    n_clusters_per_class=1,
    class_sep=1.2,
    flip_y=0.02,
    random_state=42,
)

clf_vis = GaussianNB().fit(X_vis, y_vis)

# Build a grid over the feature space and compute the predicted probability
# of class 1 at each grid point for the decision-region figure.
x_min, x_max = X_vis[:, 0].min() - 0.5, X_vis[:, 0].max() + 0.5
y_min, y_max = X_vis[:, 1].min() - 0.5, X_vis[:, 1].max() + 0.5
xx, yy = np.meshgrid(
    np.linspace(x_min, x_max, 300),
    np.linspace(y_min, y_max, 300),
)
grid = np.column_stack([xx.ravel(), yy.ravel()])
Z = clf_vis.predict_proba(grid)[:, 1].reshape(xx.shape)
VisualizationOut [6]
CollapseExpand
Scatter plot of two classes with a smooth curved decision boundary and background shading from blue to red representing the predicted probability of class 1.
Gaussian naive Bayes decision regions for a two-feature, two-class problem. The background shading is the predicted probability of class 1, and the dashed curved boundary shows where the two class scores tie. Each class is modeled with a separate one-dimensional Gaussian for each feature, so the model ignores correlation between the features, and the boundary is curved rather than straight because the class variances differ.

Subtracting the two Gaussian log scores gives a quadratic expression without feature cross-products. Equal corresponding class variances cancel the quadratic terms, leaving a linear score difference. Unequal variances can produce curved boundaries, as in this fitted example. The shape is restricted, however: the model cannot represent a boundary that depends on a nonlinear interaction between the features beyond what the squared terms allow. If the true classes were arranged in a checkerboard pattern, this model would struggle.

The second figure examines calibration. A classifier is calibrated if, among all observations assigned a predicted probability of 0.80.8, about 80%80\% actually belong to the positive class. Naive Bayes is not guaranteed to satisfy this property. When features are correlated, the model treats them as independent evidence and can become overconfident. The simulation below creates two features that carry nearly the same information. The model treats these strongly overlapping measurements as separate evidence.

PythonIn [7]
CollapseExpand
# Simulate a latent score, its binary label, and two nearly collinear features.
rng = np.random.default_rng(7)
n_cal = 5000

z = rng.normal(size=n_cal)
p_true = 1.0 / (1.0 + np.exp(-2.0 * z))
y_cal = rng.binomial(1, p_true)

# Feature 2 is almost a copy of feature 1, so the independence assumption fails.

x1 = z + 0.45 * rng.normal(size=n_cal)
x2 = x1 + 0.08 * rng.normal(size=n_cal)
X_cal = np.column_stack([x1, x2])

X_train_cal, X_test_cal, y_train_cal, y_test_cal = train_test_split(
    X_cal, y_cal, test_size=0.5, random_state=7, stratify=y_cal
)

clf_cal = GaussianNB().fit(X_train_cal, y_train_cal)

# Predict on the held-out split and collect calibration diagnostics.
p_hat_cal = clf_cal.predict_proba(X_test_cal)[:, 1]

prob_true, prob_pred = calibration_curve(
    y_test_cal, p_hat_cal, n_bins=10, strategy="quantile"
)
brier_cal = brier_score_loss(y_test_cal, p_hat_cal)
ConsoleOut [8]
CollapseExpand
Brier score on the simulated test set: 0.184
VisualizationOut [9]
CollapseExpand
Reliability diagram comparing mean predicted probability with observed positive frequency. The naive Bayes curve lies below the perfect-calibration diagonal at high predicted probabilities.
Reliability diagram for Gaussian naive Bayes on a simulated problem with two highly correlated features. The dashed diagonal is perfect calibration. The naive Bayes points fall below the diagonal at high predicted probabilities, indicating overconfidence: the model predicts more certainty than the observed labels support. This diagnostic does not isolate the contribution of feature dependence from other model misspecification.

The reliability diagram is a diagnostic, not a proof. In this simulation, the two features are nearly collinear, so the independence assumption is badly violated. The class-conditional marginals are not guaranteed to be Gaussian either, so this single curve does not isolate the effect of dependence. The model can still separate the classes, but its probabilities are not trustworthy as estimates of risk. If we needed calibrated probabilities, we would apply a post-hoc calibration method such as Platt scaling or isotonic regression, which we will discuss in Part XII: Calibration and Prediction Uncertainty.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy