CUB-200 Birds - Species Confusion Map
A TMAP of the CUB-200 dataset (11,788 images, 200 species) built from ResNet-50 embeddings (cosine metric). 81.5% of tree edges connect birds from the same family, with mean subtree purity of 0.761 by family but only 0.430 by species - fine-grained species distinctions are far less visually separable than broad taxonomic groups. The most visually similar species pairs are Caspian Tern <-> Elegant Tern (74 shared edges), Indigo Bunting <-> Blue Grosbeak (66), and Scarlet Tanager <-> Summer Tanager (66). Morphological paths trace routes between distantly related species, such as Ruby-throated Hummingbird to Belted Kingfisher in 37 hops crossing 11 species and 4 families.
This demo is hosted externally
The dataset is too large to embed inline. Opens in a new tab.
Open Interactive DemoHow it was made
from tmap import TMAP
from tmap.graph.analysis import boundary_edges, subtree_purity
model = TMAP(metric="cosine", n_neighbors=15, seed=42).fit(resnet50_embeddings)
# Family-level vs species-level boundaries
family_be = boundary_edges(model.tree_, bird_families)
species_be = boundary_edges(model.tree_, species_labels)
print(f"Same-family edges: {len(model.tree_.edges) - len(family_be)} / {len(model.tree_.edges)}")
# Species purity is much lower than family purity - fine-grained species
# are visually harder to separate than broad taxonomic families
family_purity = subtree_purity(model.tree_, bird_families, min_size=10)
species_purity = subtree_purity(model.tree_, species_labels, min_size=10)
# Most visually similar species pair: Caspian Tern <-> Elegant Tern
path = model.path(caspian_tern_idx, elegant_tern_idx)