当前位置:   article > 正文

Python实现K-Means聚类算法_kmeans聚类算法python

kmeans聚类算法python

       声明:代码的运行环境为Python3。Python3与Python2在一些细节上会有所不同,希望广大读者注意。本博客以代码为主,代码中会有详细的注释。相关文章将会发布在我的个人博客专栏《Python从入门到深度学习》,欢迎大家关注~


       根据训练样本是否包含标签信息,机器学习可以分为监督学习和无监督学习(这里我们不考虑半监督学习)。聚类算法是典型的无监督学习算法,它是对事务自动归类的一种算法,在聚类算法中利用样本的标签,将具有相似属性的事物聚集到一类中。

 

一、常用的相似性度量

        K-Means算法(K-均值算法)是基于相似性的无监督学习算法,即通过比较样本之间的相似性,将较为相似的样本划分到同一个类别中。为了度量两个样本(以样本X和样本Y为例)之间的相似性,通常会定义一个距离函数d(X,Y),利用这个距离函数来定义样本X和样本Y之间的相似性。

1、闵可夫斯基距离

        空间中两个点X,Y的坐标分别为:

        那么,点X与点Y之间的闵可夫斯基距离可以定义为:

2、曼哈顿距离

        同样的两个点X,Y其曼哈顿距离可以表示为:

3、欧氏距离

        同样的,点X与点Y的欧氏距离可以表示为:

       

        由上面的定义可知,曼哈顿距离和欧式距离是闵可夫斯基距离的特殊形式。当p=1时,闵可夫斯基距离就是曼哈顿距离;当p=2时,闵可夫斯基距离就是欧式距离。在K-Means算法中,我们使用欧氏距离作为其相似性度量。因为欧氏距离的根号存在与否对其度量性没有影响,简单起见,我们使用欧氏距离的平方作为最终的相似性度量。

        首先将需要加载相关的模块:

import numpy as np

       欧氏距离的平方实现代码如下:

  1. def distance(vecA, vecB):
  2. '''
  3. 计算两个向量之间欧氏距离的平方
  4. :param vecA: 向量A的坐标
  5. :param vecB: 向量B的坐标
  6. :return: 返回两个向量之间欧氏距离的平方
  7. '''
  8. dist = (vecA - vecB) * (vecA - vecB).T
  9. return dist[0, 0]

 

二、K-Means算法原理

        首先,我们需要人为的指定最终的聚类个数,假设我们最终的聚类个数为k个,即我们需要初始化k个聚类中心,通过计算每个样本与聚类中心的相似度,将样本点划分到距离最近的聚类中心。然后,通过每个类的样本重新计算每个类的聚类中心,重复这个操作直至聚类中心不再改变即为最终的聚类结果。

 

三、K-Means算法步骤

        1、随机初始化K个聚类中心,其代码如下:

  1. def randomCenter(data, k):
  2. '''
  3. 随机初始化聚类中心
  4. :param data: 训练数据
  5. :param k: 聚类中心的个数
  6. :return: 返回初始化的聚类中心
  7. '''
  8. n = np.shape(data)[1] # 特征的个数
  9. cent = np.mat(np.zeros((k, n))) # 初始化K个聚类中心
  10. for j in range(n): # 初始化聚类中心每一维的坐标
  11. minJ = np.min(data[:, j])
  12. rangeJ = np.max(data[:, j]) - minJ
  13. cent[:, j] = minJ * np.mat(np.ones((k, 1))) + np.random.rand(k, 1) * rangeJ # 在最大值和最小值之间初始化
  14. return cent

         2、计算每个样本与k个聚类中心的相似度,将样本划分到与之最相似的类中;

         3、计算划分到每个类别中所有样本特征的均值,并将该均值作为每个类别新的聚类中心;

         4、重复2、3步操作,直至聚类中心不再改变,输出最终的聚类中心。

         构建K-Means算法的代码如下:

  1. def kmeans(data, k, cent):
  2. '''
  3. kmeans算法求解聚类中心
  4. :param data: 训练数据
  5. :param k: 聚类中心的个数
  6. :param cent: 随机初始化的聚类中心
  7. :return: 返回训练完成的聚类中心和每个样本所属的类别
  8. '''
  9. m, n = np.shape(data) # m:样本的个数;n:特征的维度
  10. subCenter = np.mat(np.zeros((m, 2))) # 初始化每个样本所属的类别
  11. change = True # 判断是否需要重新计算聚类中心
  12. while change == True:
  13. change = False # 重置
  14. for i in range(m):
  15. minDist = np.inf # 设置样本与聚类中心的最小距离,初始值为正无穷
  16. minIndex = 0 # 所属的类别
  17. for j in range(k):
  18. # 计算i和每个聚类中心的距离
  19. dist = distance(data[i, ], cent[j, ])
  20. if dist < minDist:
  21. minDist = dist
  22. minIndex = j
  23. # 判断是否需要改变
  24. if subCenter[i, 0] != minIndex: # 需要改变
  25. change = True
  26. subCenter[i, ] = np.mat([minIndex, minDist])
  27. # 重新计算聚类中心
  28. for j in range(k):
  29. sum_all = np.mat(np.zeros((1, n)))
  30. r = 0 # 每个类别中样本的个数
  31. for i in range(m):
  32. if subCenter[i, 0] == j: # 计算第j个类别
  33. sum_all += data[i, ]
  34. r += 1
  35. for z in range(n):
  36. try:
  37. cent[j, z] = sum_all[0, z] / r
  38. except:
  39. print("ZeroDivisionError: division by zero")
  40. return subCenter, cent

 

四、K-Means算法举例

1、数据集:数据集含有两个特征,如下图所示:

2、加载数据集

       我们此处使用如下方法加载数据集,也可使用其他的方式进行加载,此处可以参考我的另外一篇文章《Python两种方式加载文件内容》。加载文件内容代码如下:

  1. def load_data(file_path):
  2. '''
  3. 导入数据
  4. :param file_path: 文件路径
  5. :return: 以矩阵的形式返回导入的数据
  6. '''
  7. f = open(file_path)
  8. data = []
  9. for words in f.readlines():
  10. row = [] # 记录每一行
  11. word = words.strip().split("\t")
  12. for x in word:
  13. row.append(float(x)) # 将文本中的特征转换成浮点数
  14. data.append(row)
  15. f.close()
  16. return np.mat(data) # 以矩阵的形式返回

3、保存聚类结果

       通过K-Means聚类之后,我们可以使用如下方法保存聚类结果:

  1. def save_result(file_name, data):
  2. '''
  3. 保存source中的结果到file_name文件中
  4. :param file_name: 保存的文件名
  5. :param data: 需要保存的数据
  6. :return:
  7. '''
  8. m, n = np.shape(data)
  9. f = open(file_name, "w")
  10. for i in range(m):
  11. tmp = []
  12. for j in range(n):
  13. tmp.append(str(data[i, j]))
  14. f.write("\t".join(tmp) + "\n")
  15. f.close()

4、调用K-Means算法

       调用K-Means算法:

  1. if __name__ == "__main__":
  2. k = 4 # 聚类中心的个数
  3. file_path = "tfidf.txt"
  4. subCenter, center = kmeans(load_data(file_path), k, randomCenter(load_data(file_path), k))
  5. save_result("result/kmeans_sub", subCenter)
  6. save_result("result/kmeans_center", center)

5、结果展示

       得到的聚类结果如图所示:

 

        你们在此过程中遇到了什么问题,欢迎留言,让我看看你们都遇到了哪些问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/337715
推荐阅读
相关标签
  

闽ICP备14008679号