t-SNE vs PCA vs UMAP: Which Reveals True Clusters?
By MCP Analytics Team | Published , updated
PCA is a linear projection that keeps the directions of greatest variance, so its axes have a clear meaning. t-SNE and UMAP are nonlinear methods that keep each point's nearest neighbors close, so they can separate groups that PCA does not, but cluster sizes and the gaps between clusters in their plots should not be read as real distances.
A t-SNE plot can show tight, well-separated groups that a PCA plot of the same data does not. When that happens, the picture alone does not tell you which one to believe. PCA, t-SNE and UMAP are different methods. They optimize different objectives and can show different structures. This guide shows how to check what you see before you report it.
Worked Example (Simulated): Do the Groups Look Tighter in a Picture Than in the Data?
Question: If we know the groups in made-up data, how do PCA and t-SNE show them?
Inputs: Simulated data, seed 17. The script makes 180 rows with 8 features and 3 built-in groups. It scales each feature, then makes 2D PCA and t-SNE plots. PCA keeps 2 components. t-SNE uses perplexity 20, a PCA start, an automatic learning rate, 750 steps and seed 17. The silhouette score sums up how close each point is to its own group and how far it is from the other groups. Higher means tighter, more separate groups, but the score does not prove the groups are real.
Method: The script prints the share of input spread kept by 2D PCA. It then prints the silhouette score in the scaled 8-feature input and in each 2D plot, using the built-in group labels. It also prints t-SNE's KL divergence, the loss it minimizes.
import os
os.environ["LOKY_MAX_CPU_COUNT"] = "2"
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler
# Simulated data, seed 17
X, labels = make_blobs(
n_samples=180,
centers=3,
n_features=8,
cluster_std=2.3,
random_state=17,
)
X = StandardScaler().fit_transform(X)
pca = PCA(n_components=2, random_state=17)
X_pca = pca.fit_transform(X)
tsne = TSNE(
n_components=2,
perplexity=20,
init="pca",
learning_rate="auto",
max_iter=750,
random_state=17,
)
X_tsne = tsne.fit_transform(X)
print("data=make_blobs; seed=17; rows=180; features=8; centers=3; "
"cluster_std=2.3")
print("prep=StandardScaler; PCA=n_components:2; t-SNE=perplexity:20, "
"init:pca, learning_rate:auto, max_iter:750, seed:17")
print(f"PCA 2D variance share={pca.explained_variance_ratio_.sum():.3f}")
print(f"silhouette in scaled input space={silhouette_score(X, labels):.3f}")
print(f"silhouette in PCA 2D={silhouette_score(X_pca, labels):.3f}")
print(f"silhouette in t-SNE 2D={silhouette_score(X_tsne, labels):.3f}")
print(f"t-SNE KL divergence={tsne.kl_divergence_:.3f}")
Printed output:
data=make_blobs; seed=17; rows=180; features=8; centers=3; cluster_std=2.3
prep=StandardScaler; PCA=n_components:2; t-SNE=perplexity:20, init:pca, learning_rate:auto, max_iter:750, seed:17
PCA 2D variance share=0.700
silhouette in scaled input space=0.402
silhouette in PCA 2D=0.664
silhouette in t-SNE 2D=0.795
t-SNE KL divergence=0.419
Result: PCA keeps 0.700 of the input spread in 2D. The silhouette score is 0.402 in the scaled input, 0.664 in the PCA plot and 0.795 in the t-SNE plot. t-SNE's KL divergence is 0.419. Both pictures score higher than the input space does, so both make the groups look tighter than they are in 8 dimensions. A higher silhouette score in a picture is not proof the picture is more accurate. Distances in a t-SNE picture do not mean the same as distances in the data.
Limit: The data were made with built-in groups, so this run does not show that a plot can find true groups in real data. It is one seed and one setting of each method.
Sources
Cited for who published each method and when, not for any number on this page.
- Jolliffe I, Cadima J (2016). Principal component analysis: a review and recent developments. Philosophical Transactions of the Royal Society A. doi 10.1098/rsta.2015.0202
- van der Maaten L, Hinton G (2008). Visualizing Data using t-SNE. Journal of Machine Learning Research 9. jmlr.org/papers/v9/vandermaaten08a.html
- McInnes L, Healy J, Melville J (2018). UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction. arxiv.org/abs/1802.03426
- Rousseeuw P (1987). Silhouettes: a graphical aid to the interpretation and validation of cluster analysis. Journal of Computational and Applied Mathematics. doi 10.1016/0377-0427(87)90125-7
What Each Method Optimizes (And Why It Matters)
Treating these methods as generic "make my data 2D" tools is a mistake. Each one keeps different aspects of your data, so each one can mislead you in a different way.
PCA: Keeping the Directions With the Most Spread
PCA is a linear projection that keeps the directions with the most spread. The first principal component captures the most variance, the second captures the most remaining variance at a right angle to the first, and so on (Jolliffe and Cadima, 2016).
What PCA keeps: the directions of largest spread, which tend to carry the overall shape of the data.
What PCA can lose: local neighborhoods that do not line up with the directions of largest spread. If your data has a curved structure, a linear projection will flatten it.
t-SNE: Keeping Local Neighborhoods
t-SNE is nonlinear. It converts high-dimensional distances into probabilities, then finds a low-dimensional embedding that matches those probabilities (van der Maaten and Hinton, 2008). It uses a Gaussian for the high-dimensional side and a Student t distribution for the low-dimensional side.
What t-SNE keeps: neighborhoods. Points that are close together in the data are meant to stay close in the picture.
What t-SNE does not keep: distances between clusters and the relative sizes of clusters.
UMAP: Keeping Neighborhoods With a Different Method
UMAP is described in McInnes, Healy and Melville (2018). Like t-SNE it is nonlinear and keeps neighborhoods. Like t-SNE, it does not keep exact distances, and its output depends on its settings and on the seed.
Five Situations Where a t-SNE Plot Can Mislead
These are patterns to check for. They are not results from a data set on this page.
1. Random High-Dimensional Data
In high dimensions, distances between points become similar to each other. A method that keeps neighborhoods can then pick up small random differences and draw them as groups. The perplexity setting defines how large a "neighborhood" is, and some settings can make random variation look like structure.
Detection method: Generate random data with the same number of rows and columns as your real data. If t-SNE draws similar-looking groups from random data, do not trust the groups in your real data.
2. Smooth Gradients Read as Discrete Groups
A t-SNE plot of data that changes smoothly, such as cells moving from one state to another, can show separate islands. Those islands may be breakpoints in a continuous process.
Detection method: Compare t-SNE, UMAP and PCA. If PCA or UMAP shows a gradient where t-SNE shows islands, suspect the islands. Ask whether your categories are truly discrete or could be continuous.
3. The Perplexity Illusion
Perplexity controls how many neighbors t-SNE treats as local. Run the same data at several perplexity values and the number and size of groups can change. Which one is "true" depends on what scale of structure matters for your question.
Detection method: Run t-SNE at several perplexity values across a sensible range for your data size. Similar patterns across settings are one check. They do not by themselves show that the groups are real. If boundaries shift a lot, treat the groups as unsettled.
4. Density Differences Read as Clusters
If one region of the data is sampled sparsely and another densely, t-SNE can pull them apart even when both come from the same underlying distribution.
Detection method: Check whether apparent groups line up with differences in sampling density rather than differences in the data. Use silhouette scores or other cluster metrics computed in the original space, not in the embedding.
5. Outliers Changing the Picture
Extreme points have to fit into the same 2D space as everything else. They can change the layout of the main body of data and create artificial boundaries.
Detection method: Run t-SNE with and without extreme outliers. If the group structure changes a lot, handle the outliers separately and compare the result.
How Perplexity Changes What You See
Perplexity is a key t-SNE setting, and a single value gives a single view. If you run t-SNE with only one perplexity value, you have one view of the data.
Perplexity is loosely read as "how many neighbors should influence each point." Technically it is related to the entropy of the conditional probability distribution.
Smaller Perplexity: Focusing on Immediate Neighbors
Low perplexity shows fine-grained local structure. You may see many small, tight groups.
Risk: Random local variation can look like meaningful groups, especially with few points.
Larger Perplexity: Revealing Coarse Structure
High perplexity considers broader neighborhoods, so it shows larger-scale organization.
Risk: You can miss real fine-scale structure by averaging over many neighbors.
Three Uses That Fit t-SNE
t-SNE is useful when used for the right job. These are the jobs it fits.
High-Dimensional Data With Manifold Structure
t-SNE suits data that lies on or near a low-dimensional curved surface inside a high-dimensional space. Images of handwritten digits are a common example, where each digit class occupies its own region of pixel space.
Exploratory Analysis With Careful Checks
t-SNE is useful for generating hypotheses, not for confirming them. Use it to spot structure that might be worth testing, then test it with other methods. A workflow that does this:
- Run a clustering method such as k-means in the original feature space, not in the plot
- Compute silhouette scores in the original space
- Compare the cluster assignments with the groups you see in the t-SNE plot
- Check on a holdout set that the clusters hold up
- Test the clusters against a business outcome you care about
Looking at Known Groups
When you already know the labels, t-SNE can show whether those groups are separable in your feature space. This is different from discovering unknown clusters: you are looking at known structure, for example to see which labeled classes overlap.
Comparing Methods: PCA vs t-SNE vs UMAP
Which method to use depends on your data and your question. This table says what each method takes in and gives out. It does not rank them.
| Use Case | Method to Try | Why |
|---|---|---|
| Initial look, unknown structure | PCA first, then UMAP or t-SNE | PCA is a linear projection that keeps the directions with the most spread. t-SNE and UMAP are nonlinear and keep neighbourhoods. |
| Need to keep global distances | PCA or MDS | t-SNE does not keep distances between clusters. |
| Same result on every run | PCA | t-SNE and UMAP depend on a random start unless you fix the seed, and the result still depends on their settings. |
| Cluster discovery (no known labels) | All three, plus the checks below | Compare methods. Groups that appear across methods and settings are worth a closer look. Groups that appear in only one are not yet evidence. |
| Publication figure (single visualization) | Depends on your checks | Show the method that represents the structure you checked. Report the parameters used. |
Checklist: Testing If Your Clusters Are Real
Before you report clusters from any dimensionality reduction method, run through these checks.
1. Cross-Method Consistency
Test: Run PCA, t-SNE (at several perplexities) and UMAP. Note how many apparent clusters each one shows.
Look for: Similar groups across methods. If t-SNE shows many groups but PCA shows a continuous cloud, be skeptical.
Code example:
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import umap
# Run all three methods
pca = PCA(n_components=2)
pca_result = pca.fit_transform(data)
tsne_30 = TSNE(n_components=2, perplexity=30, random_state=42)
tsne_result_30 = tsne_30.fit_transform(data)
tsne_100 = TSNE(n_components=2, perplexity=100, random_state=42)
tsne_result_100 = tsne_100.fit_transform(data)
umap_reducer = umap.UMAP(n_neighbors=15, random_state=42)
umap_result = umap_reducer.fit_transform(data)
# Visually compare and count apparent clusters
2. Stability Across Random Seeds
Test: Run t-SNE several times with different random seeds. Measure how consistent the cluster assignments are using the Adjusted Rand Index (ARI).
Look for: ARI near 1 means the assignments agree from run to run. Low ARI means the boundaries move between runs.
from sklearn.metrics import adjusted_rand_score
from sklearn.cluster import KMeans
# Run t-SNE multiple times
results = []
labels_list = []
for seed in range(10):
tsne = TSNE(perplexity=30, random_state=seed)
embedding = tsne.fit_transform(data)
# Cluster the embedding
kmeans = KMeans(n_clusters=5, random_state=42)
labels = kmeans.fit_predict(embedding)
labels_list.append(labels)
results.append(embedding)
# Calculate pairwise ARI
for i in range(len(labels_list)-1):
ari = adjusted_rand_score(labels_list[i], labels_list[i+1])
print(f"ARI between run {i} and {i+1}: {ari:.3f}")
3. Silhouette Score in the Original Space
Test: Assign cluster labels, then calculate silhouette scores in the original high-dimensional space as well as in the embedding (Rousseeuw, 1987).
Look for: A gap between the two. In the worked example above, the silhouette score is 0.402 in the input space and 0.795 in the t-SNE plot. A higher score in the picture is not proof the picture is more accurate.
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
# Get cluster labels from t-SNE embedding
tsne = TSNE(perplexity=30, random_state=42)
embedding = tsne.fit_transform(data)
kmeans = KMeans(n_clusters=5, random_state=42)
labels = kmeans.fit_predict(embedding)
# Calculate silhouette score in ORIGINAL space
silhouette_orig = silhouette_score(data, labels)
print(f"Silhouette score in original space: {silhouette_orig:.3f}")
# Compare to silhouette score in embedded space
silhouette_embed = silhouette_score(embedding, labels)
print(f"Silhouette score in t-SNE space: {silhouette_embed:.3f}")
4. Null Model Comparison
Test: Generate random data with the same dimensions and sample size. Run t-SNE on both real and random data. Compare.
Look for: Real data that shows clearer separation than random data. If random data produces similar-looking groups, your results may be noise.
import numpy as np
# Generate random null data
random_data = np.random.randn(*data.shape)
# Run t-SNE on both
tsne_real = TSNE(perplexity=30, random_state=42)
embedding_real = tsne_real.fit_transform(data)
tsne_random = TSNE(perplexity=30, random_state=42)
embedding_random = tsne_random.fit_transform(random_data)
# Compare: random data should not show clear clusters
# If it does, your real clusters might be artifacts
5. Perplexity Sweep
Test: Run t-SNE at several perplexity values and track the number of apparent clusters at each value.
Look for: Similar patterns across a range of perplexities. They do not by themselves show that the groups are real, but large changes are a warning.
6. Downstream Task Check
Test: If you use clusters for a downstream purpose such as customer segmentation, test whether cluster membership relates to the outcomes you care about.
Look for: Differences between clusters on relevant metrics, such as retention or conversion.
Common Mistakes That Undermine Your Results
Mistake 1: Using Only One Method
If you only run t-SNE, you cannot tell whether the structure is real or an artifact. Compare multiple methods, the way you would replicate a finding.
Mistake 2: Counting Clusters by Eye
"I see 6 clusters" is not analysis. Use quantitative methods: k-means with the elbow method, hierarchical clustering with a dendrogram, DBSCAN, or silhouette analysis. Visual intuition finds clusters even in random data.
Mistake 3: Ignoring Preprocessing
t-SNE and UMAP are sensitive to feature scaling. A feature with a much larger variance than the others will dominate the distance calculations. Standardize or normalize features before embedding.
from sklearn.preprocessing import StandardScaler
# Running t-SNE on raw data with mixed scales
tsne = TSNE(perplexity=30)
embedding = tsne.fit_transform(raw_data)
# Standardize first
scaler = StandardScaler()
scaled_data = scaler.fit_transform(raw_data)
embedding = tsne.fit_transform(scaled_data)
Mistake 4: Using t-SNE for Clustering
t-SNE is for visualization, not clustering. The embedding distorts distances in ways that can mislead a clustering algorithm. If you want clusters, cluster in the original space (or a PCA-reduced space), then visualize with t-SNE.
Mistake 5: Cherry-Picking the Cleanest Run
Running t-SNE many times and showing only the cleanest picture is p-hacking, visual edition. Report typical results or show multiple runs. Variation across runs tells you how stable your structure is.
Mistake 6: Interpreting Distance Between Clusters
In t-SNE, the distance between clusters does not mean the same thing as distance in the data. Two clusters that appear far apart might be similar in the original space, and two that appear close might be distant.
Mistake 7: Using Tiny Sample Sizes
t-SNE on very few points will show groups, but they may well be noise. The number of points you need depends on the data and on the number of groups you expect, so check stability across seeds and settings.
A Workflow for Dimensionality Reduction Projects
Step 1: Start With PCA
Begin with PCA. Look at the scree plot: how much variance do the first few components capture? Then plot the first two or three components and see whether groups appear.
Step 2: Run UMAP or t-SNE for Nonlinear Structure
Compare the nonlinear picture to PCA. If they show similar overall structure, that is one sign of real organization. If they are very different, investigate before you draw conclusions.
Step 3: Use Multiple Perplexities
Run t-SNE with at least three perplexity values. Do the same groups appear across perplexities and across methods?
Step 4: Quantitative Checks
Run the checklist from the previous section:
- Stability across random seeds
- Silhouette scores in the original space
- Null model comparison (real data against random data)
Step 5: Domain Check
Do the clusters make sense? Can domain experts tell the clusters apart from the features? Do the clusters relate to relevant outcomes? Statistical checks are not enough on their own: you also want clusters that are meaningful, not just mathematically separable.
Step 6: Document Everything
Report all parameters used: perplexity values, random seeds and preprocessing steps. Report stability measures. Show multiple pictures, not just the cleanest one, so readers can replicate your analysis.
Advanced Considerations
Very Large Datasets
Standard t-SNE can become slow as the number of points grows. Options:
- Approximate methods: Use an approximate t-SNE implementation or UMAP.
- Random sampling: Run t-SNE on a representative subsample, then place the remaining points using nearest neighbors in the original space.
- Hierarchical approach: Cluster in the original space (for example with mini-batch k-means), then visualize cluster centroids with t-SNE.
Very High Dimensionality
In very high dimensions, distances between points become similar, which weakens distance-based methods. A common step is to reduce with PCA first, then apply t-SNE or UMAP. Check how much variance the PCA step keeps.
Non-Metric Data
t-SNE, UMAP and PCA assume you can compute meaningful distances between points. For categorical or structured data, you need a different first step:
- Categorical data: Use correspondence analysis or encode with embeddings (for example, entity embeddings for categorical variables)
- Graph data: Use graph embedding methods (node2vec, DeepWalk) before visualization
- Text data: Use text embeddings (word2vec, BERT) to convert to vectors first
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai
Frequently Asked Questions
t-SNE is designed to keep local neighborhoods, not global distances. Distances between clusters in a t-SNE plot do not mean the same as distances in the data: two clusters that appear far apart may be similar in the original space, and the reverse. If you need to keep global relationships, use PCA or MDS.
t-SNE optimizes a function with many local minima, and the result depends on the starting layout and the seed. Run it with several seeds. If your clusters change a lot between runs, treat them with caution.
There is no single right value. Try several values across a range that suits the size of your data set. Similar patterns across settings are one check. They do not by themselves show that the groups are real.
No. A higher silhouette score in a picture is not proof the picture is more accurate. In the worked example above, the silhouette score is 0.402 in the input space, 0.664 in the PCA plot and 0.795 in the t-SNE plot, so both pictures make the groups look tighter than they are in the data.
Final Recommendations: Which Method for Your Data?
Use PCA when: You want reproducible results, you want to keep global structure, you are doing an initial look, or your data is roughly linear. PCA is also easier to explain to non-technical stakeholders.
Use UMAP when: You want a nonlinear picture that keeps neighborhoods, and you will check how it changes with its settings and seed.
Use t-SNE when: You want to look closely at local neighborhoods, and you will run several perplexities and seeds to check stability.
Use all three when: You are discovering clusters rather than visualizing known structure, you are publishing results, or the stakes are high.
Dimensionality reduction methods are not neutral observers. They shape what you see, because they optimize different objectives. Treat the groups in any one picture as a hypothesis, and test them with several methods, stability checks and domain knowledge.