机器学习(聚类四)——K-Means的优化算法

K-Means算法是最基本的一种聚类算法,也会有一些问题,前面的博客《机器学习(聚类二)——K-Means》中有介绍,这里就不详细说了。下面介绍一下典型的优化算法:

优化算法

1)K-Mediods聚类(K中值聚类)

K-means算法在迭代的过程中使用所有点的均值作为新的质点(中心点),如果簇中存在异常点,将导致均值偏差比较严重。比如一个簇中有2、4、6、8、100五个数据,那么新的质点为24,显然这个质点离绝大多数点都比较远;在当前情况下,使用中位数6可能比使用均值的想法更好,使用中位数的聚类方式叫做 K-Mediods聚类(K中值聚类)

2)二分K-Means算法
解决K-Means算法对初始簇心比较敏感的问题,二分K-Means算法是一种弱化初始质心的一种算法,具体思路步骤如下:

  • 将所有样本数据作为一个簇放到一个队列中
  • 从队列中选择一个簇进行K-means算法划分,划分为两个子簇,并将子簇添加到队列中
  • 循环迭代第二步操作,直到中止条件达到(聚簇数量、最小平方误差、迭代次数等)
  • 队列中的簇就是最终的分类簇集合

从队列中选择划分聚簇的规则一般有两种方式;分别如下:

  • 对所有簇计算误差和SSE(SSE也可以认为是距离函数的一种变种),选择SSE最大的聚簇进行划分操作(优选这种策略)
    S S E = ∑ i = 1 n w i ( x ⃗ i − a ⃗ x i ) ,     w i 表 示 对 应 的 权 重 SSE=\sum_{i=1}^n w_i(\vec{x}_i-\vec{a}_{x_i}), \,\,\, w_i 表示对应的权重 SSE=i=1nwi(x ia xi),wi
  • 选择样本数据量最多的簇进行划分操作

图示
在这里插入图片描述

3)K-Means++
解决K-Means算法对初始簇心比较敏感的问题,K-Means++算法和K-Means算法的区别主要在于初始的K个中心点的选择方面,K-Means算法使用随机给定的方式,K-Means++算法采用下列步骤给定K个初始质点:

  • 从数据集中任选一个节点作为第一个聚类中心
  • 对数据集中的每个点x,计算x到所有已有聚类中心点的距离和D(X),基于D(X)采用线性概率选择出下一个聚类中心点(距离较远的一个点成为新增的一个聚类中心点,为什么不是最远的点?防止异常点)
  • 重复步骤2直到找到k个聚类中心点

缺点:由于聚类中心点选择过程中的内在有序性,在扩展方面存在着性能方面的问题(第k个聚类中心点的选择依赖前k-1个聚类中心点的值)

4)K-Means||
解决K-Means++算法缺点而产生的一种算法。
主要思路是改变每次遍历时候的取样规则,并非按照K-Means++算法每次遍历只获取一个样本,而是每次获取K个样本,重复该取样操作O(logn)次,然后再将这些抽样出来的样本聚类出K个点,最后使用这K个点作为K-Means算法的初始聚簇中心点。实践证明:一般5次重复采用就可以保证一个比较好的聚簇中心点。
样本稀疏了,质点变化会更剧烈。效率也会更高。

5)Canopy算法
Canopy算法属于一种“粗”聚类算法,执行速度较快,但精度较低,算法执行步骤如下:

  • 给定样本列表 L = x 1 , x 2 . . . , x m L=x_1 ,x_2 ...,x_m L=x1,x2...,xm 以及先验值 r 1 r_1 r1 r 2    ( r 1 > r 2 ) r_2 \,\,(r_1 >r_2 ) r2(r1>r2)
  • 从列表L中获取一个节点P,计算P到所有聚簇中心点的距离(如果不存在聚簇中心,那么此时点P形成一个新的聚簇),并选择出最小距离 D ( P , a j ) D(P,a_j ) D(P,aj)
  • 如果距离D小于 r 1 r_1 r1,表示该节点属于该聚簇,添加到该聚簇列表中
  • 如果距离D小于 r 2 r_2 r2,表示该节点不仅仅属于该聚簇,还表示和当前聚簇中心点非常近,所以将该聚簇的中心点设置为该簇中所有样本的中心点,并将P从列表L中删除
  • 如果距离D大于 r 1 r_1 r1,那么节点P形成一个新的聚簇
  • 直到列表L中的元素数据不再有变化或者元素数量为0的时候,结束循环操作

Canopy算法过程图形说明
在这里插入图片描述
Canopy算法得到的最终结果的值,聚簇之间是可能存在重叠的,但是不会存在某个对象不属于任何聚簇的情况。
在这里插入图片描述
由于K-Means算法存在初始聚簇中心点敏感的问题,常用使用Canopy 和 K-Means算法混合形式进行模型构建

  • 先使用canopy算法进行“粗”聚类得到K个聚类中心点
  • K-Means算法使用Canopy算法得到的K个聚类中心点作为初始中心点,进行“细”聚类

优点:

  • 执行速度快(先进行了一次聚簇中心点选择的预处理)
  • 不需要给定K值,应用场景多
    能够缓解K-Means算法对于初始聚类中心点敏感的问题

:目前的sklearn中没有相应的API

6)Mini Batch K-Means算法(与k-means||类似)
Mini Batch K-Means算法是K-Means算法的一种优化变种,采用小规模的数据子集(每次训练使用的数据集是在训练算法的时候随机抽取的数据子集)减少计算时间,同时试图优化目标函数;Mini Batch K-Means算法可以减少K-Means算法的收敛时间,而且产生的结果效果只是略差于标准K-Means算法。(可以说二者唯一的区别就是采样:全部和部分)

算法步骤如下:

  • 首先抽取部分数据集,使用K-Means算法构建出K个聚簇点的模型
  • 继续抽取训练数据集中的部分数据集样本数据,并将其添加到模型中,分配给距离最近的聚簇中心点
  • 更新聚簇的中心点值
  • 循环迭代第二步和第三步操作,直到中心点稳定或者达到迭代次数,停止计算操作

:这里提到了6种算法:

  • 特殊值(离群值)对模型的影响比较大,可用K中值聚类
  • 其他的算法,二分K-Means算法、K-Means++、K-Means||(K-Means++的升级版)、Canopy算法以及Mini Batch K-Means算法,都能在一定程度上解决K-Means初值敏感的问题。其中Mini Batch K-Means算法,还能明显地提升速度。

代码实现

这里只实现K-Means和Mini Batch K-Means算法比较案例。基于scikit包中的创建模拟数据的API创建聚类数据,使用K-means算法和MiniBatch K-Means算法对数据进行分类操作,比较这两种算法的聚类效果以及聚类的消耗时间长度。

API

class sklearn.cluster.KMeans(n_clusters=8, init=‘k-means++’, n_init=10, max_iter=300, tol=0.0001, precompute_distances=‘auto’, verbose=0, random_state=None, copy_x=True, n_jobs=None, algorithm=‘auto’)[source]

class sklearn.cluster.MiniBatchKMeans(n_clusters=8, init=‘k-means++’, max_iter=100, batch_size=100, verbose=0, compute_labels=True, random_state=None, tol=0.0, max_no_improvement=10, init_size=None, n_init=3, reassignment_ratio=0.01)[source]

参数,基本同kmeans

  • batch_size,每次的样本数

代码

import time  
import numpy as np  
import matplotlib.pyplot as plt  
import matplotlib as mpl
from sklearn.cluster import MiniBatchKMeans, KMeans  
from sklearn.metrics.pairwise import pairwise_distances_argmin  
from sklearn.datasets.samples_generator import make_blobs 

## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

#初始化三个中心
centers = [[1, 1], [-1, -1], [1, -1]] 
clusters = len(centers)  #聚类的数目为3    
#产生3000组二维的数据,中心是意思三个中心点,标准差是.7
X, Y = make_blobs(n_samples=3000, centers=centers, cluster_std=0.7, random_state=28) 

#构建kmeans算法
k_means = KMeans(init='k-means++', n_clusters=clusters, random_state=28)
t0 = time.time() #当前时间
k_means.fit(X)  #训练模型
km_batch = time.time() - t0  #使用kmeans训练数据的消耗时间
print ("K-Means算法模型训练消耗时间:%.4fs" % km_batch)

K-Means算法模型训练消耗时间:0.0811s

构建MiniBatchKMeans算法
batch_size = 100
mbk = MiniBatchKMeans(init='k-means++', n_clusters=clusters, batch_size=batch_size, random_state=28)  
t0 = time.time()  
mbk.fit(X)  
mbk_batch = time.time() - t0  
print ("Mini Batch K-Means算法模型训练消耗时间:%.4fs" % mbk_batch)

Mini Batch K-Means算法模型训练消耗时间:0.0560s

Mini Batch K-Means算法要更快一些。

#预测结果
km_y_hat = k_means.predict(X)
mbkm_y_hat = mbk.predict(X)

print(km_y_hat[:10])
print(mbkm_y_hat[:10])
print(k_means.cluster_centers_)
print(mbk.cluster_centers_)

[0 2 2 2 2 1 0 0 2 2]
[1 0 0 0 0 2 1 1 0 0]
[[-1.0600799 -1.05662982]
[ 1.02975208 -1.07435837]
[ 1.01491055 1.02216649]]
[[ 0.99602094 1.10688195]
[-1.00828286 -1.05983915]
[ 1.07892315 -0.94286826]]

##获取聚类中心点并聚类中心点进行排序
k_means_cluster_centers = k_means.cluster_centers_#输出kmeans聚类中心点
mbk_means_cluster_centers = mbk.cluster_centers_#输出mbk聚类中心点
print ("K-Means算法聚类中心点:\ncenter=", k_means_cluster_centers)
print ("Mini Batch K-Means算法聚类中心点:\ncenter=", mbk_means_cluster_centers)
order = pairwise_distances_argmin(k_means_cluster_centers,  
                                  mbk_means_cluster_centers) 
#方便后面画图
order

K-Means算法聚类中心点:
center= [[-1.0600799 -1.05662982]
[ 1.02975208 -1.07435837]
[ 1.01491055 1.02216649]]
Mini Batch K-Means算法聚类中心点:
center= [[ 0.99602094 1.10688195]
[-1.00828286 -1.05983915]
[ 1.07892315 -0.94286826]]

array([1, 2, 0], dtype=int64)

## 画图
plt.figure(figsize=(12, 6), facecolor='w')
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.9)
cm = mpl.colors.ListedColormap(['#FFC2CC', '#C2FFCC', '#CCC2FF'])
cm2 = mpl.colors.ListedColormap(['#FF0000', '#00FF00', '#0000FF'])
#子图1:原始数据
plt.subplot(221)
plt.scatter(X[:, 0], X[:, 1], c=Y, s=6, cmap=cm, edgecolors='none')
plt.title(u'原始数据分布图')
plt.xticks(())
plt.yticks(())
plt.grid(True)
#子图2:K-Means算法聚类结果图
plt.subplot(222)
plt.scatter(X[:,0], X[:,1], c=km_y_hat, s=6, cmap=cm,edgecolors='none')
plt.scatter(k_means_cluster_centers[:,0], k_means_cluster_centers[:,1],c=range(clusters),s=60,cmap=cm2,edgecolors='none')
plt.title(u'K-Means算法聚类结果图')
plt.xticks(())
plt.yticks(())
plt.text(-3.8, 3,  'train time: %.2fms' % (km_batch*1000))  
plt.grid(True)
#子图三Mini Batch K-Means算法聚类结果图
plt.subplot(223)
plt.scatter(X[:,0], X[:,1], c=mbkm_y_hat, s=6, cmap=cm,edgecolors='none')
plt.scatter(mbk_means_cluster_centers[:,0], mbk_means_cluster_centers[:,1],c=range(clusters),s=60,cmap=cm2,edgecolors='none')
plt.title(u'Mini Batch K-Means算法聚类结果图')
plt.xticks(())
plt.yticks(())
plt.text(-3.8, 3,  'train time: %.2fms' % (mbk_batch*1000))  
plt.grid(True)

#
different = list(map(lambda x: (x!=0) & (x!=1) & (x!=2), mbkm_y_hat))
for k in range(clusters):  
    different += ((km_y_hat == k) != (mbkm_y_hat == order[k]))
identic = np.logical_not(different)
different_nodes = len(list(filter(lambda x:x, different)))

plt.subplot(224)
# 两者预测相同的
plt.plot(X[identic, 0], X[identic, 1], 'w', markerfacecolor='#bbbbbb', marker='.')  
# 两者预测不相同的
plt.plot(X[different, 0], X[different, 1], 'w', markerfacecolor='m', marker='.')  
plt.title(u'Mini Batch K-Means和K-Means算法预测结果不同的点')  
plt.xticks(())  
plt.yticks(())
plt.text(-3.8, 2,  'different nodes: %d' % (different_nodes))  

plt.show()

最后看一下显示效果:
在这里插入图片描述

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: K-Means 聚类算法是一种常用的无监督学习算法,它可以将数据集划分为 K 个不同的类别,其中 K 是预先设定的。在 K-Means 算法中,我们需要指定 K 值和距离计算方法,然后通过迭代的方式不断调整聚类中心,直到达到某个停止准则为止。 下面我们以鸢尾花数据集为例,来实现 K-Means 聚类算法。 首先,我们需要导入数据集并进行预处理。这里我们使用 sklearn 中的 load_iris 函数来加载数据集,并使用 MinMaxScaler 对数据进行归一化处理: ``` python from sklearn.datasets import load_iris from sklearn.preprocessing import MinMaxScaler # 加载数据集 iris = load_iris() X = iris.data # 数据归一化 scaler = MinMaxScaler() X = scaler.fit_transform(X) ``` 接下来,我们需要实现 K-Means 算法。这里我们使用 scikit-learn 中的 KMeans 类来实现: ``` python from sklearn.cluster import KMeans # 设置 K 值 k = 3 # 初始化 KMeans 模型 kmeans = KMeans(n_clusters=k) # 训练模型并预测结果 y_pred = kmeans.fit_predict(X) ``` 最后,我们可以使用 Matplotlib 来可视化聚类结果: ``` python import matplotlib.pyplot as plt # 绘制聚类结果 plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.title("K-Means Clustering") plt.show() ``` 运行以上代码,即可得到鸢尾花数据的聚类结果。 ### 回答2: K-Means聚类算法是一种常用的无监督学习方法,能够对数据进行聚类。在K-Means算法中,通过计算数据点与聚类中心的距离,将数据点归类到距离最近的聚类中心,从而实现数据的聚类。 鸢尾花数据是机器学习中常用的数据集之一,包含了150个样本,每个样本有4个特征,分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。这些样本被分为三个类别,分别是山鸢尾、变色鸢尾和维吉尼亚鸢尾。 使用K-Means聚类算法对鸢尾花数据进行聚类的过程如下: 1. 随机选择K个初始聚类中心。K代表要将数据聚成的类别数,这里我们选择K=3,即将鸢尾花数据聚成3个类别。 2. 对每个数据点,计算其与各个聚类中心的距离,并将其归类到距离最近的聚类中心。 3. 更新每个聚类中心的位置,将其移动到所归类数据点的平均位置。 4. 重复步骤2和3,直到聚类中心不再发生变化或达到预定的迭代次数。 通过上述步骤,可以将鸢尾花数据聚类成3个类别。每个类别中的数据点具有相似的特征,并且与其他类别中的数据点的特征有较大的区别。 K-Means聚类算法的优点是简单易实现,计算效率高。然而,这种算法对初始聚类中心的选择较为敏感,可能会收敛到局部最优解。因此,在应用K-Means算法时,需要进行多次实验,以避免得到不理想的聚类结果。同时,K-Means算法对于离群点比较敏感,离群点可能会影响聚类结果的准确性。 ### 回答3: K-Means 聚类算法是一种常用的无监督学习算法,主要用于将数据集中的样本划分成不同的簇。下面以实现鸢尾花数据的聚类为例进行解释。 首先,我们需要加载鸢尾花数据集,该数据集包含了150个样本,每个样本有4个特征,分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。我们将这些样本表示为一个150x4的矩阵。 然后,我们需要确定簇的数量 k,即要将数据集划分成几个簇。在这里,我们可以根据经验或者领域知识来选择一个合适的值。 接下来,我们需要初始化 k 个簇的中心点。可以随机从数据集中选取 k 个样本作为初始的簇中心点。 然后,对于每个样本,我们计算其与各个簇中心点的距离,并将其分配给距离最近的簇中心点所在的簇。 接着,我们更新每个簇的中心点,即将每个簇中的样本的特征均值作为新的簇中心点。 最后,我们重复执行以上两个步骤,直到簇中心点不再发生变化,或者到达预定的迭代次数。 完成聚类后,我们可以根据簇的中心点和每个样本所属的簇来进行结果的分析和可视化。例如,可以绘制不同簇中心点的特征值分布图,以及将样本点按簇的标签进行颜色分类的散点图等。 K-Means 聚类算法能够有效地将数据集划分为不同的簇,实现了对样本的聚类。在鸢尾花数据集这个例子中,我们可以根据花萼和花瓣的特征值将鸢尾花分为不同的类别,从而更好地了解这些花的分类情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值