MODELCATALOG

Group rows without labels.

sklearn.cluster

cluster

Group rows without labels.

1 Get data Something to practise on
2 Split & tune An honest test set
3 Prepare Into numbers a model accepts
4 Compose One object, no leakage
5 Model The algorithm itself
6 Unsupervised No labels available
7 Measure Is it any good, and why
8 Utilities Glue and extension

What it is for

Segmentation, deduplication and exploratory structure-finding. The main decision is whether you know how many groups you want — KMeans requires you to say, density methods do not.

Contents

KMeans common Default. You must specify n_clusters
MiniBatchKMeans Same, for large data
DBSCAN Density-based. Arbitrary shapes, marks outliers, no cluster count needed
HDBSCAN DBSCAN without the hard epsilon parameter (1.3+). Usually preferable
AgglomerativeClustering Hierarchical, gives a dendrogram
SpectralClustering, Birch, OPTICS, MeanShift Situational

Worked examples 2

Runnable, with the arguments that change the outcome called out. Output shapes are shown as comments where they help.

Choosing the number of clusters honestly

KMeans requires you to specify k. Silhouette score is a better guide than the elbow plot, which is usually ambiguous.

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

for k in range(2, 9):
    km = KMeans(n_clusters=k, n_init=10, random_state=42).fit(X_scaled)
    print(f"k={k}  inertia={km.inertia_:12.0f}  "
          f"silhouette={silhouette_score(X_scaled, km.labels_):.3f}")

# k=2  inertia=  418203  silhouette=0.412
# k=3  inertia=  312887  silhouette=0.389
# k=4  inertia=  266401  silhouette=0.301   <- quality falling
#
# Inertia always decreases with k, so it can never tell you when to
# stop. Silhouette peaks, which is a usable signal.

Density clustering when you do not know k

HDBSCAN finds clusters of varying density, marks genuine outliers as noise, and needs no cluster count.

from sklearn.cluster import HDBSCAN      # 1.3+
import numpy as np

hdb = HDBSCAN(
    min_cluster_size=50,        # smallest group you would call a cluster
    min_samples=10,             # higher = more points labelled noise
    metric="euclidean",
)
labels = hdb.fit_predict(X_scaled)

print("clusters:", len(set(labels)) - (1 if -1 in labels else 0))
print("noise points:", (labels == -1).sum())

# Label -1 means noise, not a cluster. That is a feature: KMeans is
# forced to assign every point somewhere, so genuine outliers get
# absorbed into whichever cluster is least wrong.