Confusion Matrix Heatmap — Matplotlib

A specialized heatmap visualization for evaluating classification model performance, displaying the counts or proportions of predicted vs actual class labels. The confusion matrix reveals true positives, false positives, true negatives, and false negatives at a glance, making it essential for understanding model behavior, identifying class imbalances, and diagnosing specific misclassification patterns.

Confusion Matrix Heatmap rendered with Matplotlib

Python source (Matplotlib)

""" anyplot.ai
confusion-matrix: Confusion Matrix Heatmap
Library: matplotlib 3.10.9 | Python 3.13.13
Quality: 89/100 | Updated: 2026-05-09
"""

import os

import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split


THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"

# Data - Iris classification
iris = load_iris()
X, y = iris.data, iris.target
class_names = iris.target_names

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Train classifier
clf = RandomForestClassifier(random_state=42)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

# Build confusion matrix
n_classes = len(class_names)
confusion_matrix = np.zeros((n_classes, n_classes))
for true_label, pred_label in zip(y_test, y_pred, strict=True):
    confusion_matrix[true_label, pred_label] += 1

# Plot
fig, ax = plt.subplots(figsize=(12, 12), facecolor=PAGE_BG)
ax.set_facecolor(PAGE_BG)

# Create heatmap using Blues colormap
im = ax.imshow(confusion_matrix, cmap="Blues", aspect="equal")

# Add colorbar with theme-adaptive styling
cbar = ax.figure.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
cbar.ax.tick_params(labelsize=16, colors=INK_SOFT)
cbar.ax.yaxis.set_tick_params(color=INK_SOFT)
cbar.set_label("Count", fontsize=18, color=INK)
for spine in cbar.ax.spines.values():
    spine.set_edgecolor(INK_SOFT)

# Set ticks and labels
ax.set_xticks(np.arange(n_classes))
ax.set_yticks(np.arange(n_classes))
ax.set_xticklabels(class_names, fontsize=18, color=INK_SOFT)
ax.set_yticklabels(class_names, fontsize=18, color=INK_SOFT)

# Rotate x-axis labels for readability
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")

# Annotate cells with counts and percentages
for i in range(n_classes):
    for j in range(n_classes):
        count = confusion_matrix[i, j]
        row_total = confusion_matrix[i, :].sum()
        if row_total > 0:
            percentage = count / row_total * 100
        else:
            percentage = 0

        # Choose text color based on background intensity
        text_color = "#FFFDF6" if count > confusion_matrix.max() * 0.5 else "#1A1A17"

        # Display count and percentage
        text = ax.text(
            j,
            i,
            f"{int(count)}\n({percentage:.1f}%)",
            ha="center",
            va="center",
            color=text_color,
            fontsize=16,
            fontweight="bold",
        )

# Grid lines between cells
ax.set_xticks(np.arange(n_classes + 1) - 0.5, minor=True)
ax.set_yticks(np.arange(n_classes + 1) - 0.5, minor=True)
ax.grid(which="minor", color=INK_SOFT, linestyle="-", linewidth=0.8, alpha=0.3)
ax.tick_params(which="minor", bottom=False, left=False)

# Spine styling
for spine in ("top", "right"):
    ax.spines[spine].set_visible(False)
for spine in ("left", "bottom"):
    ax.spines[spine].set_color(INK_SOFT)

# Labels and title
ax.set_xlabel("Predicted Label", fontsize=20, color=INK)
ax.set_ylabel("True Label", fontsize=20, color=INK)
ax.set_title(
    "Iris Classification · confusion-matrix · matplotlib · anyplot.ai",
    fontsize=24,
    fontweight="medium",
    color=INK,
    pad=20,
)

plt.tight_layout()
plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG)

Part of Confusion Matrix Heatmap on anyplot.ai.

Other implementations