EMNIST - Character Confusion Map

20,000 imagesMLcomputer-visionOCR

A TMAP of 20,000 EMNIST handwritten characters (47 classes: digits and letters) using raw pixel vectors with cosine metric. 70.6% of tree edges connect the same character, rising to 84.3% when grouped by visual shape family. The most confused pairs are '0'<->'O' (654 edges), 'F'<->'f' (538), '1'<->'L' (534), and '9'<->'q' (450) - classic OCR ambiguities. Subtree purity is 0.575 by exact character but 0.748 by shape group. Digits and letters mostly stay separated (86.8% same-type edges), and confusion paths trace exactly how the model gets from one character to a visually similar one, e.g. '0' to 'D' in 21 hops via 'O'.

This demo is hosted externally

The dataset is too large to embed inline. Opens in a new tab.

Open Interactive Demo

How it was made

generate.pypython
from tmap import TMAP
from tmap.graph.analysis import boundary_edges, subtree_purity, path_properties

model = TMAP(metric="cosine", n_neighbors=15, seed=42).fit(pixel_vectors)

# Character-level vs shape-group vs digit/letter boundaries
char_be = boundary_edges(model.tree_, characters)
shape_be = boundary_edges(model.tree_, shape_groups)
type_be = boundary_edges(model.tree_, digit_or_letter)

# OCR confusion path: '0' -> 'D' through 'O'
path = model.path(zero_idx, d_idx)
route = path_properties(model.tree_, zero_idx, d_idx, characters)