机器学习之聚类算法/Bisecting K-Means算法
来源:互联网 发布:上市公司数据分析 编辑:程序博客网 时间:2024/06/04 18:37
前面文章机器学习之聚类算法——K-Means算法分享了K-Means算法,文章最后总结了其缺点及解决方法。如下:
1)首先,K-Means算法只能找到局部最优的聚类,而不是全局最优的聚类。而且算法的结果非常依赖于初始随机选择的聚类中心的位置。我们通过多次运行算法,使用不同的随机生成的聚类中心点运行算法,然后对各自结果C通过evaluate(C)函数进行评估,选择多次结果中evaluate(C)值最小的那一个。
2)关于初始k值选择的问题。首先的想法是,从一个起始值开始,到一个最大值,每一个值运行k-means算法聚类,通过一个评价函数计算出最好的一次聚类结果,这个k就是最优的k。然而,k越大,聚类中心越多,显然每个观测点距离其中心的距离的平方和会越小,这在实践中也得到了验证。
3)关于性能问题。原始的算法,每一次迭代都要计算每一个观测点与所有聚类中心的距离。有没有方法能够提高效率呢?是有的,可以使用k-d tree或者ball tree这种数据结构来提高算法的效率。特定条件下,对于一定区域内的观测点,无需遍历每一个观测点,就可以把这个区域内所有的点放到距离最近的一个聚类中去。
经典的k均值聚类有很大的缺点就是很容易收敛到局部最优,而没有考虑全局的最小化,影响聚类性能,为了避免这种局部最优,有前辈提出了Bisecting k-Means算法(也叫二分K-均值算法)。
对于Bisecting k-Means算法,这里选择一种全局最小值的度量方法,SSE(sum of squared error)。SSE越小,所有的节点距离它们的中心点越近。
算法原理:开始时只有一个聚类,然后将其分割为两个聚类,分割之后根据SSE最小化原则从所有聚类中选择一个聚类继续进行分割,直到聚类个数达到K。
选择哪一个簇进行划分取决于是否可以最大程度降低SSE的值。上述基于SSE的划分过程不断重复,直到得到用户指定的簇数目为止。
以上隐含着一个原则是:
因为聚类的误差平方和能够衡量聚类性能,该值越小表示数据点月接近于它们的质心,聚类效果就越好。所以我们就需要对误差平方和最大的簇进行再一次的划分,因为误差平方和越大,表示该簇聚类越不好,越有可能是多个簇被当成一个簇了,所以我们首先需要对这个簇进行划分。
关于二分K-means的优点《Machine Learning in Action》说的是能够克服K-means收敛于局部最小,但是想了一下感觉这个并不能保证收敛到全局最优值(而且后面运行代码结果也会出现不太好的情况,不知道这算不算是个证据)
通过查阅一些资料和总结,二分K-means聚类的优点有:
二分K均值算法可以加速K-means算法的执行速度,因为它的相似度计算少了。
不受初始化问题的影响,因为这里不存在随机点的选取,且每一步都保证了误差最小。
所以说这个算法也并不能够保证完全不受K的影响一定归到全局最小,只是相对较优,并且还有了一定的速度提升。理解有偏差欢迎指正。
伪代码如下:
Start with all the points in one clusterWhile the number of clusters is less than k for every clustermeasure total errorperform k-means clustering with k=2 on the given clustermeasure total error after k-means has split the cluster in two choose the cluster split that gives the lowest error and commit this split
里面主要用到了函数
biKmeans(dataSet, k, distMeas=distEclud)
实现了二分算法,大致的思路是:
1.初始化全部点的质心,并建立所需要的数据存储结构
2.对每一个簇尝试二分(最开始就是一个簇),选出最好的
3.更新各个簇的元素个数
biKmeans的代码实现如下:(《机器学习实战》中提供了该代码)
def biKmeans(dataSet, k, distMeas=distEclud):
m = shape(dataSet)[0]
clusterAssment = mat(zeros((m,2)))#记录簇分配的结果及误差
centroid0 = mean(dataSet, axis=0).tolist()[0]#计算整个数据集的质心
centList =[centroid0] #create a list with one centroid
for j in range(m):#计算初始聚类点与其他点的距离
clusterAssment[j,1] = distMeas(mat(centroid0), dataSet[j,:])**2
while (len(centList) < k):
lowestSSE = inf
for i in range(len(centList)):#尝试划分每一簇
ptsInCurrCluster = dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]#get the data points currently in cluster i
centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2, distMeas)#对这个簇运行一个KMeans算法,k=2
sseSplit = sum(splitClustAss[:,1])#compare the SSE to the currrent minimum
sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1])
print "sseSplit, and notSplit: ",sseSplit,sseNotSplit
if (sseSplit + sseNotSplit) < lowestSSE:##划分后更好的话
bestCentToSplit = i
bestNewCents = centroidMat
bestClustAss = splitClustAss.copy()
lowestSSE = sseSplit + sseNotSplit
bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList) #更新簇的分配结果change 1 to 3,4, or whatever
bestClustAss[nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit
print 'the bestCentToSplit is: ',bestCentToSplit
print 'the len of bestClustAss is: ', len(bestClustAss)
centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]#replace a centroid with two best centroids
centList.append(bestNewCents[1,:].tolist()[0])
clusterAssment[nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:]= bestClustAss#reassign new clusters, and SSE
return mat(centList), clusterAssment
用了一些数据,测试效果如下:
测试效果还不错。
所以,对于书中的知识也需要辩证的去看,老话说的好,尽信书不如无书啊。
对于大数据集,本文没有将K-Means与Bisecting k-Means算法作过对比,关于大数据集的效果无法下结论。
参考资料
Peter HARRINGTON.机器学习实战[M].李锐,李鹏,曲亚东,王斌译.北京:人民邮电出版社, 2013.
当你的才华撑不起你的野心时,只有静下心来好好学习~
欢迎转发到朋友圈或分享给好友
- 机器学习之聚类算法/Bisecting K-Means算法
- bisecting k-means 算法
- K-均值聚类算法(K-means algorithm) & 二分K-均值算法(Bisecting k-means algorithm)
- Bisecting k-means聚类算法及实现
- 二分K均值(bisecting k-means)算法
- 机器学习:k-Means聚类算法
- 机器学习-K-means聚类算法
- 机器学习之K-means算法:深入浅出K-Means算法
- 机器学习之聚类算法(K-Means)
- 机器学习之聚类算法k-means
- 机器学习之K-means聚类算法
- 机器学习(25)之K-Means聚类算法详解
- 机器学习算法 之 K-Means聚类
- 机器学习之K-means算法
- 【机器学习算法】之K-means聚类
- 机器学习之k-means算法
- 机器学习算法之K-means-spark
- Spark2.0机器学习系列之8: 聚类(k-means,Bisecting k-means,Streaming k-means)
- leetcode_145. Binary Tree Postorder Traversal ? 待解决
- es6学习-let,const
- A02_IO路径管理
- 将Tomcat添加到服务中
- Firefox彻底禁止自动更新
- 机器学习之聚类算法/Bisecting K-Means算法
- [操作系统] 分页系统的实现问题
- Parquet表在spark与Impala间不兼容问题
- B2B2C商城上线小程序的必要性
- startx 及xinit 介绍(经典)
- IDEA报错URI is not registered ( Setting | Project Settings | Schemas and DTDs
- 电阻器不是电阻器---凯利讯半导体
- Linux下redis安装与使用
- iOS_子类集成父类的XIB样式