Concepts 🚀 Project 🧮 Labs
🧮 Labs / ML Advanced / K-Means visualized — centroid movement + elbow plot (iris)

K-Means visualized — centroid movement + elbow plot (iris)

SEE the centroids move iteration by iteration. SEE the elbow plot to pick K. Unsupervised learning made visual.

script.py v3.1
Python output click Run to execute
Click "Run" to execute the code on the left.
The output will appear here.
🧠 How it works

K-Means Clustering — VISUALIZED: UNSUPERVISED: no labels. The algorithm finds structure on its own. ALGORITHM (Lloyd's): (1) Place K centroids randomly. (2) ASSIGN: each point joins its nearest centroid. (3) UPDATE: move each centroid to the MEAN of its points. (4) Repeat until centroids stop moving. INERTIA (cost function): sum of squared distances from each point to its centroid. Inertia = Σ Σ ||x - centroid||². K-Means minimizes this. ELBOW PLOT: inertia vs K. Always decreasing (more K = smaller distances). Look for the 'bend' — that's the natural number of clusters. On iris: elbow at K=3. K-Means finds the 3 species WITHOUT BEING TOLD! CENTROID MOVEMENT: Iteration 1: random centroids → bad clustering. Iteration 2: centroids move to cluster means → better. Iteration 5+: centroids stabilize → convergence. WARNINGS: (1) Clusters are SPHERICAL — fails on elongated/irregular shapes (use DBSCAN instead). (2) Clusters are SIMILAR SIZE — fails on very uneven sizes. (3) K must be chosen — elbow plot or silhouette score. (4) ALWAYS scale first — large features dominate distance. (5) Random initialization — run multiple times (n_init=10) and pick the best. ADJUSTED RAND INDEX (ARI): compares K-Means clusters to true labels. 1.0 = perfect match. 0.0 = random. On iris: ~0.7-0.9 — K-Means recovers the species!

✏️ Try these changes
  • Change n_clusters from 3 to 2
    → merges 2 species into 1 cluster — look at the elbow plot to see why 3 is better
  • Change n_clusters from 3 to 5
    → splits species into sub-clusters — overfitting the clustering
  • Change init from 'random' to 'k-means++'
    → smarter initialization — converges faster, better results
  • Use sepal features: X = iris.data[:, [0, 1]]
    → clusters are less clear — species overlap in sepal dimensions