K-Means Clustering
K-Means is an unsupervised learning algorithm for clustering that divides data into k groups based on the distance to a centroid. It is popular because it is simple and efficient.
How It Works
- Choose k centroids randomly
- Assign each data point to the nearest centroid
- Recompute each centroid as the mean of all points in the cluster
- Repeat steps 2-3 until the centroids stop changing (convergence)
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import numpy as np
X, y_true = make_blobs(n_samples=300, centers=4, random_state=42)
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
kmeans.fit(X)
labels = kmeans.labels_
centroids = kmeans.cluster_centers_
print(f"Cluster labels: {np.unique(labels)}")
print(f"Centroid shape: {centroids.shape}")
Elbow Method
The elbow method helps determine the optimal number of clusters by examining the total within-cluster sum of squares (WCSS) for various values of k.
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
X, _ = make_blobs(n_samples=300, centers=4, random_state=42)
wcss = []
k_range = range(1, 11)
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
kmeans.fit(X)
wcss.append(kmeans.inertia_)
plt.figure(figsize=(8, 4))
plt.plot(k_range, wcss, 'bo-')
plt.xlabel('Number of Clusters (k)')
plt.ylabel('WCSS (Inertia)')
plt.title('Elbow Method')
plt.grid(True, alpha=0.3)
plt.show()
Silhouette Score
The silhouette score measures how similar a data point is to its own cluster compared to other clusters. The value ranges from -1 to 1; higher is better.
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
X, _ = make_blobs(n_samples=300, centers=4, random_state=42)
for k in range(2, 8):
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 = {score:.4f}")
K-Means++ Initialization
K-Means++ chooses initial centroids that are well spread out, reducing convergence to a local optimum. This is the default in scikit-learn.
from sklearn.cluster import KMeans
# The default already uses k-means++
kmeans = KMeans(
n_clusters=3,
init='k-means++',
n_init=10,
random_state=42
)
Important Attributes
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
iris = load_iris()
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
kmeans.fit(iris.data)
print(f"Labels: {kmeans.labels_}")
print(f"Centroids:\n{kmeans.cluster_centers_}")
print(f"Inertia (WCSS): {kmeans.inertia_:.4f}")
print(f"Number of iterations: {kmeans.n_iter_}")
Example: Customer Segmentation
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
np.random.seed(42)
data = {
'annual_income': np.random.randint(20000, 150000, 200),
'spending_score': np.random.randint(1, 100, 200)
}
df = pd.DataFrame(data)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(df)
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
df['cluster'] = kmeans.fit_predict(X_scaled)
cluster_summary = df.groupby('cluster').agg({
'annual_income': 'mean',
'spending_score': 'mean'
}).round(0)
print(cluster_summary)
Pros and Cons
| Pros | Cons |
|---|---|
| Simple and fast | You must choose k manually |
| Scales to large data | Sensitive to centroid initialization |
| Works well with spherical clusters | Not great for non-convex clusters |
| Easy to interpret | Sensitive to outliers |
| Guaranteed convergence | Assumes all clusters are the same size |
Next chapter: Hierarchical Clustering, an alternative approach to grouping data.