Quiz 2

Clustering: k-Means, Hierarchical, DBSCAN

1874 words
9 min read
Python Week 1: the first filter for runtime behavior
Visual companion
Python
Type and operator map

Python Week 1: the first filter for runtime behavior

View
Revision summary

What this note is really saying

Short form

# Clustering: k-Means, Hierarchical, DBSCAN ## 🎯 Learning Objectives - Explain unsupervised learning and when clustering is appropriate - Implement and interpret k-means clustering with proper k selection - Understand hierarchical clustering and dendrogram interpretation - Use DBSCAN for density-based clustering wi...

Clustering: k-Means, Hierarchical, DBSCAN

🎯 Learning Objectives

  • Explain unsupervised learning and when clustering is appropriate
  • Implement and interpret k-means clustering with proper k selection
  • Understand hierarchical clustering and dendrogram interpretation
  • Use DBSCAN for density-based clustering with arbitrary shapes
  • Evaluate cluster quality using internal and external metrics

📋 Prerequisites

  • Unsupervised learning concepts — learning without labels
  • Distance metrics — Euclidean, Manhattan (from k-NN)
  • Basic statistics — mean, variance, standard deviation

📖 Core Content

9.1 Intuition: Finding Natural Groups Without a Teacher

Imagine you're given a pile of music tracks and asked to organize them. You don't know the genres ahead of time, but you notice some are fast and loud, others are slow and melodic, and some have acoustic guitar. Clustering discovers these groupings automatically — it finds structure in unlabeled data. (Diagram) Applications:
  • Customer segmentation (marketing)
  • Image compression (color quantization)
  • Anomaly detection (outliers are tiny clusters)
  • Recommendation systems (cluster users, recommend within cluster)

9.2 k-Means Clustering

Algorithm:
  1. Choose k (number of clusters)
  2. Initialize k centroids (randomly or with k-means++)
  3. Repeat until convergence:
    • Assignment step: Assign each point to nearest centroid
    • Update step: Recompute centroid as mean of assigned points Objective (Inertia):
J=i=1mx(i)μc(i)2J = \sum_{i=1}^{m} \|x^{(i)} - \mu_{c^{(i)}}\|^2
Where μc(i)\mu_{c^{(i)}} is the centroid assigned to point x(i)x^{(i)}. Minimizing this makes clusters compact.
python
# runnable
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
# Generate synthetic data
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=1.0, random_state=42)
# Fit k-means
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
kmeans.fit(X)
print(f"Inertia: {kmeans.inertia_:.2f}")
print(f"Centroids:\n{kmeans.cluster_centers_}")
print(f"Labels: {kmeans.labels_[:10]}")
# Visualize
plt.scatter(X[:, 0], X[:, 1], c=kmeans.labels_, cmap='viridis', alpha=0.7)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1],
            marker='X', s=200, c='red', label='Centroids')
plt.title('k-Means Clustering')
plt.legend()
plt.grid(True)
plt.show()

9.2.1 Worked Example 1: k-Means by Hand

Points: A(1,2), B(2,1), C(4,4), D(5,5), E(8,1), F(9,2). k=2. Step 1: Initialize centroids: μ₁ = A(1,2), μ₂ = E(8,1). Step 2: Assign each point to nearest centroid.
PointDist to μ₁Dist to μ₂Assign to
A(1,2)0√[(1-8)²+(2-1)²] = √50 ≈ 7.071
B(2,1)√[(2-1)²+(1-2)²] = √2 ≈ 1.41√[(2-8)²+(1-1)²] = 61
C(4,4)√[(4-1)²+(4-2)²] = √13 ≈ 3.61√[(4-8)²+(4-1)²] = 51
D(5,5)√[(5-1)²+(5-2)²] = 5√[(5-8)²+(5-1)²] = 51 (tie, arbitrarily)
E(8,1)√50 ≈ 7.0702
F(9,2)√[(9-1)²+(2-2)²] = 8√[(9-8)²+(2-1)²] = √2 ≈ 1.412
Step 3: Update centroids.
  • μ₁ = mean(A, B, C, D) = mean([1,2,4,5], [2,1,4,5]) = (3, 3)
  • μ₂ = mean(E, F) = mean([8,9], [1,2]) = (8.5, 1.5) Step 4: Reassign. Now check distances.
PointDist to μ₁(3,3)Dist to μ₂(8.5,1.5)Assign
A(1,2)√5 ≈ 2.24√[(1-8.5)²+(2-1.5)²] ≈ √56.5 ≈ 7.521
B(2,1)√5 ≈ 2.24√[(2-8.5)²+(1-1.5)²] ≈ √42.5 ≈ 6.521
C(4,4)√2 ≈ 1.41√[(4-8.5)²+(4-1.5)²] ≈ √26.5 ≈ 5.151
D(5,5)√8 ≈ 2.83√[(5-8.5)²+(5-1.5)²] ≈ √24.5 ≈ 4.951
E(8,1)√29 ≈ 5.39√0.5 ≈ 0.712
F(9,2)√37 ≈ 6.08√0.5 ≈ 0.712
No changes in assignment → converged! Result: Cluster 1: {A, B, C, D}, Cluster 2: {E, F}.

9.2.2 Choosing k: The Elbow Method

python
# runnable
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
# Calculate inertia for k=1 to k=10
inertias = []
K = range(1, 11)
for k in K:
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    kmeans.fit(X)
    inertias.append(kmeans.inertia_)
plt.plot(K, inertias, 'bo-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Elbow Method for Optimal k')
plt.grid(True)
plt.show()
The "elbow" is where adding more clusters gives diminishing returns (similar to PCA's scree plot).

9.3 Hierarchical Clustering

Builds a hierarchy of clusters via:
  • Agglomerative (bottom-up): Start with each point as its own cluster, merge closest pairs
  • Divisive (top-down): Start with all points in one cluster, split recursively
python
# runnable
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt
# Agglomerative clustering
hc = AgglomerativeClustering(n_clusters=4, linkage='ward')
hc.fit(X)
print(f"Hierarchical labels: {hc.labels_}")
# Dendrogram
Z = linkage(X, method='ward')
plt.figure(figsize=(10, 5))
dendrogram(Z)
plt.title('Dendrogram (Ward Linkage)')
plt.ylabel('Distance')
plt.show()
Linkage Criteria:
LinkageDistance Between ClustersTendency
SingleMinimum pairwise distanceChaining, finds elongated clusters
CompleteMaximum pairwise distanceCompact clusters
AverageAverage pairwise distanceBetween single and complete
WardVariance increase when mergingProduces compact, spherical clusters

9.4 DBSCAN: Density-Based Spatial Clustering

DBSCAN finds clusters as dense regions separated by sparse regions. It doesn't require specifying k and can find arbitrarily-shaped clusters. Parameters:
  • eps: Maximum distance between two points to be considered neighbors
  • min_samples: Minimum points to form a dense region Point Types:
  • Core point: ≥ min_samples neighbors within eps
  • Border point: < min_samples neighbors, but reachable from a core point
  • Noise point: Not reachable from any core point
python
# runnable
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons
# Non-spherical data
X, _ = make_moons(n_samples=200, noise=0.05, random_state=42)
# k-means fails on this
kmeans = KMeans(n_clusters=2, random_state=42)
print(f"k-means on moons: {kmeans.fit_predict(X)}")
# DBSCAN succeeds
db = DBSCAN(eps=0.3, min_samples=5)
db_labels = db.fit_predict(X)
print(f"DBSCAN labels: {db_labels}")
print(f"Number of clusters found: {len(set(db_labels)) - (1 if -1 in db_labels else 0)}")
print(f"Noise points: {list(db_labels).count(-1)}")

9.5 Cluster Evaluation

Internal Metrics (no ground truth):
MetricFormulaRangeBetter
Silhouette Scorebamax(a,b)\frac{b-a}{\max(a,b)}[-1, 1]Higher (well-separated)
Davies-Bouldin1kmaxijsi+sjdij\frac{1}{k}\sum \max_{i\neq j} \frac{s_i+s_j}{d_{ij}}[0, ∞)Lower
Inertia$\sum\x-\mu\^2$
Where aa = mean intra-cluster distance, bb = mean nearest-cluster distance. External Metrics (with ground truth labels):
MetricMeasures
Adjusted Rand Index (ARI)Pairwise agreement, chance-adjusted
Normalized Mutual Info (NMI)Mutual information between true and predicted labels
HomogeneityEach cluster contains only one class
CompletenessAll members of a class assigned to same cluster

9.6 When to Use / Not Use

AlgorithmBest ForLimitations
k-MeansSpherical clusters, large data, equally sized clustersAssumes spherical clusters, sensitive to initialization
HierarchicalSmall data, any shape, want dendrogramO(m²), doesn't scale
DBSCANArbitrary shapes, noisy data, outliersVarying density clusters, high dimensions

📐 Key Formulas / Concepts

ConceptFormulaNotes
k-Means Inertia$\sum_{i=1}^{m} \x^{(i)} - \mu_{c^{(i)}}\
Silhouette Scorebamax(a,b)\frac{b-a}{\max(a,b)}Measures cluster separation
DBSCAN Core≥ min_samples neighbors within epsDense region
Linkage (Ward)Minimizes within-cluster varianceMerge clusters with smallest variance increase

⚠️ Common Pitfalls

Pitfall 1: Wrong k in k-Means

The mistake: Choosing k arbitrarily without the elbow method or silhouette analysis. Fix: Always use elbow + silhouette to determine k. If they disagree, consider domain knowledge.

Pitfall 2: Inconsistent Scales

The mistake: Not scaling features before clustering. Why: All clustering algorithms use distance — features with larger ranges dominate. Fix: Standardize features to have zero mean and unit variance.

Pitfall 3: k-Means on Non-Spherical Data

The mistake: Using k-means on moon-shaped or concentric datasets. Why: k-means assumes spherical clusters of similar size. It can't separate interlocking moons. Fix: Use DBSCAN for density-based clusters or spectral clustering for complex shapes.

📝 Practice Questions

Q1: Compute the 2nd step of k-means for points (0,0), (2,0), (5,5), (7,5) with k=2, centroids at (0,0) and (7,5).
Assignment:
  • (0,0) → 0 (dist=0 vs √74=8.6)
  • (2,0) → 0 (dist=2 vs √[25+25]=√50=7.07)
  • (5,5) → 1 (dist=√50=7.07 vs √[4+0]=2)
  • (7,5) → 1 (dist=√74=8.6 vs 0)
Update:
  • μ₀ = mean([0,0], [2,0]) = (1, 0)
  • μ₁ = mean([5,5], [7,5]) = (6, 5) Q2: What does a silhouette score close to 1 mean?
Each point is much closer to its own cluster than to the nearest other cluster. The clusters are dense and well-separated. By contrast, a score near 0 means clusters overlap, and negative means many points are assigned to the wrong cluster. Q3: Why does DBSCAN label some points as -1 (noise)?
Points labeled -1 cannot be reached from any core point within ε distance. They're in sparse regions that don't meet the density threshold. These are outliers that don't belong to any cluster. Q4: When would you use hierarchical over k-means?
  1. You want a dendrogram — visualize the hierarchy at all levels
  2. You don't know k — the dendrogram helps choose k post-hoc
  3. Small dataset (< 2000 points) — hierarchical is O(m²)
  4. Non-spherical clusters — with single/complete linkage Q5: What is k-means++ initialization?
Standard random initialization can lead to poor convergence. k-means++ spreads out initial centroids:
  1. Pick first centroid randomly
  2. For each point, compute distance to nearest centroid
  3. Pick next centroid with probability proportional to distance²
  4. Repeat until k centroids chosen
This leads to better, faster convergence. It's the default in sklearn (init='k-means++'). Q6: Implement k-means with silhouette score to find optimal k.
python
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import numpy as np

best_k, best_score = 2, -1
for k in range(2, 11):
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    labels = kmeans.fit_predict(X)
    score = silhouette_score(X, labels)
    print(f"k={k}: silhouette = {score:.3f}")
    if score > best_score:
        best_k, best_score = k, score

print(f"Best k = {best_k} with silhouette = {best_score:.3f}")
Q7: What happens in DBSCAN if eps is too small or too large?
  • eps too small: Most points become noise (-1), clusters fragment into tiny groups
  • eps too large: Clusters merge together, most points become core points of one big cluster
The optimal eps creates enough density within clusters while keeping them separated. Use the k-distance plot to find the optimal eps value. Q8: Compare centroid-based vs density-based clustering.
Aspectk-Means (Centroid)DBSCAN (Density)
Cluster shapeSphericalArbitrary shapes
Number of clustersMust specify kAuto-detected
Noise handlingForces all points into clustersLabels outliers as noise
ScalabilityO(m·k·iter)O(m²) with naive, O(m log m) with spatial index
DeterministicNo (initialization)Yes (order-independent with good implementation)
Q9: A customer segmentation has silhouette score 0.15. What does this indicate?
0.15 is low — clusters are not well-separated. The customer segments likely overlap significantly. Possible issues:
  1. Wrong k (try different values)
  2. Features don't separate customers well (try different features or PCA first)
  3. Customers genuinely form a continuum, not discrete segments Q10: How would you cluster a dataset of 1 million customer records?
Use k-means (scalable) or Mini-Batch k-Means (even faster). Avoid hierarchical (O(m²)) and DBSCAN (O(m²) naive). Mini-Batch k-Means processes data in small batches, making it suitable for million-scale data with minimal quality loss.
python
from sklearn.cluster import MiniBatchKMeans
mbk = MiniBatchKMeans(n_clusters=10, batch_size=1000, random_state=42)
Q11: Explain single vs complete linkage in hierarchical clustering with an example.
  • Single linkage: Distance between clusters = minimum distance between any point in A and any point in B. Creates long "chained" clusters (good for elongated shapes).
  • Complete linkage: Distance = maximum distance between any point in A and any point in B. Creates compact clusters (good for spherical shapes).
Example: Two circular clusters connected by a thin line of points. Single linkage would merge them into one chain. Complete linkage would keep them separate (the line's nearest-endpoint distance is small, but its farthest is large). Q12: Your k-means gives different results each run. Why?
k-means is sensitive to initialization. Different random starts produce different final clusters. To make it reproducible:
  1. Use random_state in sklearn
  2. Use k-means++ initialization (default)
  3. Run multiple restarts (n_init=10+) and keep the one with lowest inertia
sklearn's defaults handle this, but the variability is inherent to the algorithm.

🔗 Cross-References

Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.