小言_互联网的博客

K-means聚类分析与python实现

437人阅读  评论(0)

    K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。

 

算法原理:

    首先从n个数据对象任意选择 k 个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数。k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。

 

算法优缺点:

优点:

1.对处理大数据集,该算法保持可伸缩性和高效性

2.算法快速、简单,易于理解;

缺点:

1.在 K-means 算法中 K 是事先给定的,这个 K 值的选定是非常难以估计的;

2.若簇中含有异常点,将导致均值偏离严重(即:对噪声和孤立点数据敏感);

3.该算法需要不断地进行样本分类调整,不断地计算调整后的新的聚类中心,因此当数据量非常大时,算法的时间开销是非常大的;

4.在 K-means 算法中,首先需要根据初始聚类中心来确定一个初始划分,然后对初始划分进行优化。这个初始聚类中心的选择对聚类结果有较大的影响,一旦初始值选择的不好,可能无法得到有效的聚类结果;

5.局部最优解而不是全局优 (这个和初始点选谁有关)。

 

算法流程:

step-1:首先从n个数据对象任意选择 k 个对象作为初始聚类中心;

 


  
  1. #随机选择K个点
  2. k = rd.sample(range(count), k_count)
  3. k_point = [[x[i], [y[i]]] for i in k] #保证有序
  4. k_point.sort()

step-2:根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;

 

 


  
  1. km = [[] for i in range(k_count)] #存储每个簇的索引
  2. #遍历所有点
  3. for i in range(count):
  4. cp = [x[i], y[i]] #当前点
  5. #计算cp点到所有质心的距离
  6. _sse = [distance(k_point[j], cp) for j in range(k_count)]
  7. #cp点到那个质心最近
  8. min_index = _sse.index(min(_sse))
  9. #把cp点并入第i簇
  10. km[min_index].append(i)

step-3:重新计算每个(有变化)聚类的均值(中心对象);

 

 


  
  1. #更换质心
  2. step+= 1
  3. k_new = []
  4. for i in range(k_count):
  5. _x = sum([x[j] for j in km[i]]) / len(km[i])
  6. _y = sum([y[j] for j in km[i]]) / len(km[i])
  7. k_new.append([_x, _y])
  8. k_new.sort() #排序

step-4: 循环(2)到(3)直到每个聚类不再发生变化为止

 


  
  1. frames.append(imageio.imread( '1.jpg'))
  2. if (k_new != k_point): #一直循环直到聚类中心没有变化
  3. k_point = k_new
  4. else:
  5. return km

python完整代码实现:

 


  
  1. # coding:utf-8
  2. import numpy as np
  3. import pylab as pl
  4. import random as rd
  5. import imageio
  6. #计算平面两点的欧氏距离
  7. step= 0
  8. color=[ '.r', '.g', '.b', '.y'] #颜色种类
  9. dcolor=[ '*r', '*g', '*b', '*y'] #颜色种类
  10. frames = []
  11. def distance(a, b):
  12. return (a[ 0]- b[ 0]) ** 2 + (a[ 1] - b[ 1]) ** 2
  13. #K均值算法
  14. def k_means(x, y, k_count):
  15. count = len(x) #点的个数
  16. #随机选择K个点
  17. k = rd.sample(range(count), k_count)
  18. k_point = [[x[i], [y[i]]] for i in k] #保证有序
  19. k_point.sort()
  20. global frames
  21. global step
  22. while True:
  23. km = [[] for i in range(k_count)] #存储每个簇的索引
  24. #遍历所有点
  25. for i in range(count):
  26. cp = [x[i], y[i]] #当前点
  27. #计算cp点到所有质心的距离
  28. _sse = [distance(k_point[j], cp) for j in range(k_count)]
  29. #cp点到那个质心最近
  30. min_index = _sse.index(min(_sse))
  31. #把cp点并入第i簇
  32. km[min_index].append(i)
  33. #更换质心
  34. step+= 1
  35. k_new = []
  36. for i in range(k_count):
  37. _x = sum([x[j] for j in km[i]]) / len(km[i])
  38. _y = sum([y[j] for j in km[i]]) / len(km[i])
  39. k_new.append([_x, _y])
  40. k_new.sort() #排序
  41. #使用Matplotlab画图
  42. pl.figure()
  43. pl.title( "N=%d,k=%d iteration:%d"%(count,k_count,step))
  44. for j in range(k_count):
  45. pl.plot([x[i] for i in km[j]], [y[i] for i in km[j]], color[j% 4])
  46. pl.plot(k_point[j][ 0], k_point[j][ 1], dcolor[j% 4])
  47. pl.savefig( "1.jpg")
  48. frames.append(imageio.imread( '1.jpg'))
  49. if (k_new != k_point): #一直循环直到聚类中心没有变化
  50. k_point = k_new
  51. else:
  52. return km
  53. x, y = np.loadtxt( '2.csv', delimiter= ',', unpack= True)
  54. k_count = 4
  55. km = k_means(x, y, k_count)
  56. print step
  57. imageio.mimsave( 'k-means.gif', frames, 'GIF', duration = 0.5)

实验结果:
初始值选取的不同造成结果也不一样,如:

 

 

 

代码:

链接:https://pan.baidu.com/s/1dEEEeWh 

密码:需要的请回复或者支持下,赚点积分!

http://download.csdn.net/download/wind_blast/10155662

 

百度分享密码:thmt

 

参考资料:

k-means百度百科

K-means算法优缺点及改进
 


转载:https://blog.csdn.net/wind_blast/article/details/78779987
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场