K-Means

来源:互联网 发布:网络策略 sftp 协议 编辑:程序博客网 时间:2024/05/16 00:31
K-均值聚类算法
    优点:容易实现,不足之处可能收敛到局部最小值,在大规模数据集上收敛较慢,适用于数值型数据。工作流程如下:
 创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
    对数据集中的每个数据点
        对每个质心
              计算质心与数据点之间的距离
        将数据点分配到距其最近的簇

    对每一个簇,计算簇中所有点的均值并将均值作为质心

#-*- coding:utf-8 -*-from numpy import *def loadDataSet(fileName):    dataMat=[]    fr=open(fileName)    for line in fr.readlines():        curLine=line.strip().split('\t')        fitLine=map(float,curLine)        dataMat.append(fitLine)    return dataMat#计算两个向量的欧氏距离def distEclud(vecA,vecB):    return sqrt(sum(power(vecA-vecB,2)))#给定数据集构建一个包含k个随机质心的集合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)#生成0到1.0之间的随机数并通过取值范围和最小值确保随机点在数据边界之内    return centroids
>>> import kmeans
>>> from numpy import *
>>> datMat=mat(kmeans.loadDataSet('E:/code/testSet.txt'))
>>> min(datMat[:,0])
matrix([[-5.379713]])
>>> min(datMat[:,1])
matrix([[-4.232586]])
>>> max(datMat[:,1])
matrix([[ 5.1904]])
>>> max(datMat[:,0])
matrix([[ 4.838138]])

>>> kmeans.randCent(datMat,2)
matrix([[ 1.58043495, -1.31447897],
        [ 1.70103927,  4.95529564]])

测试一下距离的计算方法:

>>> kmeans.distEclud(datMat[0],datMat[1])
5.184632816681332

    所支持的函数正常运行,准备实现K均值算法。创建k个质心,然后将每个点分配到最近的质心,在重新计算质心。重复数次,直到数据点的簇分配结果不会改变为止。

#数据集及簇的数目是必选参数,计算距离和创建初始质心的函数可选def keans(dataSet,k,distMeas=distEclud,createCent=randCent):    m=shape(dataSet)[0]#创建一个矩阵来存储每个点的簇分配结果    clusterAssment=mat(zeros((m,2)))#一列记录簇索引值,一列存储误差    centroids=createCent(dataSet,k)    clusterChanged=True#标识变量,true则继续迭代    #遍历所有数据找到距离每个点最近的质心,对每个点遍历所有质心并计算每个质心的距离来完成    while clusterChanged:        clusterChanged=False        for i in range(m):            minDist=inf;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[i,:]=minIndex,minDist**2        print centroids        #遍历并更新取值,通过数组过滤来获得给定簇的所有点,计算均值,axis=0表示沿矩阵列的方向进行均值计算        for cent in range(k):            ptsInClust=dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]            centroids[cent,:]=mean(ptsInClust,axis=0)    return centroids,clusterAssment
>>> reload(kmeans)
<module 'kmeans' from 'E:\python\kmeans.py'>
>>> datMat=mat(kmeans.loadDataSet('E:/code/testSet.txt'))
>>> myCenttroids,clustAssing=kmeans.keans(datMat,4)
[[-2.70314932  2.01452543]
 [ 0.89843689  2.61822779]
 [ 1.18644542 -3.90997013]
 [ 3.1300084  -2.7441036 ]]
[[-3.07195136  0.92565029]
 [ 2.24547378  2.92273278]
 [-2.00155638 -3.472942  ]
 [ 3.25624481 -2.728045  ]]
[[-2.54951105  2.75812458]
 [ 2.46383071  3.1198451 ]
 [-3.19984738 -2.96423548]
 [ 2.926737   -2.70147753]]
[[-2.46154315  2.78737555]
 [ 2.6265299   3.10868015]
 [-3.38237045 -2.9473363 ]
 [ 2.80293085 -2.7315146 ]]

二分K-均值算法:

 将所有点看成一个簇

当簇数目小于k时

    对于每一个簇

        计算总误差

        在给定的簇上面进行K-均值聚类(k=2)

         计算将该簇一分为二之后的总误差

    选择使得误差最小的那个簇进行划分操作

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#将最小SSE设置为无穷大        #尝试划分每一簇        for i in range(len(centList)):            ptsInCurrCluster=dataSet[nonzero(clusterAssment[:,0].A!=i)[0],:]#小数据集            centroidMat,splitClustAss=kMeans(ptsInCurrCluster,2,distMeas)#k-均值算法会生成两个质心,同时给出误差值            sseSplit=sum(splitClustAss[:,1])            sseNotSplit=sum(clusterAssment[nonzero(clusterAssment[:,0].A!=i)[0],1])            print "sseSplit,and not Split:",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
>>> reload(kmeans)
<module 'kmeans' from 'E:\python\kmeans.py'>
>>> datMat3=mat(kmeans.loadDataSet('E:/code/testSet2.txt'))
>>> centList,myNewAssments=kmeans.biKmeans(datMat3,3)
[]

Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    centList,myNewAssments=kmeans.biKmeans(datMat3,3)
  File "E:\python\kmeans.py", line 65, in biKmeans
    centroidMat,splitClustAss=kMeans(ptsInCurrCluster,2,distMeas)#k-均值算法会生成两个质心,同时给出误差值
  File "E:\python\kmeans.py", line 31, in kMeans
    centroids=createCent(dataSet,k)
  File "E:\python\kmeans.py", line 24, in randCent
    rangeJ=float(max(dataSet[:,j])-minJ)
ValueError: max() arg is an empty sequence

为什么出错呢?试了好几种方法,求大神指点,多谢!




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在线中文字幕最好看最经典 丈夫面前不允许出声的侵犯2 2018吉译明i作品全集一览 好看的中文字幕推荐 yellow字幕幕网 中文字幕人人视频在线萝莉 中文永久字幕在线播放 好看的字幕最新字幕一经典幕 母乳妻诱惑中文字幕 有什么好看的电影 2018好看的大陆电影 什么动漫电影好看中文 在线播放丝服制袜 2018最新手机中文字幕 中文字幕视频2018 中文字幕爸爸在线播放 濡x母 もう、やめて… 中文字幕在线手机播放2018 免费中文字幕 啄木鸟中文字幕在线播放军舰 中文字幕永久在线2016 免费伦电影中文字幕 大嫂潮湿中文字幕在线迅雷 小白看看永久播放平台 看永久看免费2018中文字 妻人射中文字幕 2019永久免费播放平台 免费永久播放平台领城四虎 好看的中文字 幕经典中文字幕 中字幕在线永久视频 绝对的经典中文字幕 中文字幕最新好看 仓多真央好看中文字幕叔母 好看不卡的中文字幕 好看的中文字幕 039 2019最新男的网站 好看的无中文字幕美剧 中文字幕看永久看视频平台 美国一千部污女视频而且免费 大明看永久看免费播放平台 一千部禁污女一进一出的视频