二分的kmeans、Kmeans++、

本文详细介绍了二分KMeans算法的思想,包括其降低聚类代价函数的原则,以及如何选择划分的簇。同时,讨论了二分KMeans的时间复杂度,并与K-means进行了比较。此外,还提到了KMeans++算法,这是一种为了解决K-Means初始化问题而提出的改进方法,其选择聚类中心的策略确保了点与已有中心的距离较远,提高了聚类质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.二分KMeans:    

        算法的主要思想是:首先将所有点作为一个簇,然后将该簇一分为二。之后选择能最大限度降低聚类代价函数(也就是误差平方和)的簇划分为两个簇。以此进行下去,直到簇的数目等于用户给定的数目k为止。以上隐含的一个原则就是:因为聚类的误差平方和能够衡量聚类性能,该值越小表示数据点越接近于他们的质心,聚类效果就越好。所以我们就需要对误差平方和最大的簇进行再一次划分,因为误差平方和越大,表示该簇聚类效果越不好,越有可能是多个簇被当成了一个簇,所以我们首先需要对这个簇进行划分。


伪代码:

初始化簇表,使之包含由所有的点组成的簇。
repeat
   {对选定的簇进行多次二分试验}
   for i=1 to 试验次数 do
       使用基本k均值,二分选定的簇。
   endfor
   从二分试验中选择具有最小误差的两个簇。
   将这两个簇添加到簇表中。
until 簇表中包含k个簇


1.k值与整体误差平方和的关系:

    k值越大,划分越细,(x-x1)越小,则整体误差平方和越小;

    所以,k值固定时,“误差平方和”可以量化聚类效果;

    轮廓系数可以比较不同k值下划分效果,ai表示簇内距离,bi表示簇外距离,

    一般情况下,k值增大(=2,3,4,5...)会使轮廓系数,先增大,后减小,慢慢接近0;不同情况下,临界点不同;

2.二分kmeans算法过程中,可以k=1,2,3....的结果,

所以,当你不知道分成几个簇的时候,可以使用二分kmeans算法;

算法意图在于得到k=2,3...时,整体SSE(簇内误差平方和)最小的结果;


3.每次选择要划分的簇时,简单的操作:

以下是使用KMeansKMeans++二分K均值算法对图像进行分割的Python代码: ```python import numpy as np from PIL import Image from sklearn.cluster import KMeans import matplotlib.pyplot as plt # 加载图像 img = np.array(Image.open('test.jpg')) # 将图像转换为二维数组 X = img.reshape(-1, 3) # 定义KMeansKMeans++二分K均值算法函数 def kmeans(X, K): kmeans = KMeans(n_clusters=K, init='random') return kmeans.fit_predict(X) def kmeans_plus(X, K): kmeans = KMeans(n_clusters=K, init='k-means++') return kmeans.fit_predict(X) def bisecting_kmeans(X, K): labels = np.zeros((X.shape[0], 1)) centers = [np.mean(X, axis=0, keepdims=True)] for k in range(1, K): max_sse = -1 max_idx = -1 for i in range(len(centers)): c = X[labels == i, :] sse = np.sum((c - centers[i])**2) if sse > max_sse: max_sse = sse max_idx = i kmeans = KMeans(n_clusters=2, init='random') c1, c2 = kmeans.fit_predict(X[labels == max_idx, :]) labels[labels == max_idx] = len(centers) labels[c1] = max_idx labels[c2] = len(centers) centers[max_idx] = np.mean(X[labels == max_idx, :], axis=0, keepdims=True) centers.append(np.mean(X[labels == len(centers), :], axis=0, keepdims=True)) return labels.flatten() # 调用KMeansKMeans++二分K均值算法函数 labels1 = kmeans(X, K=4) labels2 = kmeans_plus(X, K=4) labels3 = bisecting_kmeans(X, K=4) # 将聚类结果转换为图像 img1 = labels1.reshape(img.shape[:2]) img2 = labels2.reshape(img.shape[:2]) img3 = labels3.reshape(img.shape[:2]) # 可视化聚类结果 plt.subplot(131) plt.imshow(img1) plt.title('KMeans') plt.axis('off') plt.subplot(132) plt.imshow(img2) plt.title('KMeans++') plt.axis('off') plt.subplot(133) plt.imshow(img3) plt.title('Bisecting KMeans') plt.axis('off') plt.show() ``` 在这个代码中,我们首先使用PIL库加载一张RGB图像,并将其转换为二维数组X。然后,我们定义了三个函数kmeans()、kmeans_plus()和bisecting_kmeans(),分别使用KMeansKMeans++二分K均值算法对数据进行聚类,并返回聚类结果。在函数中,我们使用sklearn库的KMeans类来实现聚类,并将聚类结果转换为一维标签。对于二分K均值算法,我们使用了一个循环来逐步将聚类中心数量增加到K,并使用KMeans类对每个簇进行二分聚类。最后,我们将聚类结果转换为与原始图像相同大小的图像,并使用matplotlib库将三个聚类结果可视化。 运行上述代码,我们可以看到使用KMeansKMeans++二分K均值算法对图像进行聚类的结果。其中,KMeansKMeans++的效果比较相似,都能较好地区分出图像的不同区域;而二分K均值算法的效果稍差,可能是由于算法本身的限制导致。最终的聚类结果可视化图如下: ![image.png](https://cdn.nlark.com/yuque/0/2021/png/236174/1632923994741-92e9c6a1-06c9-4c17-84b9-8aa1d54b0a5c.png#clientId=u7b8f5e57-1c4c-4&from=paste&height=380&id=u6a1c8c98&margin=%5Bobject%20Object%5D&name=image.png&originHeight=380&originWidth=1140&originalType=binary&ratio=1&size=190473&status=done&style=none&taskId=u4c69c9c3-a4b0-4db6-9c4d-7a6e26b12b7)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值