Clustering with k-means and friends

scikit-learn · Practical · 11 min

Clustering is how you find structure, such as customer segments, when there is no label to predict.

Clustering assigns samples to groups without labels. Every clusterer has fit and exposes labels_; most also have fit_predict.

KMeans(n_clusters=k) places k centroids and alternates between assigning points to the nearest centroid and moving centroids to the mean of their points. It is fast and simple but assumes roughly spherical, similar-sized clusters, needs k in advance, and is sensitive to feature scale, so scale first. It runs several initialisations (n_init) and keeps the one with the lowest inertia_ (within-cluster sum of squares). predict assigns new points to the nearest centroid. MiniBatchKMeans scales to millions of rows.

DBSCAN(eps, min_samples) groups dense regions, finds clusters of any shape and labels outliers as -1, but eps is hard to set when densities vary; HDBSCAN removes that parameter. AgglomerativeClustering merges clusters bottom-up and works with different linkages.

Choosing k and judging quality is the hard part, because there is no ground truth:

  • silhouette_score(X, labels) ranges from -1 to 1; higher means tighter, better-separated clusters.
  • Inertia always falls as k grows, so look for an elbow rather than the minimum.

Ultimately clusters are judged by whether they are useful and interpretable for your purpose.

Example

from sklearn.cluster import KMeans, DBSCAN
from sklearn.datasets import make_blobs, make_moons
from sklearn.metrics import silhouette_score

X, _ = make_blobs(n_samples=300, centers=4, random_state=0)
for k in [2, 3, 4, 5, 6]:
    labels = KMeans(n_clusters=k, n_init=10, random_state=0).fit_predict(X)
    print(k, round(silhouette_score(X, labels), 3))
# 2 0.448
# 3 0.457
# 4 0.501  <- best
# 5 0.453
# 6 0.412

Xm, _ = make_moons(n_samples=200, noise=0.05, random_state=0)
db = DBSCAN(eps=0.3, min_samples=5).fit(Xm)
print(sorted(set(db.labels_.tolist()))) # [0, 1] (two moon shapes, no noise points)

Remember

  • k-means needs scaled data and a chosen k; it prefers round clusters
  • DBSCAN/HDBSCAN find arbitrary shapes and mark noise as -1
  • Use silhouette scores and domain sense to choose k

Watch out for

  • Picking k at the minimum inertia, which always means the largest k.

Check yourself

  1. Why is the k with the lowest inertia_ a poor way to choose the number of clusters?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: scikit-learn.org/stable/modules/clustering.html

Builds on

Unlocks

Nothing builds on this yet.