深圳幻海软件技术有限公司 欢迎您!

K-Means 聚类算法 Python实现

2023-07-12

聚类算法        将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类。由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异。“物以类聚,人以群分”,在自然科

聚类算法

        将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类。由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异。“物以类聚,人以群分”,在自然科学和社会科学中,存在着大量的分类问题。聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法。聚类分析起源于分类学,但是聚类不等于分类。聚类与分类的不同在于,聚类所要求划分的类是未知的。聚类分析内容非常丰富,有系统聚类法、有序样品聚类法、动态聚类法、模糊聚类法、图论聚类法、聚类预报法等。

(以上名词解释源自百度百科)

K-Means基本思想

  • 初始化中心点
  • 计算样本点与中心点之间的距离,将样本点归为最近的中心点的类中
  • 根据类划分,计算新的样本中心点
  • 重复操作直到中心点或类的归属不再发生变化

需要预设类的个数为K


代码解析

生成随机样本

  1. import torch
  2. import math
  3. import matplotlib.pyplot as plt
  4. # 利用torch的函数生成随机的样本点
  5. X=torch.randn(2000)*100
  6. y=torch.randn(2000)*100
  7. # 一个长度为2000的向量,表示点的类别归属
  8. C=torch.zeros(2000)

生成初始中心点

  1. # 设置k-means的类别数
  2. K = 5
  3. CentPoint = []
  4. for i in range(K):
  5. CentPoint.append([torch.randint(-100,100,(1,)).item(),
  6. torch.randint(-100,100,(1,)).item()])

K-Means算法

  1. # 计算二维平面上点的距离
  2. def dis(a,b):
  3. return math.sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1]))
  4. # K-Means
  5. # 一般执行10次以内即可完成分类
  6. for p in range(10):
  7. # NewPoint初始化为0
  8. NewPoint = [[0, 0] for i in range(K)]
  9. for i in range(len(X)):
  10. mDis=1e9
  11. mC=0
  12. for j in range(len(CentPoint)):
  13. cp=CentPoint[j]
  14. D = dis([X[i].item(), y[i].item()], cp)
  15. # print("distance:", D)
  16. if mDis>D:
  17. mDis=D
  18. mC=j
  19. C[i]=mC
  20. # print("mC",mC,C[i].item())
  21. NewPoint[mC][0]+=X[i].item()
  22. NewPoint[mC][1]+=y[i].item()
  23. # 更新中心点
  24. for i in range(K):
  25. CentPoint[i][0]=NewPoint[i][0]/2000
  26. CentPoint[i][1]=NewPoint[i][1]/2000
  27. # 输出中心点,观察变化过程
  28. print(CentPoint)

结果展示

  1. cc=list(C)
  2. # 按不同颜色来区分不同种类的点
  3. for i in range(len(X)):
  4. if cc[i]==0:
  5. plt.plot(X[i].item(), y[i].item(), 'r.')
  6. elif cc[i]==1:
  7. plt.plot(X[i].item(), y[i].item(), 'g.')
  8. elif cc[i]==2:
  9. plt.plot(X[i].item(), y[i].item(), 'b.')
  10. elif cc[i]==3:
  11. plt.plot(X[i].item(), y[i].item(), color='pink', marker='.')
  12. elif cc[i]==4:
  13. plt.plot(X[i].item(), y[i].item(), color='orange', marker='.')
  14. # 样本聚类的中心点
  15. for CP in CentPoint:
  16. plt.plot(CP[0], CP[1], color='black', marker='X')

可以观察出来,由于这组随机样本的生成是基于二维正态分布的,用K-Means来分析聚类,五个中心点的位置十分接近于二维正态分布的中心。


完整代码

  1. import torch
  2. import math
  3. import matplotlib.pyplot as plt
  4. def dis(a,b):
  5. return math.sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1]))
  6. X=torch.randn(2000)*100
  7. y=torch.randn(2000)*100
  8. C=torch.zeros(2000)
  9. K = 5
  10. CentPoint = []
  11. for i in range(K):
  12. CentPoint.append([torch.randint(-100,100,(1,)).item(),
  13. torch.randint(-100,100,(1,)).item()])
  14. print(CentPoint)
  15. for p in range(10):
  16. NewPoint = [[0, 0] for i in range(K)]
  17. for i in range(len(X)):
  18. mDis=1e9
  19. mC=0
  20. for j in range(len(CentPoint)):
  21. cp=CentPoint[j]
  22. D = dis([X[i].item(), y[i].item()], cp)
  23. if mDis>D:
  24. mDis=D
  25. mC=j
  26. C[i]=mC
  27. NewPoint[mC][0]+=X[i].item()
  28. NewPoint[mC][1]+=y[i].item()
  29. for i in range(K):
  30. CentPoint[i][0]=NewPoint[i][0]/2000
  31. CentPoint[i][1]=NewPoint[i][1]/2000
  32. print(CentPoint)
  33. cc=list(C)
  34. for i in range(len(X)):
  35. if cc[i]==0:
  36. plt.plot(X[i].item(), y[i].item(), 'r.')
  37. elif cc[i]==1:
  38. plt.plot(X[i].item(), y[i].item(), 'g.')
  39. elif cc[i]==2:
  40. plt.plot(X[i].item(), y[i].item(), 'b.')
  41. elif cc[i]==3:
  42. plt.plot(X[i].item(), y[i].item(), color='pink', marker='.')
  43. elif cc[i]==4:
  44. plt.plot(X[i].item(), y[i].item(), color='orange', marker='.')
  45. for CP in CentPoint:
  46. plt.plot(CP[0], CP[1], color='black', marker='X')
  47. plt.show()

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览49088 人正在系统学习中