K-means python 实现

系统 1499 0
原文链接: https://blog.csdn.net/hanxia159357/article/details/81530361

转载链接:https://blog.csdn.net/hanxia159357/article/details/81530361

本文完成程序及测试数据集详细见:https://github.com/HanXia001/k-means-python3-

本文主要内容:

                1.k-means解决的问题;

                2.k-means原理介绍;

                3.k-means的简单实现。

1.k-means解决的问题

         k-means算法属于无监督学习的一种聚类算法,其目的为:在不知数据所属类别及类别数量的前提下,依据数据自身所暗含的特点对数据进行聚类。对于聚类过程中类别数量k的选取,需要一定的先验知识,也可根据“类内间距小,类间间距大“(一种聚类算法的理想情况)为目标进行实现。

2.k-means原理介绍

        k-means算法以数据间的距离作为数据对象相似性度量的标准,因此选择计算数据间距离的计算方式对最后的聚类效果有显著的影响,常用计算距离的方式有:余弦距离、欧式距离、曼哈顿距离等。本文以欧式距离为例(会一种,其余也就会了)。

欧式距离公式:

                                                                  

例子:若数据为其计算欧式距离如下(可理解为D表示维度,i,j表示行数):

                                                                

         通过公式(1)可计算出每对数据对象间的距离,根据距离的远近进行聚类成指定的类别数K。对每一类中的数据初步选取类心,取的方式有多种如:

                             1.该类所有数据的均值;

                             2.随机取k个数据作为类心;

                             3.选取距离最远的k个点作为类心等。

以上方法均需要对初步的类心进行迭代,当类心变化缓慢时便可认为收敛,此时该点便为最终的类型。本文以方法1为例:

                                                                  

表示第k类,表示第k类中数据对象的个数。类心迭代过程如下:

                                                               

通常迭代终止的条件有两种:1)达到指定的迭代次数T;2)类心不再发生明显的变化,即收敛。

3.k-means的简单实现

原理讲过,此处直接上代码(python3实现):

            
              
import numpy as np

import matplotlib.pyplot as plt

 

# 加载数据

def loadDataSet(fileName):

    data = np.loadtxt(fileName,delimiter='\t')

    return data

 

# 欧氏距离计算

def distEclud(x,y):

    return np.sqrt(np.sum((x-y)**2))  # 计算欧氏距离

 

# 为给定数据集构建一个包含K个随机质心的集合

def randCent(dataSet,k):

    m,n = dataSet.shape

    centroids = np.zeros((k,n))

    for i in range(k):

        index = int(np.random.uniform(0,m)) #

        centroids[i,:] = dataSet[index,:]

    return centroids

 

# k均值聚类

def KMeans(dataSet,k):

 

    m = np.shape(dataSet)[0]  #行的数目

    # 第一列存样本属于哪一簇

    # 第二列存样本的到簇的中心点的误差

    clusterAssment = np.mat(np.zeros((m,2)))

    clusterChange = True

 

    # 第1步 初始化centroids

    centroids = randCent(dataSet,k)

    while clusterChange:

        clusterChange = False

 

        # 遍历所有的样本(行数)

        for i in range(m):

            minDist = 100000.0

            minIndex = -1

 

            # 遍历所有的质心

            #第2步 找出最近的质心

            for j in range(k):

                # 计算该样本到质心的欧式距离

                distance = distEclud(centroids[j,:],dataSet[i,:])

                if distance < minDist:

                    minDist = distance

                    minIndex = j

            # 第 3 步:更新每一行样本所属的簇

            if clusterAssment[i,0] != minIndex:

                clusterChange = True

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

        #第 4 步:更新质心

        for j in range(k):

            pointsInCluster = dataSet[np.nonzero(clusterAssment[:,0].A == j)[0]]  # 获取簇类所有的点

            centroids[j,:] = np.mean(pointsInCluster,axis=0)   # 对矩阵的行求均值

 

    print("Congratulations,cluster complete!")

    return centroids,clusterAssment

 

def showCluster(dataSet,k,centroids,clusterAssment):

    m,n = dataSet.shape

    if n != 2:

        print("数据不是二维的")

        return 1

 

    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '
              
                 len(mark):

        print("k值太大了")

        return 1

 

    # 绘制所有的样本

    for i in range(m):

        markIndex = int(clusterAssment[i,0])

        plt.plot(dataSet[i,0],dataSet[i,1],mark[markIndex])

 

    mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '
                
              
            
            
          

效果如图:

                   
版权声明:本文为CSDN博主「寒夏12」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hanxia159357/article/details/81530361


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论