t-SNE (t-distributed Stochastic Neighbor Embedding) is a nonlinear dimensionality reduction method for visualization: it places high-dimensional points in 2D or 3D so that neighborhoods are preserved. It excels at revealing cluster structure but is a visualization tool, not a general feature transform.

Pairwise Affinities (High Dim)

For each point define a conditional probability that would pick as a neighbor under a Gaussian centered at :

The bandwidth is set per point so the neighborhood has a target size (see perplexity). Symmetrize to .

Student-t in Low Dim

In the low-dimensional map, similarities use a Student-t distribution with one degree of freedom (a Cauchy), which has heavy tails:

KL Objective

The map is found by minimizing the Kullback-Leibler divergence between the high-dim and low-dim affinities via Gradient Descent:

Because KL is asymmetric, a large modeled by a small (nearby points placed far apart) is heavily penalized, so t-SNE prioritizes preserving local structure over global distances.

Perplexity

Perplexity sets the effective number of neighbors each targets:

Typical values are 5 to 50. Small perplexity emphasizes very local structure; large perplexity blends broader neighborhoods.

The Crowding Problem

In high dimensions there is far more room for a point to have many roughly-equidistant neighbors than in 2D. A Gaussian low-dim kernel would force moderately distant points to crush together. The heavy-tailed Student-t fixes this: it allocates more room at moderate distances, letting clusters spread out and separate cleanly.

Contrast with PCA and UMAP

AspectPCAt-SNEUMAP
Typelinearnonlinearnonlinear
Preservesglobal variancelocal neighborhoodslocal + some global
Deterministicyesno (random init)no
Speedfastslowfaster than t-SNE
New-point maptrivial (project)not nativelysupports transform

A common pipeline runs PCA first (to ~50 dims) to denoise and speed things up, then t-SNE for the final 2D plot.

sklearn Usage

from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
 
X50 = PCA(n_components=50).fit_transform(X)     # denoise / speed up
emb = TSNE(
    n_components=2,
    perplexity=30,
    learning_rate="auto",
    init="pca",
    random_state=0,
).fit_transform(X50)

Pitfalls

  • Cluster sizes and inter-cluster distances in a t-SNE plot are NOT meaningful; do not read them as real densities or gaps.
  • Results depend on perplexity and the random seed; try several settings before trusting a picture.
  • t-SNE does not learn a reusable mapping for new data (use UMAP or a parametric model if you need that).
  • Do not feed t-SNE coordinates into a downstream classifier; it is for visualization only.