说这算法之前的话,前期的准备工作,请看我前面的博客。上一篇,我说到了K-means聚类算法,但是有很多的不足,有很多能够改进的地方,例如,怎样使得聚类效果达到全局最优(可能的最好结果)呢?
那么接下来的二分K-means算法就来解决这个问题了。
一、二分K-means算法
二分K均值算法的基本思想:首先将所有的点作为一个簇来对待,并对这个簇进行K均值聚类,然后计算划分开的两个簇的总误差平方和SSE(Sum of Squared Error),将SSE较小的那个簇经行划分,以此类推,每次repeat对每个Current簇经行SSE比较,每次都是对最小SSE的簇划分(这样好贪心啊),最后当簇的个数达到K值的时候,那么整个循环就over了,我们的聚类也是完成了,最后就是显示结果了。
算法伪代码如下:
##############################################################################
###########################################################################
将所有的点看成一个簇
当簇的数目小于K时
对于每一个簇
计算总误差
在给定的簇上面进行K均值聚类(K=2)
计算将该簇一分为二后的总误差
选择使得误差最小的那个簇进行划分操作
############################################################################################
二、python实现
数据集和需要的包和安装过程,我前面的博客中都有了详细的讲解,因为二分K-means的基础还是K聚类,所以我把他们放一起了,这样的话,统一的接口,统一的数据类型,这真是极好的,接下来,我就直接贴代码了。
k-means.py
###########################################################################
def euclDistance1(point1,point2):
b=sum(np.power(point1-point2,2))
return
np.sqrt(b[0,0]+b[0,1])
#init points with random using list
def initPoints1(tt,k):
num,dim=tt.shape
points=np.zeros((k,dim))
r_list=range(0,80)
b_list=random.sample (r_list,k)
for
i in range(k):
index1=int(random.uniform (0,num))
points[i,:]=tt[index1,:]
return
points
#kmeans cluster using list
def
kmeans1(tt,k):
clusterState=True
clusterAssment=np.zeros([len(tt),2])
points=initPoints1(tt,k)
while
clusterState:
clusterState=False
for i in range(len(tt)):
minDist=euclDistance1(points[0,:], tt[i,:])
#print(minDist)
#minDist=100000.0
minIndex=0
for j in range(k):
distance = euclDistance1(points[j,:],tt[i,:])
if distance < minDist:
minDist=distance
minIndex=j
#calculate the count of each cluster
#update cluster
if clusterAssment[i, 0] != minIndex:
clusterState = True
clusterAssment[i, :] = minIndex, minDist**2
for j in range(k):
sumX=0