K-means是一種經典的無監督學習演演算法,用於對資料進行聚類。K-means演演算法將資料集視為具有n個特徵的n維空間,並嘗試通過最小化簇內平方誤差的總和來將資料點劃分為簇。本文將介紹K-means演演算法的原理、實現和應用。
K-means演演算法是一種迭代演演算法,其基本思想是通過將每個資料點分配到最近的質心,並計算新的質心來迭代地改進簇的質量,直到質心不再變化或達到最大迭代次數為止。具體步驟如下:
K-means演演算法的核心是將資料點分配到最近的質心所在的簇,這是通過計算每個資料點與K個質心的距離來實現的。一般而言,距離可以使用歐氏距離、曼哈頓距離等來計算。而每個簇的質心則是該簇內所有資料點的均值,用於表示該簇的中心位置。
在K-means演演算法中,簇的數量k是需要事先指定的。選擇合適的簇的數量非常重要。
需要注意的是,K-means演演算法可能陷入區域性最優解,因此,選擇k值需要多次執行演演算法,比較不同的聚類結果。
import numpy as np
import matplotlib.pyplot as plt
# 建立資料集
np.random.seed(0)
n_samples = 1000
centers = np.array([[0, 0], [3, 3], [0, 3], [3, 0]])
X = np.zeros((n_samples, 2))
for i in range(len(centers)):
X[i * (n_samples // len(centers)): (i + 1) * (n_samples // len(centers)), :] = \
centers[i] + np.random.randn(n_samples // len(centers), 2)
# 視覺化資料集
plt.scatter(X[:, 0], X[:, 1], s=10)
plt.show()
import numpy as np
def k_means(X, k, max_iter=100):
# 隨機選擇k個點作為初始質心
centroids = X[np.random.choice(len(X), k, replace=False)]
for i in range(max_iter):
# 計算每個資料點與k個質心的距離
distances = np.linalg.norm(X[:, np.newaxis, :] - centroids, axis=-1)
# 將資料點劃分到距離最近的質心所在的簇
labels = np.argmin(distances, axis=1)
# 對於每個簇,重新計算該簇內所有資料點的均值,將該均值作為新的質心
new_centroids = np.array([X[labels == j].mean(axis=0) for j in range(k)])
# 如果質心沒有變化,則停止迭代
if np.allclose(new_centroids, centroids):
break
centroids = new_centroids
return labels, centroids
if __name__ == '__main__':
labels, centroids = k_means(X=X, k=4)
plt.scatter(X[labels==0, 0], X[labels==0, 1], color='r')
plt.scatter(X[labels==1, 0], X[labels==1, 1], color='g')
plt.scatter(X[labels==2, 0], X[labels==2, 1], color='b')
plt.scatter(X[labels==3, 0], X[labels==3, 1])
plt.show()
import numpy as np
import matplotlib.pyplot as plt
# 建立資料集
np.random.seed(0)
n_samples = 1000
centers = np.array([[0, 0], [3, 3], [0, 3], [3, 0]])
X = np.zeros((n_samples, 2))
for i in range(len(centers)):
X[i * (n_samples // len(centers)): (i + 1) * (n_samples // len(centers)), :] = \
centers[i] + np.random.randn(n_samples // len(centers), 2)
# 視覺化資料集
def plot_data(X, labels):
plt.scatter(X[labels==0, 0], X[labels==0, 1], color='r')
plt.scatter(X[labels==1, 0], X[labels==1, 1], color='g')
plt.scatter(X[labels==2, 0], X[labels==2, 1], color='b')
plt.scatter(X[labels==3, 0], X[labels==3, 1], color='m')
plt.show()
def plot_centers(centroids):
plt.scatter(centroids[:, 0], centroids[:, 1], s=200, marker='*', color='k')
plt.show()
def k_means(X, k, max_iter=100):
# 隨機選擇k個點作為初始質心
centroids = X[np.random.choice(len(X), k, replace=False)]
for i in range(max_iter):
# 計算每個資料點與k個質心的距離
distances = np.linalg.norm(X[:, np.newaxis, :] - centroids, axis=-1)
# 將資料點劃分到距離最近的質心所在的簇
labels = np.argmin(distances, axis=1)
# 對於每個簇,重新計算該簇內所有資料點的均值,將該均值作為新的質心
new_centroids = np.array([X[labels == j].mean(axis=0) for j in range(k)])
# 如果質心沒有變化,則停止迭代
if np.allclose(new_centroids, centroids):
break
centroids = new_centroids
return labels, centroids
if __name__ == '__main__':
labels, centroids = k_means(X=X, k=4)
plot_data(X, labels)
plot_centers(centroids)