机器学习实战第十章 - K均值聚类算法

一,K均值聚类算法

1,特点

  • 优点:容易实现。
  • 缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢。
  • 适用数据类型:数值型数据。

2,伪代码

创建k个点作为起点质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
    对数据集中的每个数据点
        对每个质心
            计算质心与数据点之间的距离
        将数据点分配到距其最近的簇
    对每个簇,重新计算簇中每个点的均值并将均值作为质心

3,Python实现

from numpy import *

def loadDataSet(filename):
    dataMat = []
    fr = open(filename)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        fltLine = [float(t) for t in lineArr]
        dataMat.append(fltLine)
    return dataMat
def distEclud(vecA,vecB):
    return sqrt(sum(power(vecA-vecB,2)))
def randCent(dataSet,k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k,n)))
    for j in range(n):
        minJ = min(dataSet[:,j])
        rangeJ = float(max(dataSet[:,j])-minJ)
        centroids[:,j] = minJ+rangeJ*random.rand(k,1)
    return centroids
def kMeans(dataMat,k,distMeans=distEclud,createCent=randCent):
    m = shape(dataMat)[0]
    centroids = createCent(dataMat,k)
    clusterAssment = mat(zeros((m,2)))
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = inf;minIndex = -1
            for j in range(k):
                distJI = distMeans(dataMat[i],centroids[j])
                if distJI < minDist:
                    minDist= distJI
                    minIndex = j
            if clusterAssment[i,0]!=minIndex:
                clusterChanged=True
            clusterAssment[i] = minIndex,minDist**2
        print(centroids)
        for cent in range(k):
            ptsInClust = dataMat[nonzero(clusterAssment[:,0]==cent)[0]] #找到同一个簇中的所有点
            centroids[cent,:] = mean(ptsInClust,axis=0)
    return centroids,clusterAssment

二,使用后处理来提高聚类性能

K均值算法收敛但聚类效果差的原因是,由于质心的随机初始化,K均值算法可能会收敛到局部最小值。
一种度量聚类效果的指标是SSE(误差平方和),但必须在保持簇数目不变的情况下提高簇的质量。

后处理:

  • 将具有较大SSE值的簇划分成两个簇;
  • 为了保持簇总数不变,然后再将某两个簇进行合并:合并最近的两个质心或者合并两个使得SSE增幅最小的质心。

三,二分K均值算法

1,原理

该聚类算法可以克服收敛于局部最小值的问题。

该算法首先将所有点作为一个簇,然后将该簇一分为二。之后选择其中一个簇继续进行划分,选择哪个簇取决于是否可以最大程度地降低SSE的值。上述基于SSE的划分不断重复,直到得到用户指定的簇数目为止。
当然也可以选择SSE最大的簇进行划分。

2,伪代码

将所有点看成一个簇
当簇数目小于k时
    对于每一个簇
        计算总误差
        在给定的簇上面进行K均值聚类(k=2)
        计算将该簇一分为二后的总误差
    选择使得误差最小的那个簇进行划分操作

3,Python实现

def biKmeans(dataSet, k, distMeas=distEclud):
    m = shape(dataSet)[0]
    clusterAssment = mat(zeros((m,2)))
    centroid0 = mean(dataSet, axis=0).tolist()[0]
    centList =[centroid0]
    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],:]
            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)
        if (sseSplit + sseNotSplit) < lowestSSE:
            bestCentToSplit = i
            bestNewCents = centroidMat
            bestClustAss = splitClustAss.copy()
            lowestSSE = sseSplit + sseNotSplit
    bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] =\
                        len(centList)
    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,:]
    centList.append(bestNewCents[1,:])
    clusterAssment[nonzero(clusterAssment[:,0].A == \
                            bestCentToSplit)[0],:]= bestClustAss
    return mat(centList), clusterAssment
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值