机器学习实战之K-means

1 算法思想
聚类的基本思想是将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个”簇”(cluster)。划分后,每个簇可能有相同对应的概念(性质)。K-均值算法就是一个使用很广泛的聚类算法,其中的K就表示簇的数量,K-means简单的说就是通过质心来将样本划分成K个不同的簇。
伪代码为:
这里写图片描述
工作流程:
(1)事先选定K个聚类中心
(2)计算待测样本a到每个聚类中心的距离,然后将样本a分配到距离最近的聚类中
(3)计算每个聚类样本的均值来动态更新原聚类质心
(4)不断迭代(2),(3),直到簇质心不再改变。
2 实现

def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = shape(dataSet)[0] #m=80L
    clusterAssment = mat(zeros((m,2)))
    #创造一个m个列表,每个列表中2个元素的全零变量
     #在matlab中相当于创建一个m行2列的矩阵
     #第一列存簇索引值,第二列存当前点到簇质心的距离
    centroids = createCent(dataSet, k)  #随机创建k个簇心
    clusterChanged = True  #创建标注标量,用来达到条件就终止循环
    while clusterChanged:
        clusterChanged = False
        for i in range(m):#遍历每个样本
            minDist = inf  #初始样本到簇质心的距离  nif 表示正无穷;-nif表示负无穷
            minIndex = -1
            for j in range(k):  #遍历每个簇质心
                distJI = distMeas(centroids[j,:],dataSet[i,:])  #计算样本点到簇质心的距离
                if distJI < minDist:    #寻找距离最近的簇质心
                    minDist = distJI
                    minIndex = j   #将样本分配到距离最小的质心那簇
            if clusterAssment[i,0] != minIndex: clusterChanged = True #如果样本分配结果发生变化,更改标志变量
            #如果分配后结果不变,就将结果存入clusterAssment,结束while循环
            clusterAssment[i,:] = minIndex,minDist**2
        print centroids
        for cent in range(k):#遍历每个簇质心
            #找到每个簇质心对应的样本
            ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]#get all the point in this cluster
            centroids[cent,:] = mean(ptsInClust, axis=0) #计算这些样本的均值,作为该簇的新质心
    return centroids, clusterAssment

3 二分K-均值算法
K-means虽然实现很容易,但却很容易收敛到局部最小,达不到全局最小,所以有人提出二分K-均值。二分K-均值简单来说就是将所有数据集分成两簇,然后再选择误差最小的那个簇再进行二分K-均值划分。
二分K-均值伪代码:
这里写图片描述
3.1 实现

def biKmeans(dataSet, k, distMeas=distEclud):
    m = shape(dataSet)[0] #60L
    clusterAssment = mat(zeros((m,2)))
    centroid0 = mean(dataSet, axis=0).tolist()[0] #计算每维的均值  如果axis=1,就是计算每个列表元素的均值
    centList =[centroid0] #用每维均值创建初始簇质心,也就是说,将整个数据集当成一簇
    for j in range(m):#遍历每个样本
        #保存样本到每个簇质心的距离
        #所以此处shape(clusterAssment)=(60L,2L)
        clusterAssment[j,1] = distMeas(mat(centroid0), dataSet[j,:])**2
    while (len(centList) < k):  #如果初始的簇个数小于k
        lowestSSE = inf
        for i in range(len(centList)):   #遍历初始的那簇
            #提取当前簇中的所有样本点
            ptsInCurrCluster = dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]
            #将这些样本点进行kmeans操作,其中K设为2.
            # 也就是说,把之前那簇数据集分成两簇,分别计为:0簇和1簇,同时返回新分成的两簇中的每簇的质心和误差
            #shape(centroidMat)=(2L,2L) shape(splitClustAss)=(60L,2L)
            centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2, distMeas)
            sseSplit = sum(splitClustAss[:,1])# 所有误差相加
            sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1])
            print "sseSplit, and notSplit: ",sseSplit,sseNotSplit
            #选择误差小的簇继续二分K-均值划分
            if (sseSplit + sseNotSplit) < lowestSSE:
                bestCentToSplit = i
                bestNewCents = centroidMat
                bestClustAss = splitClustAss.copy()
                lowestSSE = sseSplit + sseNotSplit
        #将簇编号(0,1)修改成划分簇及新加簇的编号
        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中
        centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]#replace a centroid with two best centroids 
        centList.append(bestNewCents[1,:].tolist()[0])
        #新划分的结果更新到clusterAssment中
        clusterAssment[nonzero(clusterAssment[:,0].A == bestCentToSplit)[0],:]= bestClustAss#reassign new clusters, and SSE
    return mat(centList), clusterAssment
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值