原理:
- 目标:将样本集合划分为 K 个互不相交的子集,每个子集代表一个聚类。
- 初始化:随机选择 K 个样本作为初始聚类中心。
- 迭代优化:重复以下步骤,直到收敛:
- 将每个样本分配到最近的聚类中心所在的类别中。
- 计算每个聚类中心的均值,作为新的聚类中心。
- 收敛条件:当聚类中心不再发生变化,或者变化很小,算法收敛。
数学公式:
- 样本表示:假设有 m 个样本,每个样本有 n 个特征,用 表示第 i 个样本, ∈。
- 聚类中心表示:假设有 K 个聚类中心,用 表示第 k 个聚类中心,μ∈。
- 样本到聚类中心的距离:通常使用欧氏距离或其他距离度量。样本 到聚类中心μ 的距离表示为 ∣∣−μ∣∣。
- 样本分配:将样本 分配给与之最近的聚类中心 ,即选择使得 ∣∣−μ𝑘∣∣最小的聚类中心。
- 聚类中心更新:每个聚类的中心更新为该聚类中所有样本的均值,即 μ𝑘=∑𝑖∈,其中 是属于第 k 个聚类的样本集合。
优化目标:
K-Means 的优化目标是最小化样本到所属聚类中心的距离之和(称为误差平方和,SSE): 𝐽(,…,,𝜇,…,𝜇)=∣∣−𝜇∣∣其中:
- 表示样本 所属的聚类中心的索引。
- 𝜇 表示样本 所属的聚类中心。
K-Means 算法通过迭代优化这个目标函数,不断更新聚类中心,直到收敛到局部最优解。
实现代码:
# 文件功能: 实现 K-Means 算法
import random
from scipy import spatial
import matplotlib.pyplot as plt
import numpy as np
class K_Means(object):
# k是分组数;tolerance‘中心点误差’;max_iter是迭代次数
def __init__(self, n_clusters=2, tolerance=0.0001, max_iter=300):
self.k_ = n_clusters
self.tolerance_ = tolerance
self.max_iter_ = max_iter
def fit(self, datas):
# step 1.选择k个点作为聚类的中心
self.centers_ = datas[random.sample(range(datas.shape[0]),self.k_)]
old_centers = np.copy(self.centers_)
leaf_size = 1
k = 1
for i in range(self.max_iter_):
# step 2.求出查询点到中心的最近距离
labels = [[]for i in range(self.k_)]
root = spatial.KDTree(self.centers_,leafsize=leaf_size)
print("Kmeans iterator",i)
for i in range(datas.shape[0]):
_,query_index = root.query(datas[i],k) #返回距离哪个中心点最近
labels[query_index].append(datas[i])
for i in range(self.k_):
points = np.array(labels[i])
self.centers_[i] = points.mean(axis=0)
if np.sum(np.abs(self.centers_ - old_centers)) < self.tolerance_ * self.k_:
break
old_centers = np.copy(self.centers_)
self.fitted = True
def predict(self, p_datas):
result = []
if not self.fitted:
print("Unfitter.")
return result
for point in p_datas:
diff = np.linalg.norm(self.centers_ - point,axis=1)
result.append(np.argmin(diff))
return result
if __name__ == '__main__':
x = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])
k_means = K_Means(n_clusters=2)
k_means.fit(x)
cat = k_means.predict(x)
color = np.array(['r', 'g'])
cats = np.array(cat)
print(cats.shape)
plt.figure(figsize=(10, 10))
plt.title(u"scatter clustter after kmeans")
plt.scatter(x[:, 0], x[:, 1], c=color[cats])
plt.show()
print(cat)