首页 > 代码库 > 机器学习实战--k-均值聚类

机器学习实战--k-均值聚类

1、聚类是一种无监督学习,他讲相似的对象放到同一簇下,有点像自动分类。聚类方法几乎可以用到任何对象上,簇内的对象越相似,聚类结果就越好。

2、K均值聚类的优点

  算法简单容易实现

  缺点:

  可能收敛到局部最小值,在大规模数据上收敛速度较慢

3、K-均值算法算法流程以及伪代码

  首先随机选择k个初始点作为质心。然后将数据集中的每个点分配到一个簇中,具体来说,遍历数据集计算数据与质心之间的距离找到最小的距离将该数据划分到该簇内,完成后更新簇的质心。但是只要有数据点的簇发生变化就需要继续进行划分,直到没有点发生改变。

  伪代码:

  创建K个点作为起始质心(经常是随机选择,但是不能越界,下面的代码有具体的做法)

  当任意一个点的簇分配结果发生变化时

    对数据集中的每一个数据点

      对每个质心

        计算质心与数据点的距离

      将数据点分配到距离最近的簇

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

  

技术分享
from numpy import *

def loadDataSet(filename):
    dataMat=[]
    fr = open(filename)
    for line in fr.readlines():
        curLine = line.strip().split(\t)
        fltLine = list(map(float, curLine))
        #print(fltLine)
        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(dataSet, k, distMeans = distEclud, createCent = randCent):
    m = shape(dataSet)[0]
    #建立一个m*2的矩阵位置0记录聚类的索引,位置1记录到聚类质心的距离
    clusterAssment = mat(zeros((m,2)))
    centroids = createCent(dataSet, k)
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = inf; minIndex = -1
            for j in range(k):
                distJI = distMeans(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)
        for cent in range(k):
            #通过数组过滤来获得给定簇的所有样本,nozero返回一个0/1矩阵,然后取第一列的索引列
            ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]
            centroids[cent, :] = mean(ptsInClust, axis = 0)
    return centroids, clusterAssment
#print(loadDataSet(‘testSet.txt‘))
dataMat = mat(loadDataSet(testSet.txt))
myCentroids, clustAssing = Kmeans(dataMat, 4)
print(myCentroids)
print(clustAssing)
K-均值算法

4、使用后处理提高聚类的性能

  K均值算法中的K是用户给出的,如何衡量在给定K个聚类的情况下聚类的性能。对于K均值算法可能会收敛到局部最小,而不能收敛到全局最小,因此可能聚类效果不好。在上边的代码中clusterAssment保存了每个数据点的簇标号以及点到簇质心的误差(就是距离)。那么可以使用SSE(sum of squared Erro,误差平方和)作为衡量聚类性能的指标,SSE的数值越小就表示数据点越接近他们的质心聚类效果也就越好,同时由于对误差取了平方所以越远的点在SSE中就越受重视。

  怎么降低SSE?一种简单的方法是增加簇的数量,但是这样不好啊,你是去聚类了你弄了和数据集一样的簇,那还聚个啥。因此需要在不改变簇的数目的前提下降低SSE。一种可行的办法是选择SSE最大的簇,然后对其继续进行K均值算法。同时为了保证簇的数目不变,可以将簇与簇进行合并。

  合并的方法:质心之间距离最近的合并;合并两个簇然后计算总的SSE,合并可以使SSE最小的簇。

5、二分 K均值算法

  为了克服K均值算法收敛于局部最小的问题,有人提出了一个二分K均值的算法。回来继续

机器学习实战--k-均值聚类