首页 > 编程语言 > 详细

关于k-means聚类算法的原理及解析

时间:2020-11-21 22:34:35      阅读:29      评论:0      收藏:0      [点我收藏+]

一、k-means算法思想:

 

第一步,从文件中读取数据,点用元组表示,点集用列表表示。
第二步,初始化聚类中心。首先获取数据的长度,然后在range(0,length)这个区间上随机产生k个不同的值,以此为下标提取出数据点,将它们作为聚类初始中心,产生列表center。
第三步,分配数据点。将数据点分配到距离(欧式距离)最短的聚类中心中,产生列表assigment,并计算平均误差。
第四步,如果首次分配后有结果为空,则重新初始化聚类中心。
第五步,更新聚类中心,(计算每一簇中所有点的平均值),然后再次进行分配,并计算平均误差。
第六步,比较前后两次的平均误差是否相等,若不相等则进行循环,否则终止循环,进入下一步
最少进行两次聚类,对比误差,输出较小误差时的结果,避免平均误差过大。

 

二、流程图:

技术分享图片

 

 

 

三、 结果输出:

技术分享图片

 

 

 

四、散点图:

技术分享图片

 

 

 

 

五、python实现代码:

  1 import random
  2 from math import *
  3 import matplotlib.pyplot as plt
  4  
  5 #从文件种读取数据
  6 def read_data():
  7     data_points = []
  8     with open(data.txt,r) as fp:
  9         for line in fp:
 10             if line ==\n:
 11                 continue
 12             data_points.append(tuple(map(float,line.split( ))))#去掉空格,并将data中数据的类型转为tuple
 13         fp.close()
 14         return data_points
 15  
 16 #初始化聚类中心
 17 def begin_cluster_center(data_points,k):
 18     center=[]
 19     length=len(data_points)#长度
 20     rand_data = random.sample(range(0,length), k)#生成k个不同随机数
 21     for i in range(k):#得出k个聚类中心(随机选出)
 22         center.append(data_points[rand_data[i]])
 23     return center
 24  
 25 #计算最短距离(欧式距离)
 26 def distance(a,b):
 27     length=len(a)
 28     sum = 0
 29     for i in range(length):
 30         sq = (a[i] - b[i]) ** 2
 31         sum += sq
 32     return sqrt(sum)
 33 #分配样本
 34 # 按照最短距离将所有样本分配到k个聚类中心中的某一个
 35 def assign_points(data_points,center,k):
 36     assignment=[]
 37     for i in range(k):
 38         assignment.append([])
 39     for point in data_points:
 40         min = 10000000
 41         flag = -1
 42         for i in range(k):
 43             value=distance(point,center[i])#计算每个点到聚类中心的距离
 44             if value<min:
 45                 min=value#记录距离的最小值
 46                 flag=i   #记录此时聚类中心的下标
 47         assignment[flag].append(point)
 48     return assignment
 49  
 50 #更新聚类中心,计算每一簇中所有点的平均值
 51 def update_cluster_center(center,assignment,k):
 52     for i in range(k):#assignment中的每一簇
 53         x=0
 54         y=0
 55         length=len(assignment[i])#每一簇的长度
 56         if length!=0:
 57             for j in range(length):  # 每一簇中的每个点
 58                 x += assignment[i][j][0]  # 横坐标之和
 59                 y += assignment[i][j][1]  # 纵坐标之和
 60             center[i] = (x / length, y / length)
 61     return center
 62  
 63 #计算平方误差
 64 def getE(assignment,center):
 65     sum_E=0
 66     for i in range(len(assignment)):
 67         for j in range(len(assignment[i])):
 68             sum_E+=distance(assignment[i][j],center[i])
 69     return sum_E
 70  
 71 #计算各个聚类中心的新向量,更新距离,即每一类中每一维均值向量。
 72 # 然后再进行分配,比较前后两个聚类中心向量是否相等,若不相等则进行循环,
 73 # 否则终止循环,进入下一步。
 74 def k_means(data_points,k):
 75     # 由于初始聚类中心是随机选择的,十分影响聚类的结果,聚类可能会出现有较大误差的现象
 76     # 因此如果由初始聚类中心第一次分配后有结果为空,重新选择初始聚类中心,重新再聚一遍,直到符合要求
 77     while 1:
 78         # 产生初始聚类中心
 79         begin_center = begin_cluster_center(data_points, k)
 80         # 第一次分配样本
 81         assignment = assign_points(data_points, begin_center, k)
 82         for i in range(k):
 83             if len(assignment[i]) == 0:#第一次分配之后有结果为空,说明聚类中心没选好,重新产生初始聚类中心
 84                 continue
 85         break
 86     #第一次的平方误差
 87     begin_sum_E=getE(assignment,begin_center)
 88     # 更新聚类中心
 89     end_center = update_cluster_center(begin_center, assignment, k)
 90     # 第二次分配样本
 91     assignment = assign_points(data_points, end_center, k)
 92     # 第二次的平方误差
 93     end_sum_E = getE(assignment, end_center)
 94     count = 2  # 计数器
 95     #比较前后两个聚类中心向量是否相等
 96     #print(compare(end_center,begin_center)==False)
 97     while( begin_sum_E != end_sum_E):
 98         begin_center=end_center
 99         begin_sum_E=end_sum_E
100         # 再次更新聚类中心
101         end_center = update_cluster_center(begin_center, assignment, k)
102         # 进行分配
103         assignment = assign_points(data_points, end_center, k)
104         #计算误差
105         end_sum_E = getE(assignment, end_center)
106         count = count + 1      #计数器加1
107     return assignment,end_sum_E,end_center,count
108 def print_result(count,end_sum_E,k,assignment):
109     # 打印最终聚类结果
110     print(经过, count, 次聚类,平方误差为:, end_sum_E)
111     print(---------------------------------分类结果---------------------------------------)
112     for i in range(k):
113         print(,i+1,类数据:,assignment[i])
114     print(--------------------------------------------------------------------------------\n)
115  
116 def plot(k, assignment,center):
117     #初始坐标列表
118     x = []
119     y = []
120     for i in range(k):
121         x.append([])
122         y.append([])
123     # 填充坐标 并绘制散点图
124     for j in range(k):
125         for i in range(len(assignment[j])):
126             x[j].append(assignment[j][i][0])# 横坐标填充
127         for i in range(len(assignment[j])):
128             y[j].append(assignment[j][i][1])# 纵坐标填充
129         plt.scatter(x[j], y[j],marker=o)
130         plt.scatter(center[j][0], center[j][1],c=b,marker=*)#画聚类中心
131     # 设置标题
132     plt.title(K-means Scatter Diagram)
133     # 设置X轴标签
134     plt.xlabel(X)
135     # 设置Y轴标签
136     plt.ylabel(Y)
137     # 显示散点图
138     plt.show()
139  
140 def main():
141     # 3个聚类中心
142     k = 4
143     data_points =read_data()
144     assignment, end_sum_E, end_center, count = k_means(data_points, k)
145     min_sum_E = 1000
146     #返回较小误差
147     while min_sum_E>end_sum_E:
148         min_sum_E=end_sum_E
149         assignment, end_sum_E, end_center, count = k_means(data_points,k)
150     print_result(count, min_sum_E, k, assignment)#输出结果
151     plot(k, assignment,end_center)#画图
152 main()

 

data文件数据:

2.0 4.2
2.1 5.0
2.3 3.8
1.2 6.1
3.5 4.4
3.6 3.7
3.0 6.2
2.5 5.6
1.7 3.3
0.9 6.0
0.4 4.1
7.0 10.0
8.0 9.0
8.2 8.2
9.3 7.9
7.4 7.1
6.8 8.0
8.1 9.5
8.5 10.4
7.6 8.5
8.6 7.3
7.7 8.8
1.8 10.9
1.5 9.5
1.7 8.7
1.3 9.0
2.8 9.6
2.2 9.9
2.1 10.5
2.5 9.2
3.1 10.4
3.9 9.5
3.7 10.4
2.6 8.2
2.8 9.2
2.2 9.3
3.4 8.5
8.1 1.3
8.5 2.4
8.8 3.3
9.0 1.2
10.7 2.9
7.9 3.7
7.5 2.5
8.5 0.6
10.8 1.6
9.2 0.5
6.8 2.0
8.5 3.6
10.0 1.7

  

关于k-means聚类算法的原理及解析

原文:https://www.cnblogs.com/yby-algorithm/p/14016694.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!