Week 12 · Unsupervised learning in sklearn
Read the words of the video
- Imagine a huge box of mixed-up buttons, with no labels on them. Nobody tells you how they should be grouped. Can a computer still sort them out? Yes! Unsupervised learning helps computers find patterns and structures in data all on their own, just like finding groups of similar buttons.
- Unsupervised learning has three main jobs. First, it sorts data into groups, like using `KMeans` for round piles or `DBSCAN` for any shape. Second, it simplifies descriptions using fewer numbers with `PCA`. Finally, it helps us judge if our grouping is good, using tools like the "elbow" of a curve or the "silhouette score."
- Let's see an example with DBSCAN. Imagine we have seven data points, and their labels after clustering are 0, 0, 1, 1, minus one, 0, and 1. How many real groups did we find? We have two clear clusters, labeled 0 and 1. The point labeled minus one is considered noise, meaning it doesn't belong to any cluster.
- For exams, remember: inertia always drops, so use the "elbow" or "silhouette score" to pick the best number of groups. A minus one label in DBSCAN means noise, not a cluster. PCA doesn't scale data for you, always scale first! Keep practicing, you're becoming a master of finding hidden patterns in data!
The one-minute story
Imagine a huge box of mixed-up buttons with no labels. Nobody tells you the groups. Can the computer still sort them? Unsupervised learning says yes: look for structure on your own.
Three jobs, three tools:
- Sort into piles:
KMeans(round piles, you pick how many),DBSCAN(any shape, it finds the number itself and flags loners as noise),GaussianMixture(soft, overlapping piles with probabilities). - Describe each item with fewer numbers:
PCA(keep the directions of biggest spread). - Judge the answer when there is no answer key: the elbow of the inertia curve, the silhouette score, and the BIC for mixtures.
It is the practice partner of MLT weeks 1 to 4 and MLF week 6.
A note on where the numbers come from. The scikit-learn clustering and mixture modules would not load on the PC used to build this course, because of a Windows Application Control policy (we did not try to bypass it). So the KMeans, DBSCAN and Gaussian-mixture figures below were produced with careful NumPy re-implementations of the same algorithms on the same data, with real scikit-learn used for PCA and the metrics. The solutions (centres, inertia, silhouette, BIC) do not depend on the implementation for well-separated data; the iteration counts may differ by a few. On your own computer the scikit-learn code shown will run and should agree.
By the end of this week you can:
- run
KMeans, readcluster_centers_,labels_,inertia_, and choose with the elbow and silhouette; - explain when
DBSCANbeats k-means and whateps,min_samplesand the label mean; - fit
GaussianMixture, get soft assignments withpredict_proba, and choose components withbic; - apply
PCA:n_components,explained_variance_ratio_,inverse_transform, and choosing the number of components.
Words you need
- Inertia - the k-means objective: the total squared distance from each point to its centre. Smaller is tighter.
- Elbow - the bend in the inertia-vs- curve, after which extra clusters add little.
- Silhouette score - from to : how much closer a point is to its own cluster than to the next nearest. Higher is better.
- Core point / noise (DBSCAN) - a point with many close neighbours / a point belonging to no cluster (label ).
- BIC - a score that rewards fit but punishes extra parameters; lower is better.
- Explained variance ratio - the share of total variance each principal component captures.
Idea 1: KMeans
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, n_init=10, random_state=0).fit(X) # X: scaled features
km.labels_ # the cluster of each training point, shape (n,)
km.cluster_centers_ # the centroids, shape (3, n_features)
km.inertia_ # sum of squared distances to the nearest centre
km.predict(new_X) # nearest-centre label for new points
km.transform(X) # distances to every centre, shape (n, 3)
Defaults worth knowing: n_clusters=8, init="k-means++" (smart seeding, MLT week 3), max_iter=300, tol=1e-4. n_init (the number of restarts, keeping the best) was 10 in older versions and is "auto" in recent ones; set it explicitly to avoid surprises. random_state makes the result repeatable. Scale your features first: k-means uses distances. KMeans has no partial_fit; MiniBatchKMeans does (for huge data).
fit_predict(X) fits and returns the labels in one call. inertia_ equals (we checked it by hand).
Choosing
We made 300 points from 3 blobs. The inertia for :
| 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|
| inertia | 18553 | 3190 | 465 | 406 | 353 | 302 |
It collapses until , then barely moves: the elbow is at . (Inertia always falls as rises, so you cannot just pick the smallest.) The silhouette score gives a second opinion: for : best at again. Use silhouette_score(X, km.labels_) (needs ).
At the clusters are exactly the three blobs (100 points each, adjusted Rand index against the truth). The centres were about , and .
Where k-means fails
K-means draws round, equal-sized clusters (it assigns by distance to a centre). On the "two moons" data (300 points, two interleaved crescents) it cuts straight across both (adjusted Rand index only 0.23). It is also sensitive to outliers and needs in advance.
Idea 2: DBSCAN
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.2, min_samples=5).fit(X) # defaults: eps=0.5, min_samples=5
db.labels_ # cluster ids; -1 means NOISE
db.core_sample_indices_
The idea: a point is a core point if at least min_samples points (itself included) lie within distance eps of it. Clusters are chains of core points and their neighbours; points reachable from no core point are noise (label ).
- No
n_clusters: DBSCAN finds the number itself. - Finds arbitrarily shaped clusters: on the moons it recovered both crescents perfectly (adjusted Rand index 1.0, 0 noise points) where k-means failed.
- Handles outliers by labelling them .
- Weak points: needs a sensible
eps(a global density), struggles when clusters have very different densities, and it has nopredict(it cannot label new points directly).
Idea 3: GaussianMixture
from sklearn.mixture import GaussianMixture
gm = GaussianMixture(n_components=3, covariance_type="full", n_init=3, random_state=0).fit(X)
gm.weights_ # mixing weights pi_k (sum to 1): about 0.33 each here
gm.means_ # the component means (same as the three blobs)
gm.covariances_ # one covariance per component
gm.predict(X) # hard label: the most probable component
gm.predict_proba(X) # SOFT assignments (responsibilities): each row sums to 1
gm.score_samples(X) # log-likelihood of each point
gm.bic(X), gm.aic(X)
This is exactly the EM algorithm of MLT week 4. Defaults: n_components=1, covariance_type="full" (others: "tied", "diag", "spherical"). A point deep inside one blob has responsibilities like ; a point between two blobs would show a split such as .
Parameter count (full covariance, , ): , which is what _n_parameters() reports.
Choosing the number of components with BIC (lower is better):
| 1 | 2 | 3 | 4 | 5 | |
|---|---|---|---|---|---|
| BIC | 2931 | 2569 | 2303 | 2328 | 2357 |
The minimum is at : the same answer as the elbow and the silhouette. BIC = : more components always raise the likelihood but also the penalty.
GMM vs k-means: k-means = hard assignment, equal round clusters; GMM = soft assignment, clusters can be elliptical and differently sized, and it is a generative model (gm.sample(n) draws new points).
Idea 4: PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=2).fit(X) # centres the data for you, but does NOT scale it
Z = pca.transform(X) # the new coordinates, shape (n, 2)
pca.components_ # the principal directions, shape (2, n_features)
pca.explained_variance_ratio_ # share of variance per component
pca.inverse_transform(Z) # back to the original space (an approximation)
On the digits data (1797 images, 64 pixels):
- The first two components explain only 28.5% of the variance (0.15 and 0.14), the first ten 73.8%.
PCA(n_components=0.95)(a number between 0 and 1) keeps as many components as needed to reach 95% of the variance: it chose 29 components, compressing 64 numbers to 29 with little loss.- Reconstruction error (mean squared error between the original and
inverse_transform): 13.4 with 2 components, 0.77 with 30. More components, smaller error: exactly the "discarded eigenvalues" of MLT week 1. - The explained variances add up to the total variance (1202.15 for the digits), as the theory says.
To plot the cumulative variance: np.cumsum(pca.explained_variance_ratio_) and pick the "elbow" or the 95% mark.
Other facts:
- PCA subtracts the mean for you but does not standardise: do that first when features have different units.
IncrementalPCAhaspartial_fitfor huge data;KernelPCA(kernel="rbf")for curved structure;n_components="mle"guesses the dimension.- Use PCA inside a pipeline before a classifier to reduce dimensions and speed up training or reduce noise; for 2-D pictures of high-dimensional data you can also use t-SNE (visualisation only).
Solved examples
Question. Inertias for are . Which ?
Solution. The drop is huge up to () and tiny after (): the elbow is .
Question. (a) Crescent-shaped groups plus a few stray points. (b) Customer groups where each person may partly belong to two groups. (c) 5 million points to cluster in round groups, data arriving in chunks.
Solution. (a) DBSCAN (arbitrary shapes, labels strays as noise). (b) GaussianMixture (soft memberships via predict_proba). (c) MiniBatchKMeans with partial_fit.
Question. Explained variance ratios are . How many components reach at least 90%? What does PCA(n_components=0.9) choose?
Solution. Cumulative: . The first to reach is the 4th, so 4 components, and PCA(n_components=0.9) gives n_components_ == 4.
Your turn
Points on a line with two clusters and . Give cluster_centers_ and inertia_.
Need a hint?
Cluster means, then squared distances.
Show the full solution
Centres and . Inertia .
db.labels_ is [0, 0, 1, 1, -1, 0, 1]. How many clusters and how many noise points?
Need a hint?
is not a cluster.
Show the full solution
2 clusters (labels 0 and 1) and 1 noise point (the ).
gm.predict_proba(x) returns [0.7, 0.2, 0.1]. What does gm.predict(x) return? Is k-means able to give the 0.7?
Need a hint?
predict takes the largest.
Show the full solution
Component 0. K-means only gives a hard label; the probabilities are a Gaussian-mixture feature.
The 3 eigenvalues of the covariance matrix are . What are explained_variance_ratio_ and the 2-component reconstruction error?
Need a hint?
Ratios divide by the total 10; error is the discarded part.
Show the full solution
Ratios . Keeping 2 components leaves out the eigenvalue : reconstruction error (and 90% variance explained).
Should you standardise features before KMeans? Before PCA? Before a decision tree?
Need a hint?
Distance-based or variance-based?
Show the full solution
Yes for KMeans (distances), yes for PCA (variance-driven; otherwise big-unit features dominate), no for a decision tree.
Exam radar
In MLP Quiz 1 summaries the unsupervised ideas are lighter, but "which algorithm / sklearn object can reduce, expand or generate feature representations?" and Euclidean distance appear; the End Term includes the last week of the course: KMeans attributes (inertia_, cluster_centers_, labels_), elbow/silhouette reasoning, DBSCAN's noise label, GaussianMixture.predict_proba, PCA(n_components=0.95) and explained_variance_ratio_, and "which method can still recommend a brand-new item with no ratings?" (content-based filtering).
Partner theory in MLT: PCA in 25 of 60 Quiz 1 papers, EM in 46, k-means in 10.
- Inertia always falls as grows: use the elbow/silhouette, not the minimum.
- DBSCAN's label means noise, not "cluster "; it has no
predict. PCA(n_components=0.95)is a fraction of variance, not 0.95 components.- PCA does not scale for you; k-means needs scaled data.
- Lower BIC is better (higher silhouette is better).
GaussianMixture.predict_probarows sum to 1; k-means has no such thing.
Quick quiz
In DBSCAN, a label of -1 means...
- the largest cluster
- the point is noise
- an error occurred
- the first cluster
PCA(n_components=0.95) selects...
- 95 components
- 0.95 components
- enough components to explain 95 percent of the variance
- components with eigenvalue 0.95
For choosing the number of GaussianMixture components, we prefer the model with...
- the highest BIC
- the lowest BIC
- the highest inertia
- the most components
Select all TRUE statements. (select all that apply)
- KMeans.inertia_ always decreases as n_clusters increases (for the best solution).
- DBSCAN can find non-round clusters.
- PCA scales the features automatically.
- GaussianMixture gives only hard assignments.
Recap
- KMeans:
cluster_centers_,labels_,inertia_; scale first; pick by elbow / silhouette. Round clusters only.MiniBatchKMeanshaspartial_fit. - DBSCAN:
eps,min_samples; any shape; label = noise; nopredict. - GaussianMixture = EM: soft
predict_proba,weights_,means_; choose by lowest BIC. - PCA:
components_,explained_variance_ratio_,inverse_transform;n_components=0.95keeps 95% variance (digits: 29 components); error = discarded variance.
- Inertia ; silhouette in
- DBSCAN defaults
eps=0.5,min_samples=5; noise label - GMM parameters (full): ; BIC (lower is better)
- PCA: variance explained ; reconstruction error
- MLF week 6 - SVD and PCA: squeezing data: PCA in sklearn is an SVD behind the scenes.
- MLT week 3 - K-means: grouping without labels: K-means in scikit-learn.
- MLT week 4 - MLE, Bayes, Gaussian mixtures and EM: Gaussian mixtures in scikit-learn.
- MLT week 1 - PCA: finding the best view of your data: PCA in scikit-learn.
Practise with real exam questions
These come straight from past papers (with the real figures and the official answer key). Open 58 real questions on this week All End Term papers