import numpy as np
import matplotlib.pyplot as plt
def k_means_clustering(data, k, max_iterations=100):
"""
Perform K-means clustering on the given data.
Parameters:
data (numpy.ndarray): The data to be clustered.
k (int): The number of clusters.
max_iterations (int): Maximum number of iterations for convergence.
Returns:
tuple: A tuple containing centroids and labels.
centroids (numpy.ndarray): The final centroids of the clusters.
labels (numpy.ndarray): The labels for each data point.
"""
centroids = data[np.random.choice(range(len(data)), k, replace=False)]
for _ in range(max_iterations):
labels = np.argmin(np.linalg.norm(data - centroids[:, np.newaxis], axis=2), axis=0)
new_centroids = np.array([data[labels == i].mean(axis=0) for i in range(k)])
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return centroids, labels
np.random.seed(42)
data = np.concatenate([np.random.normal(loc=i, scale=1, size=(100, 2)) for i in range(3)])
k = 3
centroids, labels = k_means_clustering(data, k)
plt.scatter(data[:, 0], data[:, 1], c=labels, cmap='viridis', alpha=0.7)
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X', s=200, label='Centroids')
plt.title('K-means Clustering')
plt.legend()
plt.show()
aW1wb3J0IG51bXB5IGFzIG5wCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKCmRlZiBrX21lYW5zX2NsdXN0ZXJpbmcoZGF0YSwgaywgbWF4X2l0ZXJhdGlvbnM9MTAwKToKICAgICIiIgogICAgUGVyZm9ybSBLLW1lYW5zIGNsdXN0ZXJpbmcgb24gdGhlIGdpdmVuIGRhdGEuCgogICAgUGFyYW1ldGVyczoKICAgICAgICBkYXRhIChudW1weS5uZGFycmF5KTogVGhlIGRhdGEgdG8gYmUgY2x1c3RlcmVkLgogICAgICAgIGsgKGludCk6IFRoZSBudW1iZXIgb2YgY2x1c3RlcnMuCiAgICAgICAgbWF4X2l0ZXJhdGlvbnMgKGludCk6IE1heGltdW0gbnVtYmVyIG9mIGl0ZXJhdGlvbnMgZm9yIGNvbnZlcmdlbmNlLgoKICAgIFJldHVybnM6CiAgICAgICAgdHVwbGU6IEEgdHVwbGUgY29udGFpbmluZyBjZW50cm9pZHMgYW5kIGxhYmVscy4KICAgICAgICAgICAgY2VudHJvaWRzIChudW1weS5uZGFycmF5KTogVGhlIGZpbmFsIGNlbnRyb2lkcyBvZiB0aGUgY2x1c3RlcnMuCiAgICAgICAgICAgIGxhYmVscyAobnVtcHkubmRhcnJheSk6IFRoZSBsYWJlbHMgZm9yIGVhY2ggZGF0YSBwb2ludC4KICAgICIiIgogICAgY2VudHJvaWRzID0gZGF0YVtucC5yYW5kb20uY2hvaWNlKHJhbmdlKGxlbihkYXRhKSksIGssIHJlcGxhY2U9RmFsc2UpXQogICAgZm9yIF8gaW4gcmFuZ2UobWF4X2l0ZXJhdGlvbnMpOgogICAgICAgIGxhYmVscyA9IG5wLmFyZ21pbihucC5saW5hbGcubm9ybShkYXRhIC0gY2VudHJvaWRzWzosIG5wLm5ld2F4aXNdLCBheGlzPTIpLCBheGlzPTApCiAgICAgICAgbmV3X2NlbnRyb2lkcyA9IG5wLmFycmF5KFtkYXRhW2xhYmVscyA9PSBpXS5tZWFuKGF4aXM9MCkgZm9yIGkgaW4gcmFuZ2UoayldKQogICAgICAgIGlmIG5wLmFsbChjZW50cm9pZHMgPT0gbmV3X2NlbnRyb2lkcyk6CiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgY2VudHJvaWRzID0gbmV3X2NlbnRyb2lkcwogICAgcmV0dXJuIGNlbnRyb2lkcywgbGFiZWxzCgpucC5yYW5kb20uc2VlZCg0MikKZGF0YSA9IG5wLmNvbmNhdGVuYXRlKFtucC5yYW5kb20ubm9ybWFsKGxvYz1pLCBzY2FsZT0xLCBzaXplPSgxMDAsIDIpKSBmb3IgaSBpbiByYW5nZSgzKV0pCmsgPSAzCmNlbnRyb2lkcywgbGFiZWxzID0ga19tZWFuc19jbHVzdGVyaW5nKGRhdGEsIGspCgpwbHQuc2NhdHRlcihkYXRhWzosIDBdLCBkYXRhWzosIDFdLCBjPWxhYmVscywgY21hcD0ndmlyaWRpcycsIGFscGhhPTAuNykKcGx0LnNjYXR0ZXIoY2VudHJvaWRzWzosIDBdLCBjZW50cm9pZHNbOiwgMV0sIGM9J3JlZCcsIG1hcmtlcj0nWCcsIHM9MjAwLCBsYWJlbD0nQ2VudHJvaWRzJykKcGx0LnRpdGxlKCdLLW1lYW5zIENsdXN0ZXJpbmcnKQpwbHQubGVnZW5kKCkKcGx0LnNob3coKQo=