机器学习与数据挖掘算法--kMeans算法

k-平均算法源于信号处理中的一种向量量化方法,现在更多作为一种聚类分析方法流行于数据挖掘领域。

聚类是一种无监督学习,它将相似的对象归到同一个簇中。簇内的对象越相似,聚类的效果越好。聚类与分类最大的不同在于,分类的目标事先已知,聚类则不一样。

k-均值是发现给定数据集的k个簇的算法。簇个数k是用户给定的,每个簇通过其质心,即簇中所有点的中心来描述。

目的

把n个点划分到k个聚类中,使得每个点都属于离他最近的均值(即聚类中心)对应的聚类,以此作为聚类的标准。

算法过程

  1. 从N个数据文档随机选取k个数据文档作为质心;
  2. 对剩余的每个数据文档测量其到每个质心的距离,并把它归到最近的质心的类;
  3. 重新计算已经得到的每个类的质心;
  4. 迭代2-3步直至新的质心与原质心相等或小于指定阀值。

程序过程

数据预处理,导入数据做成矩阵。distEclud方法计算两个向量之间的距离。

from numpy import *

def loadDataSet(fileName):
    dataMat = []
    fr = open(fileName)
    for line in fr.readlines():
        curLine = line.strip().split('\t')
        fltLine = map(float, curLine)
        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

创建k个质心,然后将每个点分配到最近的质心,然后重新计算质心。这个过程反复迭代,直到数据点的簇分配结果不再改变为止。

def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = shape(dataSet)[0]
    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 = 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
        for cent in range(k):
            ptsInClust = dataSet[nonzero(clusterAssment[:0].A == cent)[0]]
            centroids[cent,:] = mean(ptsInClust, axis=0)
    return centroids, clusterAssment 

聚类的簇的数目k是一个用户预先定义的参数,那么用户如何才能直到k的选择是正确的那?在包含簇分配结果的矩阵中保存着每个点的误差,即该点到簇质心的距离平方值。下面讨论利用误差来评价聚类质量。

SSE(Sum of Squared Error, 误差平方和)
SSE值越小,表示数据点越接近它们的质心,聚类的效果也就越好。降低SSE值的方法就是增加簇的个数,但聚类的目标就是在保持簇数目不变的情况下提高簇的质量。应该如何去做?

  • 将具有最大SSEd额簇划分成两个簇。为了保持簇的总数不变,将某两个簇进行合并。

二分k-均值算法

二分k-均值算法是为了克服k-均值算法收敛于局部最小值的问题提出的。该算法首先将所有点作为一个簇,然后将簇一分为二,选择最有可能降低SSE值的簇继续进行划分,继续迭代上述的过程,直至划分到用户指定的簇数目为止。另一种做法是选择SSE最大的簇进行划分,直到簇数目达到用户指定的数目为止。

使用scikit-learn中kMeans算法计算

sklearn.cluster.KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300, tol=0.0001, precompute_distances='auto', verbose=0, random_state=None, copy_x=True, n_jobs=1, algorithm='auto')

详细API介绍

使用方法

from sklearn.cluster import KMeans
import numpy as np 

X = np.array([[1, 2], [1, 4], [1, 0],
             [4, 2], [4, 4], [4, 0]])
kmeans = KMeans(n_clusters = 2, random_state = 0).fit(X)
print kmeans.labels_
print kmeans.predict([[0, 0], [4, 4]])
print kmeans.cluster_centers_

得到结果

python kMeansAPI.py 
[0 0 0 1 1 1]
[0 1]
[[ 1.  2.]
 [ 4.  2.]]

还有其他很多方法,详细的要阅读文档API。

你可能感兴趣的:(数据挖掘)