Partitions data into k clusters by iterating: (1) assign each point to its nearest centroid, (2) recompute centroids as the mean of their assigned points — repeat until stable.
Elbow method: plot inertia vs k. Pick k at the "bend," where adding more clusters stops giving much extra improvement.
from sklearn.cluster import KMeans inertias = [] for k in range(1, 10): km = KMeans(n_clusters=k, random_state=42, n_init='auto') km.fit(X) inertias.append(km.inertia_)
Builds a tree of nested clusters. Agglomerative (bottom-up, far more common): start with every point as its own cluster, repeatedly merge the two closest clusters until one remains.
Dendrogram: the height of each merge shows how (dis)similar the merged clusters were. Cutting horizontally at a chosen height reveals that many clusters — no need to pick k upfront.
Groups points that are closely packed together (dense regions), marking points in low-density regions as noise instead of forcing them into a cluster. Driven by two parameters: eps (neighborhood radius) and min_samples (minimum points to form a dense region).
Two dense clusters (blue, green) found automatically; the isolated point (pink) is labeled noise, not forced into either cluster.
| K-Means | DBSCAN | |
|---|---|---|
| Cluster shape | Assumes roughly spherical/convex | Finds arbitrary shapes (crescents, rings) |
| Number of clusters | Must specify k | Discovered automatically from density |
| Outliers | Forced into nearest cluster, skewing centroids | Explicitly labeled as noise, doesn't distort clusters |
| Parameter sensitivity | Sensitive to k, initialization | Sensitive to eps/min_samples; struggles with varying-density clusters |
Finds new axes (principal components) — combinations of original features — that capture the most variance in the data, ordered from most to least. Projecting onto the top few components reduces dimensions while keeping most of the information.
from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler X_scaled = StandardScaler().fit_transform(X) # scale first — PCA is variance-based pca = PCA(n_components=5) X_reduced = pca.fit_transform(X_scaled) print(pca.explained_variance_ratio_) # variance captured per component print(pca.explained_variance_ratio_.cumsum()) # running total — pick components covering ~90-95%
A non-linear technique that maps high-dimensional data into 2D/3D specifically to preserve local neighborhood structure for visualization — points close together in high-D stay close in the plot.
perplexity parameter — different values can tell different visual "stories" from the same data.| K-Means | Hierarchical | DBSCAN | |
|---|---|---|---|
| Needs k upfront? | Yes | No — cut dendrogram later | No — density-driven |
| Cluster shape | Spherical / convex | Flexible, depends on linkage | Arbitrary shape |
| Handles outliers? | Poorly — skews centroids | Poorly — still gets merged in | Well — labels as noise |
| Scalability | Good — scales to large n | Poor — O(n²)+ typically | Moderate — depends on implementation |
| Best for | Large, roughly round clusters | Small/medium data, nested structure, no known k | Noisy data, irregular cluster shapes |
| PCA | t-SNE | |
|---|---|---|
| Type | Linear | Non-linear |
| Goal | Preserve global variance | Preserve local neighborhoods |
| Use case | Preprocessing / feature reduction before modeling | Visual exploration of clusters/classes |
| Deterministic? | Yes | No — depends on init & perplexity |
| Speed | Fast, scales well | Slow on large datasets |