Visual walkthrough — t-SNE for visualization
We will keep one running mental image: dots on a table (2D) that we are allowed to slide around, trying to copy the friendship pattern of dots living in a room we cannot see (high-D).
Step 1 — Turn "distance" into "how surprised am I to see you as a neighbor"
WHAT. We start with points living in a high-dimensional space. A point is just a list of numbers (a data sample); the bold letter means "a whole arrow of coordinates," not one number. The squared distance between two of them is
Read as "the length of the arrow between them," and squaring it just avoids a square root — it grows fast when points are far. That is all the raw material we have.
WHY. Raw distance is not comparable across a dataset: near a dense clump, "5 units away" is far; in a sparse region it is close. So instead of distance we ask a softer question: "If point threw a dart, how likely is it to land on ?" Nearby points should be hit often, far ones rarely.
PICTURE. In figure s01 the bell curve is centered on point ; its height at is the similarity. Two things live here:
- — the bell: tall for close , tiny for far . The minus sign flips "far" into "small."
- — the width of the bell around point (why it uses the Gaussian shape: it is the smoothest, maximum-entropy bump that only cares about distance). Wide bell = many neighbors count; narrow = only the very closest.
- The bottom sum over all other — normalization: it forces to be a genuine probability that adds to across all .
- The bar in reads " given " — this bell belongs to alone.

Step 2 — Make the friendship two-way (symmetrize)
WHAT. Point 's bell may be narrow while 's is wide, so . We blend them:
- — average the two one-sided views so friendship is mutual.
- — divide so that all together sum to ( is the number of points). Now is a single joint distribution over pairs.
WHY. Two reasons. (1) An outlier with a huge bell would otherwise get ignored — averaging guarantees every point has at least some voice in the joint table. (2) A symmetric makes the later gradient clean and force-like (Newton's third law: the pull of on equals the pull of on ).
PICTURE. In figure s02, two overlapping bells of different widths; the final is the shared, symmetric bridge between the two peaks.

Neighbor asymmetry fixed by averaging?
Step 3 — Choose the bell's width by perplexity, not by hand
WHAT. We never set directly. Instead we pick one number, perplexity, and let each point find its own to match it. Perplexity is
- — the entropy (in bits) of point 's neighbor distribution: how "spread out" its friendships are. All weight on one neighbor → ; weight spread evenly over neighbors → .
- — undoes the , so perplexity reads as "effective number of neighbors." Perplexity 30 ≈ "each point cares about roughly 30 friends."
WHY. Density varies across data. A fixed would drown dense regions and starve sparse ones. Fixing the number of neighbors instead adapts the width automatically. A binary search shrinks or grows until the entropy hits the target.
PICTURE. Figure s03: same point, three bell widths, three entropy readings — see how a wider bell raises entropy and thus perplexity.

Step 4 — Copy the pattern on the table with a heavier-tailed curve
WHAT. Now the low-D dots on our 2D table. We need their pair-probability . Crucially, is built to be a single symmetric joint distribution — one number per pair that, summed over all ordered pairs , equals — so it can sit next to the joint from Step 2 inside the KL cost. We do not reuse the Gaussian; we use the Student t-distribution with 1 degree of freedom:
- — the t-kernel for the pair : near distance it is ; as distance grows it fades, but far more slowly than the Gaussian's exponential drop.
- The bottom sum runs over every ordered pair (not just neighbors of one point). Call this single number the partition constant
Because the same divides every , the whole table is one joint distribution with and — exactly the shape needed to compare against . (Contrast Step 1's , which was conditional: normalized per point . Here there is only one global normalizer.)
WHY — the crowding problem. In high-D you can pack many points all equally near a center; in 2D there simply isn't room, so they get crushed together. Using a curve with a heavy tail means moderately-far points still register meaningful similarity, so the optimizer is content to leave them spread out instead of piling them on top of each other.
PICTURE. Figure s04 overlays the Gaussian and the t-kernel . Watch the t-curve refuse to hit zero — that stubborn tail is what buys empty space between clusters.

Is conditional or joint?
Step 5 — Measure the mismatch with KL divergence
WHAT. We want (table) to look like (room). Their disagreement is scored by the cost
- — per-pair surprise: when , positive when the table under-represents a true friendship.
- — each surprise is weighted by how important the true pair is. Weak true pairs () barely matter.
WHY this direction, not ? Look at the two failure modes:
- A true-close pair placed far apart ( big, tiny) → is huge → heavily punished.
- A true-far pair placed close ( tiny, big) → the leading mutes it → barely punished.
That asymmetry is exactly the priority we want: never tear neighbors apart; tolerate a little accidental crowding. This is why KL divergence — a directional comparison of distributions — is the right tool instead of a symmetric distance.
PICTURE. Figure s05 plots the per-pair penalty against the ratio : a steep cliff on the "torn apart" side (), a gentle slope on the "too close" side ().

Step 6 — Turn the cost into a force (the gradient)
WHAT. Differentiating with respect to each dot's position gives the direction to slide it:
WHY does this exact form appear — including the normalizer ? Moving one dot changes every low-D distance it takes part in, and — because (Step 4) sums over all pairs — it also nudges the single global normalizer. Figure s06 traces this dependency chain. It is cleanest to write the un-normalized kernel , so with . Then
- The first term comes from the numerator inside its own .
- The second term is the contribution of the shared : since appears in every 's denominator, its derivative collects a piece from all pairs. But (both and are joint distributions), so that whole sum collapses to the clean constant .
Feeding this back and using , the pieces recombine into , and the algebra folds into the boxed result. So the normalizer does not vanish by magic — it is exactly what turns the raw numerator term into the difference . Read term by term the result is a spring:
- — sign of the force. Positive (: friends too far) → pull together. Negative (: strangers too close) → push apart.
- — direction along the joining line.
- — the t-weight, softening the force for distant pairs so nothing explodes.
- The — the two factors of (one from , one because each pair appears twice in the symmetric sum) combined; it only scales the step.

WHY. Gradient descent slides each a little opposite to this force each iteration; repeat and the table settles into the shape whose best matches . Early exaggeration temporarily multiplies every by ~4, over-inflating true friendships so clusters snap apart cleanly early on, then relaxes for fine tuning.
Step 7 — Degenerate & edge cases you must expect
WHAT / WHY / PICTURE, all gathered in figure s07, because these are the traps:
- Identical points (): distance , bell height , so is maximal — fine. In 2D the t-kernel is also (finite!), so no division by zero — a hidden gift of the form.
- A lone outlier far from everyone: every bell height is tiny, but normalization renormalizes them, so its still sums to 1. Symmetrization (Step 2) then rescues it from being ignored.
- Between-cluster gaps are meaningless. Because only near neighbors drives the layout, the width of empty space between two clusters is set by the t-tail and initialization, not by true distance. Never read global distances off a t-SNE plot (see parent [!mistake] notes).
- Very low-D input (say 3–5 features): there is no crowding to fix, so t-SNE mostly adds noise — prefer scatter plots or clustering directly.

The one-picture summary
Figure s08 compresses the whole pipeline into one annotated diagram: distances → Gaussian in high-D → random dots on table → t-kernel (one global ) → KL mismatch → spring forces → repeat, with the two data-worlds (unseen room vs. touchable table) drawn side by side and the feedback loop of forces shown as a curved arrow.

Recall Feynman retelling — say it to a friend
Imagine dots in a room you can't enter. Each dot puts a soft bell over itself; where the bell is tall, another dot is a close friend. That gives a friendship table . Now scatter matching dots on a table you can touch. Give them a friendship rule too — but a stretchier one (the t-curve), and divide every pair by one shared total so the table is a single honest distribution. Compare the two tables with a one-way ruler, KL divergence, that screams if you tear real friends apart but only whispers if strangers drift close. That scream becomes little springs: real friends too far apart get pulled together, strangers too close get pushed away. The shared total is exactly what turns each raw pull into the tidy difference "wanted minus actual." Nudge, re-measure, nudge again — a thousand times. When the table stops complaining, you've drawn a map that keeps neighbors as neighbors. Just don't trust the empty space between the clusters — that gap is decoration, not distance.
Recall Key clozes
- t-SNE builds high-D similarities with a Gaussian kernel and low-D similarities with a t-distribution (heavy tails).
- is a conditional distribution (normalized per point); is a joint distribution (one global normalizer over all pairs).
- The cost minimized is the KL divergence , chosen because it punishes tearing neighbors apart far more than accidental crowding.
- Perplexity sets the effective number of neighbors via .
- The gradient acts like springs: decides pull vs push; the shared is what produces the term.
See also: 2.5.10 UMAP (faster, preserves more global structure), 3.2.1 Autoencoders and 2.5.9 Manifold Learning (parametric alternatives), Hinglish version.