K-Means||算法
K-Means||
算法是为了解决K-Means++
算法缺点而产生的一种算法;
主要思路是改变每次遍历时候的取样规则,并非按照K-Means++
算法每次遍历只获取一个样本,而是每次获取K个样本,重复该取样操作O(logn)次**(n是样本的个数)**,然后再将这些抽样出来的样本聚类出K个点,最后使用这K个点作为K-Means算法的初始聚簇中心点。实践证明:一般5次重复采用就可以保证一个比较好的聚簇中心点。
整体步骤
- 在N个样本中抽K个样本,一共抽log(n)次,形成一个新的样本集,一共有K*log(n)个数据。
- 在新数据集中使用
K-Means
算法,找到K个聚簇中心。 - 把这K个聚簇中心放到最初的样本集中,作为初始聚簇中心。
- 原数据集根据上述初始聚簇中心,再用
K-Means
算法计算出最终的聚簇。
伪代码
采用了一个采样因子l,第1步随机初始化一个中心点,第2-6步计算出满足概率条件的多个候选中心点C,候选中心点的个数可能大于k个,所以通过第7-8步来处理。第7步给C中所有点赋予一个权重值
w
x
w_x
wx,这个权重值表示距离x点最近的点的个数。第8步使用k-means
算法聚类出这些候选点的k个聚类中心。
Canopy算法
Canopy算法属于一种“粗”聚类算法,速度较快,但精度较低。 与传统的聚类算法(如K-Means)不同,Canopy聚类最大的特点是不需要事先指定k值(即聚类的个数),因此具有很大的实际应用价值。
步骤如下:
- 给定样本列表 L = x 1 , x 2 , … , x m L=x_1,x_2,\dots,x_m L=x1,x2,…,xm以及初始距离阈值为 T 1 、 T 2 , 且 ( T 1 > T 2 ) T1、T2,且(T1>T2) T1、T2,且(T1>T2)(T1、T2可自己定义);
- 从列表L中任取一点P,计算P到所有聚簇中心点的距离(如果不存在聚簇中心,那么就把点P作为一个新的聚簇),并选出与聚类中心最近的距离 D ( P , a j ) D(P,a_j) D(P,aj);
- 如果距离D小于T1,表示该节点属于该聚簇,添加到该聚簇列表中。
- 如果距离D小于T2,表示该节点不仅仅属于该聚簇,还表示和当前聚簇中心点非常近,所以将P从列表L中删除。
- 如果距离D大于T1,那么节点P形成一个新的聚簇。
- 重复步骤2-5,直到列表L为空时结束循环。
Canopy算法得到的最终结果的值,聚簇之间是可能存在重叠的,但是不会存在某个对象不属于任何聚簇的情况。
Canopy算法过程图形说明
Canopy+ K-Means聚类算法
由于K-Means
算法存在初始聚簇中心点敏感的问题,常用使用Canopy+K-Means
算法进行模型构建,这种形式聚类算法聚类效果良好。
步骤
- 先使用
Canopy
算法进行“粗”聚类得到K个聚类中心点。 - 再使用
K-Means
算法,并用Canopy
算法得到的K
个聚类中心点作为初始中心点,进行“细”聚类。
优点
- 执行速度快(先进行了一次聚簇中心点选择的预处理);
- 不需要给定
K
值,应用场景多; - 能够缓解
K-Means
算法对于初始聚类中心点敏感的问题。
Mini Batch K-Means算法
Mini Batch K-Means
算法是K-Means
算法的一种优化变种,采用小规模的数据子集(每次训练使用的数据集是在训练算法的时候随机抽取的数据子集)减少计算时间,同时试图优化目标函数;Mini Batch K-Means
算法可以减少K-Means
算法的收敛时间,而且产生的结果效果只是略差于标准K-Means
算法。
步骤
- 首先抽取部分数据集,使用
K-Means
算法构建出K个聚簇点的模型; - 继续抽取训练数据集中的部分数据集样本数据,并将其添加到模型中,分配给距离最近的聚簇中心点;
- 更新聚簇的中心点值;
- 重复2-3步,直到中心点稳定或者达到迭代次数为止。
Python实现
import time
import matplotlib.pyplot as plt
import matplotlib
from sklearn.cluster import MiniBatchKMeans
from sklearn.datasets import make_blobs # 导入产生模拟数据的方法
matplotlib.rcParams['font.sans-serif'] = [u'SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False
# 生成模拟数据
k = 5 # 给定聚类数量
X, Y = make_blobs(n_samples=1000, n_features=2, centers=k, random_state=1)
s = time.time()
km = MiniBatchKMeans(n_clusters = k, batch_size = 100)
km.fit(X)
print("用sklearn内置的Mini Batch K-Means算法聚类耗时:", time.time() - s)
label_pred = km.labels_ # 获取聚类后的样本所属簇对应值
centroids = km.cluster_centers_ # 获取簇心
# 绘制Mini Batch K-Means结果
# 未聚类前的数据分布
plt.subplot(121)
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.title("未聚类前的数据分布")
plt.subplots_adjust(wspace=0.5)
plt.subplot(122)
plt.scatter(X[:, 0], X[:, 1], c=label_pred, s=50, cmap='viridis')
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='o', s=100)
plt.title("Mini Batch K-Means算法聚类结果")
plt.show()
运行结果
总结: Mini Batch K-Means
算法比 K-Means
算法运行的时间大大减少,并且效果也差不多。