Structure
The question: two things a projection routinely gets wrong that no rank-based measure notices.
Density preservation
Section titled “Density preservation”t-SNE and UMAP both inflate sparse regions and compress dense ones by construction. Every local neighbourhood survives — so trustworthiness is delighted — while the statement “this cluster is denser than that one” becomes unreadable from the plot.
densityPreservation correlates each point’s local radius in the data — its mean
distance to its densityK nearest neighbours — with its local radius in the
projection. The correlation is taken over the logs of those radii, so it reads
density ratios rather than absolute sizes. A point whose radius is zero in either
space — it coincides with all densityK of its nearest neighbours — has no log, and is
dropped from the correlation rather than clamped to some floor. Both radius arrays
still report it.
const a = analyze(hd, ld, { densityK: 20 });densityPreservation(a.structure).value; // 0.4271densityPreservation(a.structure, "spearman").value; // rank versionThe result also carries radiusHigh and radiusLow, the per-point radii themselves,
which are often more informative than the correlation.
Loading…
Two clusters, one tight and one diffuse, drawn at the same width. Trustworthiness 0.934, continuity 0.939 — the neighbourhoods are all intact. Density preservation 0.374: the contrast is gone.
Triplet accuracy
Section titled “Triplet accuracy”Take three points. In the data, j is closer to i than k is. Is that still true
in the projection? Triplet accuracy is the fraction of triplets where it is.
This is the most direct formalisation of “can I read relative distances off this plot”, and unlike stress it is invariant to any monotone rescaling.
const a = analyze(hd, ld, { triplets: true });tripletAccuracy(a.structure).value; // 0.9560Reading these
Section titled “Reading these”Density preservation is a correlation in . Above about 0.8 means the
density structure is broadly kept; near 0 means the plot says nothing about density;
negative means it is actively inverted. It has localKind: "none" — a correlation
does not decompose per point — but the two radius arrays do the same job better.
Triplet accuracy is in with 0.5 as chance, because a triplet either
survives or does not and a coin gets half of them right. 0.75 is not “quite good”, it
is halfway to random. It has localKind: "mean", per anchor point.
An empty scatterplot.
- Triplet accuracy
- —
- parameters
- none
- points
- —
- cost
O(1)
Share of point triples whose relative ordering survives the projection.
Both read out of moments the pass has already collected. tripletAccuracy is then
over the per-row inversion counts; densityPreservation is for
"pearson", or for "spearman", which sorts the radii to rank them.
The collection itself is folded into the same sweep as everything else: densityK
adds a per-row radius, triplets: true adds one Fenwick inversion count per row.
Verification
Section titled “Verification”Both are checked against the published definition; there is no reference fixture for either. Density preservation’s radii are checked against an independent naive computation of the k-nearest-neighbour means, and the correlation itself against the invariances it must satisfy: exactly 1 for an identity projection, exactly 1 under a uniform rescaling, and a drop on a fixture where neighbourhoods survive but the density contrast is flattened. Triplet accuracy is verified against brute force over every triplet on small inputs, and against the sampling estimator it replaces on larger ones.
References
Section titled “References”- Narayan, Berger & Cho, Nature Biotechnology 39 (2021) densityPreservation
- Wang, Huang, Rudin & Shaposhnik, JMLR 22 (2021) tripletAccuracy