聚类算法:K-Means

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/keyue123/article/details/81197381

  K-Means聚类算法是一种基于距离的聚类算法,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则,最终的目标就是根据输入参数K,将数据对象分为K个簇。算法采用误差平方和准则函数作为聚类准则函数。
  基本思想:
    1、指定需要划分的簇的个数K值
    2、随机选取K个初始聚类中心
    3、计算各个数据到这K个初始聚类中心的距离,把数据对象划分到最近的聚类中心所处的簇中
    4、计算每一组的平均值,作为新的聚类中心
    5、重复2~4直至中心点不再发生变化

  一般情况下我们都是使用欧式几何距离作为聚类的目标函数:

d = ( x 1 2 x 2 2 ) + ( y 1 2 y 2 2 )

实例分析:
利用K-Means方法,将下面的数据分为两类:

坐标点 X Y
A 15 17
B 12 18
C 14 15
D 13 16
E 12 15
F 16 12
G 4 6
H 5 8
I 5 3
J 7 4
K 7 2
L 6 5

python代码实现解析:

#!/usr/bin/python
#coding=utf-8

from numpy import *
from math import sqrt
import codecs

# 获取样本集
def LoadData():
    f = codecs.open("k-means.txt", mode='r+')
    lines = f.readlines()

    data = []
    for line in lines:
        curline = line.strip().split(', ') # 用逗号把数据分开
        frline = map(float, curline)
        data.append(frline) # 将数据放在列表中

    data = mat(data)    # 将列表转为矩阵
    print data

    return data

# 计算距离量度
def distEclud(vecA, vecB):
    distance = sqrt(sum(power((vecA - vecB),2)))    # 计算欧氏距离

    return distance

# 随机生成K个初始点
def randCent(dataSet, k):
    n = shape(dataSet)[1] # 获取数据矩阵行数
    center = mat(zeros((k, n))) # 产生新的填充为0的矩阵
    for j in range(n):
        rangeJ = float(max(dataSet[:, j]) - min(dataSet[:, j])) # 计算数据范围
        center[:, j] = min(dataSet[:, j]) + rangeJ * random.rand(k, 1) # 随机产生一个在数据范围类的聚类中心

    print "初始质点: "
    print center

    return center

# dataSet   样本集
# k         簇个数
# distMeas  距离量度,默认欧式距离
# randCent  初始点选取
def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
    m = shape(dataSet)[0]               # 样本数
    clusterAssment = mat(zeros((m, 2))) # 创建矩阵并清零
    center = createCent(dataSet, k)     # 随机生成K个初始点

    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = inf
            minIndex = -1
            for j in range(k):
                distJI = distMeas(dataSet[i, :], center[j, :])  # 计算点到各个聚类中心的距离
                if distJI < minDist:
                    minDist = distJI    # 计算到各个聚类中心的最短欧氏距离
                    minIndex = j

            if clusterAssment[i, 0] != minIndex:    # 判断是否收敛
                clusterChanged = True

            clusterAssment[i, :] = minIndex, minDist ** 2

        for cent in range(k):   # 更新聚类中心
            dataCent = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]  # nonzero 非零数组位置
            center[cent, :] = mean(dataCent, 0) # 求列平均值

    print "均值后质点: "
    print center

    return center

# 主函数
def main():
    dataSet = LoadData()
    k = 2
    kMeans(dataSet, k)

if __name__ == '__main__':
    main()

最终获取到的两个聚类中心:

[john@localhost K-means]$ python K-means.py 
[[ 15.  17.]
 [ 12.  18.]
 [ 14.  15.]
 [ 13.  16.]
 [ 12.  15.]
 [ 16.  12.]
 [  4.   6.]
 [  5.   8.]
 [  5.   3.]
 [  7.   4.]
 [  7.   2.]
 [  6.   5.]]
初始质点: 
[[ 12.65495833   4.14865393]
 [  9.30725565   2.9332491 ]]
均值后质点: 
[[ 13.66666667  15.5       ]
 [  5.66666667   4.66666667]]

初始数据与随机产生的聚类中心
  没有均值之前的散点图,红色为第一次随机生成的质点,即聚类中心,蓝色为数据集。
算法完成后聚类中心
  计算均值之前的散点图,红色为均值之后的质点。

猜你喜欢

转载自blog.csdn.net/keyue123/article/details/81197381