K-Means Clustering Explained Simply (with a Focus on K-Means++)

K-means is one of the most popular and widely used unsupervised machine learning algorithms. At a high level, it takes a set of data points and groups them into a specified number (k) of clusters based on the similarity between the points. Points that are more similar or "closer" to each other are put into the same cluster.

The k-means algorithm has applications in a variety of fields including customer segmentation, document clustering, image compression, and anomaly detection. For example, businesses commonly use k-means to segment their customer base into distinct groups in order to better tailor products, services, and marketing to each segment.

In this article, we‘ll take an in-depth look at how the k-means algorithm works under the hood. We‘ll then focus on an important extension to basic k-means called k-means++, which intelligently selects the initial cluster centroids. Finally, we‘ll discuss some practical considerations when using k-means and review a few recent developments in k-means clustering. Python code examples are provided throughout to illustrate the key concepts.

The Basic K-Means Algorithm

The standard k-means algorithm follows a straightforward 4-step process:

  1. Specify the desired number of clusters k
  2. Initialize k cluster centroids (means)
  3. Assign each data point to the nearest centroid
  4. Update the centroids as the mean of the points in the cluster
  5. Repeat steps 3-4 until the centroids no longer change significantly or a max number of iterations is reached

The "nearness" of data points to centroids is determined by a distance metric, most commonly Euclidean distance. The Euclidean distance d between points p and q is calculated as:

d(p,q) = sqrt((p1-q1)^2 + (p2-q2)^2 + … + (pn-qn)^2)

Where n is the number of dimensions (features) of the data points. Intuitively, this is the straight line distance between two points in n-dimensional space.

Let‘s walk through the k-means algorithm with a simple example. Say we have a dataset of customer data with just two features – age and income. We want to find three customer segments using k-means.

We first randomly initialize 3 centroids. We then calculate the Euclidean distance between each customer and the three centroids, assigning each customer to its nearest centroid. This gives us our initial clusters.

Next we update each centroid to be the mean age and income of all the customers assigned to that cluster. We then repeat the process of assigning customers to the nearest centroid. We continue iterating like this until the cluster assignments no longer change.

Here‘s what this might look like in Python using the scikit-learn library:

from sklearn.cluster import KMeans

# Customer age and income data 
X = [[20,40000], [25,50000], [30,60000], [35,70000], [40,80000], 
     [45,90000], [50,100000], [55,110000], [60,120000]]

# Initialize and fit k-means with 3 clusters
kmeans = KMeans(n_clusters=3, random_state=42).fit(X)

# Final locations of centroids
print(kmeans.cluster_centers_)

# Cluster assignments for each customer
print(kmeans.labels_)

Output:

[[30. 60000.]
 [52.5 105000.]  
 [20. 40000.]]

[0 0 0 1 1 1 1 2 2]

The basic k-means algorithm is guaranteed to converge, but it may converge to a suboptimal local minimum. The random initialization of centroids can have a big impact on the final clusters, so k-means is usually run multiple times with different centroid seeds.

K-Means++ Centroid Initialization

While basic k-means is simple and often effective, the random initialization of centroids can lead to slower convergence and less optimal results. This is where k-means++ comes in.

K-means++, introduced by David Arthur and Sergei Vassilvitskii in 2007, is a smart centroid initialization strategy. It improves upon standard k-means in terms of both speed and accuracy.

The key idea behind k-means++ is to choose initial centroids that are far apart from each other. This is in contrast to basic k-means which chooses completely random points. Intuitively, spreading out the initial centroids allows k-means++ to more efficiently explore the data space and find a better clustering.

Here‘s how the k-means++ centroid initialization works:

  1. Choose one centroid uniformly at random from the data points
  2. For each data point x, compute the distance d(x) between x and the nearest centroid that has already been chosen
  3. Select the next centroid from the data points with probability proportional to d(x)^2
  4. Repeat steps 2-3 until k centroids have been chosen

Basically, k-means++ chooses the first centroid randomly and then selects the rest of the centroids with a probability proportional to their squared distance from the closest existing centroid. This encourages the algorithm to pick centroids that are further away from the ones it already picked.

Here‘s how we can modify our previous example to use k-means++:

from sklearn.cluster import KMeans

X = [[20,40000], [25,50000], [30,60000], [35,70000], [40,80000], 
     [45,90000], [50,100000], [55,110000], [60,120000]]

# K-means++ initialization
kmeans = KMeans(n_clusters=3, init=‘k-means++‘, random_state=42).fit(X)

That‘s it! By simply changing the init parameter to ‘k-means++‘, scikit-learn will use the k-means++ centroid initialization strategy instead of random initialization.

So how effective is k-means++ in practice? In their original paper, Arthur and Vassilvitskii proved that k-means++ is Θ(log k)-competitive with the optimal clustering. This means that on average, k-means++ provides a clustering that is at most O(log k) times worse than the optimal k-means clustering.

Empirically, studies have shown that k-means++ tends to converge faster and to better solutions than random initialization. It is generally recommended to use k-means++ over basic k-means for these reasons.

Choosing the Number of Clusters (k)

One of the main practical issues with k-means is that the number of clusters k must be specified in advance. But how do we know what k value to use for a given dataset?

There are a few different heuristics that are commonly used to choose k:

The Elbow Method

The elbow method looks at the within-cluster sum of squared errors (SSE) as a function of k. The SSE measures the compactness of the clustering and we want it to be as small as possible.

As k increases, the SSE will tend to decrease because having more clusters allows the data to be fit more closely. However, the improvements in SSE tend to decline as k gets larger. If we plot SSE vs. k, we‘ll often see a kink or "elbow" in the plot where the rate of decrease sharply shifts. This kink location is a good indication of a reasonable k value.

The Silhouette Method

The silhouette method measures how similar a data point is to its own cluster compared to other clusters. The silhouette coefficient for a data point i is defined as:

s(i) = (b(i) – a(i)) / max(a(i), b(i))

where a(i) is the mean distance between i and all other points in the same cluster, and b(i) is the mean distance between i and all other points in the next nearest cluster.

The silhouette coefficient ranges from -1 to 1. A high positive value indicates that i is well matched to its own cluster and poorly matched to neighboring clusters. If most points have a high silhouette coefficient, then the clustering is considered appropriate. The silhouette method involves computing the mean silhouette coefficient for different values of k and picking the k that maximizes the mean coefficient.

In practice, it‘s a good idea to use multiple criteria, like the elbow and silhouette methods in combination, to determine a suitable number of clusters. Domain knowledge should also be used to help assess if the clusters are meaningful and useful.

Here‘s an example of using the elbow and silhouette methods with k-means++ initialization in Python:

from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
import numpy as np

# Vary k from 1 to 10
K = range(1,10)

# List to store SSE for each k
sse = []

for k in K:
    km = KMeans(n_clusters=k, init=‘k-means++‘, random_state=42)
    km.fit(X)
    sse.append(km.inertia_)

# Plot SSE vs k (elbow method)  
plt.plot(K, sse, ‘bx-‘)
plt.xlabel(‘k‘)
plt.ylabel(‘SSE‘)
plt.title(‘Elbow Method For Optimal k‘)
plt.show()

# Compute silhouette coefficients for k=2 through 9 
silhouette_coefficients = []

for k in range(2, 10):
    km = KMeans(n_clusters=k, init=‘k-means++‘, random_state=42)
    labels = km.fit_predict(X)
    score = silhouette_score(X, labels)
    silhouette_coefficients.append(score)

# Plot silhouette coefficient vs k    
plt.plot(range(2,10), silhouette_coefficients)
plt.xticks(range(2,10))
plt.xlabel("Number of Clusters")
plt.ylabel("Silhouette Coefficient")
plt.show()

Practical Considerations and Limitations

While k-means and k-means++ are powerful clustering algorithms, there are several practical issues to be aware of:

Curse of Dimensionality

K-means is known to struggle with high-dimensional data due to the "curse of dimensionality". As the number of dimensions increases, distances between points become less meaningful and clusters tend to be less separable. Dimensional reduction techniques like PCA can help alleviate this issue.

Handling Categorical Data

K-means assumes continuous, numeric data since it relies on computing Euclidean distances. However, datasets often contain categorical features. One approach is to use one-hot encoding to convert categorical variables into dummy binary features. Alternatively, the k-modes algorithm is a variant of k-means designed to handle categorical data.

Outlier Sensitivity

K-means is sensitive to outliers since it uses the mean as the centroid of each cluster. A single faraway point can substantially pull the centroid away from the center of the other cluster points. The k-medoids algorithm is more robust to outliers as it uses medoids (actual data points) as cluster centers instead of means.

Assessing Cluster Tendency

Before applying k-means, we should check if the data actually has a clustering tendency – that is, if there are meaningful clusters to find. The Hopkins statistic is one way to assess the clustering tendency of a dataset by comparing the distance between objects in the original data to objects in a simulated random distribution. A value close to 1 suggests the data is highly clusterable, while a value close to 0.5 suggests the data is randomly distributed.

Recent Developments and Applications

K-means clustering continues to be an active area of research. Some recent developments as of 2023 include:

  • Scalable k-means++ initialization for massive datasets using MapReduce or Apache Spark
  • Integration of deep learning with k-means for joint representation learning and clustering
  • Application of k-means to streaming data for real-time cluster analysis
  • Use of k-means for COVID-19 patient triage and resource allocation
  • Application of k-means to single-cell RNA sequencing data for cell type discovery

Some interesting applications of k-means in different domains:

  • Astronomy: Segmenting celestial objects in telescope images
  • Retail: Customer segmentation for targeted marketing campaigns
  • Social media: Detecting communities in social networks
  • Neuroscience: Identifying neuron types based on electrophysiology data
  • Agriculture: Segmenting satellite imagery to monitor crop health

Conclusion

K-means is a classic clustering algorithm that is still widely used today thanks to its simplicity and effectiveness. K-means++ provides a clever way to choose initial centroids that can improve both the speed and quality of the clustering.

When using k-means in practice, it‘s important to be aware of its assumptions and limitations. Careful data preprocessing, feature selection, and evaluation of cluster tendency can help ensure meaningful results.

Despite its age, k-means remains a powerful tool in the data scientist‘s toolkit and continues to find new applications across many different fields. Understanding its inner workings is a foundational skill for anyone working with unsupervised machine learning.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts