zoukankan      html  css  js  c++  java
  • 机器学习算法-K-means聚类

    引文: k均值算法是一种聚类算法。所谓聚类。他是一种无监督学习,将类似的对象归到同一个蔟中。蔟内的对象越类似,聚类的效果越好。

    聚类和分类最大的不同在于。分类的目标事先已知。而聚类则不一样。

    由于其产生的结果和分类同样,而仅仅是类别没有预先定义。

    算法的目的: 使各个样本与所在类均值的误差平方和达到最小(这也是评价K-means算法最后聚类效果的评价标准)

    Github源代码:K-Means聚类python实现

    K-均值聚类

    • 长处:easy实现
    • 缺点:可能收敛到局部最小值,在大规模数据上收敛较慢
    • 适合数据类型:数值型数据

    伪代码

    #创建k个点作为起始质心(常常随机选择)
    #当随意一个点的蔟分配结果发生变化时
        #对数据集中的每一个数据点
            #对每一个质心
                #计算质心到数据点之间的距离
            #将数据点分配到距其近期的蔟
        #对每一个蔟,计算蔟中全部点的均值并将均值作为质心

    代码实现

    由于我们用到的是数值类型的数据,这里编写一个载入数据集的函数,返回值是一个矩阵形式。


    以下代码应写在一个py文件中。我这里写在kMeans.py文件中。

    文件的头部引入numpy

    from numpy import *

    数据集载入代码

    # 载入数据集文件,没有返回类标号的函数
    def loadDataSet(fileName):
        dataMat = []
        openfile = open(fileName)    
        for line in openfile.readlines():
            curLine = line.strip().split('	')
            floatLine = map(float,curLine)
            dataMat.append(floatLine)
        return dataMat

    由于在k均值算法中要计算点到质心的距离,所以这里将距离计算写成一个函数,计算欧几里得距离公式:

    d=(x2x1)2+...+(z2z1)2

    函数代码例如以下:

    # 计算两个向量的欧氏距离
    def distEclud(vecA,vecB):
        return sqrt(sum(power(vecA-vecB,2)))

    接下来初始化k个蔟的质心函数centroid

    # 传入的数据时numpy的矩阵格式
    def randCent(dataMat, k):
        n = shape(dataMat)[1]
        centroids = mat(zeros((k,n)))  
        for j in range(n):
            minJ = min(dataMat[:,j]) # 找出矩阵dataMat第j列最小值
            rangeJ = float(max(dataMat[:,j]) - minJ) #计算第j列最大值和最小值的差
            #赋予一个随机质心,它的值在整个数据集的边界之内
            centroids[:,j] = minJ + rangeJ * random.rand(k,1) 
        return centroids #返回一个随机的质心矩阵

    K-means算法

    #k-均值算法
    def kMeans(dataMat,k,distE = distEclud , createCent=randCent):
        m = shape(dataMat)[0]    # 获得行数m
        clusterAssment = mat(zeros((m,2))) # 初试化一个矩阵,用来记录簇索引和存储误差                               
        centroids = createCent(dataMat,k) # 随机的得到一个质心矩阵蔟
        clusterChanged = True
        while clusterChanged:
            clusterChanged = False
            for i in range(m):    #对每一个数据点寻找近期的质心
                minDist = inf; minIndex = -1
                for j in range(k): # 遍历质心蔟,寻找近期的质心    
                    distJ1 = distE(centroids[j,:],dataMat[i,:]) #计算数据点和质心的欧式距离
                    if distJ1 < minDist: 
                        minDist = distJ1; 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].A==cent)[0]]    
                centroids[cent,:] = mean(ptsInClust, axis=0) 
        return centroids, clusterAssment

    測试:

    dataMat = mat(loadDataSet('testSet.txt'))
    kMeans(dataMat,4)

    输出结果:

    ===================

    [[-3.66087851 2.30869657]
    [ 3.24377288 3.04700412]
    [ 2.52577861 -3.12485493]
    [-2.79672694 3.19201596]]
    [[-3.78710372 -1.66790611]
    [ 2.6265299 3.10868015]
    [ 1.62908469 -2.92689085]
    [-2.18799937 3.01824781]]
    [[-3.53973889 -2.89384326]
    [ 2.6265299 3.10868015]
    [ 2.65077367 -2.79019029]
    [-2.46154315 2.78737555]]

    ===================

    上面的结果给出了四个质心。能够看出,经过3次迭代之后K-均值算法收敛。质心会保存在第一个返回值中。第二个是每一个点的簇分布情况。

    附件:
    上面測试的数据集为:

    1.658985    4.285136
    -3.453687   3.424321
    4.838138    -1.151539
    -5.379713   -3.362104
    0.972564    2.924086
    -3.567919   1.531611
    0.450614    -3.302219
    -3.487105   -1.724432
    2.668759    1.594842
    -3.156485   3.191137
    3.165506    -3.999838
    -2.786837   -3.099354
    4.208187    2.984927
    -2.123337   2.943366
    0.704199    -0.479481
    -0.392370   -3.963704
    2.831667    1.574018
    -0.790153   3.343144
    2.943496    -3.357075
    -3.195883   -2.283926
    2.336445    2.875106
    -1.786345   2.554248
    2.190101    -1.906020
    -3.403367   -2.778288
    1.778124    3.880832
    -1.688346   2.230267
    2.592976    -2.054368
    -4.007257   -3.207066
    2.257734    3.387564
    -2.679011   0.785119
    0.939512    -4.023563
    -3.674424   -2.261084
    2.046259    2.735279
    -3.189470   1.780269
    4.372646    -0.822248
    -2.579316   -3.497576
    1.889034    5.190400
    -0.798747   2.185588
    2.836520    -2.658556
    -3.837877   -3.253815
    2.096701    3.886007
    -2.709034   2.923887
    3.367037    -3.184789
    -2.121479   -4.232586
    2.329546    3.179764
    -3.284816   3.273099
    3.091414    -3.815232
    -3.762093   -2.432191
    3.542056    2.778832
    -1.736822   4.241041
    2.127073    -2.983680
    -4.323818   -3.938116
    3.792121    5.135768
    -4.786473   3.358547
    2.624081    -3.260715
    -4.009299   -2.978115
    2.493525    1.963710
    -2.513661   2.642162
    1.864375    -3.176309
    -3.171184   -3.572452
    2.894220    2.489128
    -2.562539   2.884438
    3.491078    -3.947487
    -2.565729   -2.012114
    3.332948    3.983102
    -1.616805   3.573188
    2.280615    -2.559444
    -2.651229   -3.103198
    2.321395    3.154987
    -1.685703   2.939697
    3.031012    -3.620252
    -4.599622   -2.185829
    4.196223    1.126677
    -2.133863   3.093686
    4.668892    -2.562705
    -2.793241   -2.149706
    2.884105    3.043438
    -2.967647   2.848696
    4.479332    -1.764772
    -4.905566   -2.911070
    
  • 相关阅读:
    数据库基础-INDEX
    LINQ教程
    NPOI导出EXCEL
    WPF数据双向绑定
    WPF控件数据单项绑定
    HelloWorld IL代码
    Python基础教程(英文视频教学)
    ado.net的5个主要对象
    Linux学习-0627
    C#中Abstract和Virtual
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5249632.html
Copyright © 2011-2022 走看看