K-means聚类

K-means聚类

导语
这一章主要参考《集体编程智慧》的第三张–发现群组。看了三章感觉《集体编程智慧》这本书讲的还可以,但是说实话他的代码不是特别科学,例如这一章使用的数据源并不太适合新手使用来学习这个算法,所以主要参考了算法的原理,代码的话借鉴了别人博客里的数据,然后实现了一下。


K-means原理简介:

算法的基础是最小化误差平方和准则,代价函数为:

J(c,μ)=1nx(i)μc(i)2 J ( c , μ ) = ∑ 1 n ∥ x ( i ) − μ c ( i ) ∥ 2

其中 μc(i) μ c ( i ) 为第i类的中心点,显然这个公式是得到的是一个全局的误差最小结果。

算法原理:
1. 首先根据在样本集大小范围内随机产生k个聚类中心点
2. 遍历数据集,计算每一个数据样本距离中心点的欧式距离,将其划分到最近的中心点所代表的聚类类别
3. 分别遍历K个聚类内的数据样本,将类别内的所有样本的平均值作为该类的新中心点,更新中心点
4. 不断迭代以上三个步骤,直到每一个数据样本所属类别不再有变化


举例:

如下所示数据data.txt:

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  

数据分布如下图:

这里写图片描述

K-means聚类代码如下:

import json
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as plt
import re
import math

def get_data(filename):                 #读取数据
    f = open(filename)  
    data = DataFrame(columns=['x','y']) #构造DataFrame存放数据,列名为x与y
    line = f.readline()
    p = re.compile(r'\s+')              #由于数据由若干个空格分隔,构造正则表达式分隔
    while line:
        linedata = p.split(line)
        data.set_value(len(data),['x','y'],[float(linedata[0]),float(linedata[1])]) #数据存入DataFrame
        line = f.readline()
    return data
def get_distance(p1,p2):                #计算两个点之间的欧氏距离
    distance = math.sqrt(sum([pow(p1[i]-p2[i],2) for i in range(len(p1))]))
    return distance
def initCenterPoint(dataset,k):         #初始化聚类中心点
    numSample,dim = data.shape
    centerPoint = np.zeros((k,dim))
    for i in range(k):                  #生成的聚类中心点坐标范围在样本范围之内
        centerPoint[i][0] = np.random.uniform(min(dataset['x']),max(dataset['x']))
        centerPoint[i][1] = np.random.uniform(min(dataset['y']),max(dataset['y']))
    return centerPoint
def kmeans(dataset,k):                        #K均值聚类
    numSample = dataset.shape[0]
    clustAssment = np.zeros((numSample,2))    #样本类别集合,存放样本所属类别标签和到中心点的距离
    clustChanged = True                       #结束循环标志位

    centerPoint = initCenterPoint(dataset,k)  #初始化聚类中心点
    while clustChanged:
        clustChanged = False
        for i in range(numSample):            #遍历所有样本,更新样本的类别标签与到中心点距离
            minDist = 1000                    #初始化最小距离
            minindex = 0                      #初始化所属样本标签
            p1 = dataset.ix[i]                #当前样本点
            for j in range(k):
                p2 = centerPoint[j]           #当前聚类中心点
                dist = get_distance(p1,p2)    #计算距离
                if dist<minDist:              #取最小距离的中心点来更新当前样本的标签与距离
                    minDist = dist
                    minindex = j
            if clustAssment[i][0]!= minindex: #样本类别集合有更新,则继续迭代
                clustChanged = True
                clustAssment[i] = [minindex,minDist] #更新样本点类别和距离

        for i in range(k):                          #更新聚类中心点
            xnum = 0
            ynum = 0
            pnum = 0
            for j in range(numSample):
                if clustAssment[j][0]==i:
                    pnum += 1
                    xnum += dataset.ix[j,'x']
                    ynum += dataset.ix[j,'y']
            centerPoint[i] = [xnum/pnum,ynum/pnum]  #计算均值更新
    print('Cluster Complete')
    return centerPoint,clustAssment
def showCluster(dataset,k,centerPoint,clusterAssment): #画图显示
    numSample,dim = dataset.shape
    mark = ['or','ob','og','ok']
    for i in range(numSample):
        markIndex = int(clustAssment[i][0])
        plt.plot(dataset.ix[i,'x'],dataset.ix[i,'y'],mark[markIndex])
    mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']
    for i in range(k):
        plt.plot(centerPoint[i][0],centerPoint[i][1],mark[i],markersize=12)
    plt.show()

if __name__ == "__main__":
    data = get_data('data.txt')
    centerPoint,clustAssment = kmeans(data,4)
    showCluster(data,4,centerPoint,clustAssment)

结果如下图所示:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值