K-Means groups unlabelled points into K clusters around centres (centroids). The elbow method helps choose K.
Start
Pick K initial centroids (
k-means++spreads them out smartly).Assign
Each point joins its nearest centroid.
Update
Each centroid moves to the mean of its points.
Repeat
Until assignments stop changing (or
max_iter).
from collections import Counter
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
km = KMeans(n_clusters=4, init="k-means++", n_init=10, random_state=0).fit(X)
print(km.cluster_centers_.shape) # (4, 2)
print(sorted(Counter(km.labels_).values())) # [75, 75, 75, 75] ← 4 equal clustersChoosing K: the elbow method
Run K-Means for K = 1…10 and record the WCSS (within-cluster sum of squares, inertia_). It always falls as K grows; the “elbow” where it stops falling sharply is a good K.
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
wcss = [KMeans(n_clusters=k, n_init=10, random_state=0).fit(X).inertia_ for k in range(1, 11)]
drops = [round(wcss[i] - wcss[i + 1]) for i in range(5)]
print(drops) # [1621, 644, 335, 23, 18] ← big drops until K = 4, then small onesimport matplotlib.pyplot as plt
plt.plot(range(1, 11), wcss, marker="o")
plt.xlabel("Number of clusters (K)"); plt.ylabel("WCSS"); plt.title("Elbow Method")
plt.show()The same with SciPy
import numpy as np
from scipy.cluster.vq import kmeans, vq
from sklearn.datasets import make_blobs
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
centroids, _ = kmeans(X, 4, seed=0) # centroids
labels, _ = vq(X, centroids) # nearest centroid for each point
print(centroids.shape, len(np.unique(labels))) # (4, 2) 4