Plotly How to make an annotated confusion matrix using a heatmap?
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
An annotated confusion matrix is just a heatmap with the cell values written on top of the colors. Plotly is a good fit for this because it gives you hover labels, custom color scales, and easy axis labeling without much boilerplate.
The main tasks are straightforward: compute the confusion matrix, pass it to a heatmap trace, and provide text annotations so each cell shows the exact count or normalized value.
Build the Matrix from Predictions
Start by computing the confusion matrix from your true and predicted labels.
That produces a two-dimensional array that Plotly can render directly.
If you want percentages instead of raw counts, normalize first:
Counts and normalized values are both useful. Counts show absolute errors, while normalized values make class imbalance easier to see.
Create an Annotated Heatmap with Plotly
The simplest modern pattern is to use plotly.graph_objects.Heatmap and provide a text matrix plus texttemplate.
Two details matter here:
- the y-axis is reversed so the first actual label appears at the top in the conventional matrix layout
- '
texttemplatewrites the annotation directly inside each cell'
This is often cleaner than manually placing one annotation object per cell.
Show Counts and Percentages Together
A common improvement is to show both values in the same cell.
This is especially useful in multiclass problems where raw counts alone can hide the relative quality of each row.
Improve Readability for Larger Label Sets
As the number of classes grows, readability becomes the main challenge.
Helpful layout tweaks:
For long class names, rotate the x-axis labels and widen the figure rather than shrinking the font until it becomes unreadable.
If the matrix is very large, consider interactive hover-only values with lighter in-cell text, or show only normalized values in the text layer.
Common Pitfalls
The most common mistake is mixing up the axes. Be explicit about whether rows are actual labels and columns are predicted labels, then label the axes accordingly.
Another common issue is forgetting to reverse the y-axis. Plotly heatmaps start from the bottom by default, which can make the matrix look upside down compared with the usual machine learning presentation.
People also normalize incorrectly. If you want per-class recall-style normalization, divide each row by its row sum. If you want global proportions, divide by the full matrix sum. Those are different visual stories.
Finally, avoid adding dozens of manual annotation objects unless you need very custom placement. text plus texttemplate is simpler and easier to maintain.
Summary
- Compute the confusion matrix first, then pass it directly to a Plotly heatmap.
- Use
textandtexttemplateto annotate each cell. - Reverse the y-axis for the conventional confusion matrix layout.
- Decide whether you want raw counts, normalized values, or both.
- Adjust figure size and tick labels for multiclass readability.
- Be explicit about which axis is actual and which is predicted.
Related reading
- Plotting a 2D heatmap
- Plotting a list of x, y coordinates
- Plotting a pie chart out of a dictionary
- Plotting a ROC curve in scikit yields only 3 points
- Plotting in a non-blocking way with Matplotlib
- Plotting numpy array using Seaborn
- Plotting decision boundary for High Dimension Data
- plotting spectrogram in audio analysis
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.