当前位置:   article > 正文

K-Means聚类算法(含Python代码)_k聚类python代码

k聚类python代码

K-Means算法是典型的基于距离的非层次聚类算法,在最小化误差函数的基础上将数据划分为预定的类数K,采用距离作为相似性的评价指标,即认为两个对象的距离越近其相似度就越大。

1.算法过程

1)从N个样本数据中随机选取K个对象作为初始的聚类中心。
2)分别计算每个样本到各个聚类中心的距离,将对象分配到距离最近的聚类中。
3)所有对象分配完成后,重新计算K个聚类的中心。
4)与前一次计算得到的K个聚类中心比较,如果聚类中心发生变化,转过程2),否则转过程5)。
5)当质心不发生变化时停止并输出聚类结果。
聚类的结果可能依赖于初始聚类中心的随机选择,可能使得结果严重偏离全局最优分实践中,为了得到较好的结果,通常选择不同的初始聚类中心,多次运行K-Means算类。法。在所有对象分配完成后,重新计算K个聚类的中心时,对于连续数据,聚类中心取该簇的均值,但是当样本的某些属性是分类变量时,均值可能无定义,可以使用K-众数方法。

2.数据类型与相似度度量

(1)连续属性
对于连续属性,要先对各属性值进行零-均值规范,再进行距离的计算。在K-Means聚类算法中,一般需要度量样本之间的距离、样本与簇之间的距离以及簇与簇之间的距离。

度量样本之间的相似性最常用的是欧几里得距离、曼哈顿距离和闵可夫斯基距离;样本与簇之间的距离可以用样本到簇中心的距离 ;簇与簇之间的距离可以用簇中心的距离。

具体计算公式如下图:

(2)文档数据
对于文档数据使用余弦相似性度量,先将文档数据整理成文档-词矩阵格式,如下图:

文档之间计算公式如下:

3.目标函数

使用误差平方和 SSE作为度量聚类质量的目标函数,对于两种不同的聚类结果,选择误差平方和较小的分类结果。 

符号说明:

连续属性的SSE计算公式为: 

文档数据的 SSE 计算公式为:

簇的聚类中心计算公式:

 

4. 实例

 部分餐饮客户的消费行为特征数据如下。根据这些数据将客户分类成不同客户群并评价这些客户群的价值。

采用K-Means聚类算法,设定聚类个数K为3,最大迭代次数为500次,距离函数取欧氏距离。
K-Means聚类算法的Python 代码如下所示:

1.导入数据

  1. import pandas as pd
  2. #导入数据
  3. inputfile = r'D:\daily\data1\consumption_data.xls' #销量及其他属性数据
  4. k = 3 #聚类的类别
  5. iteration = 500 #聚类最大循环次数
  6. data = pd.read_excel(inputfile, index_col = 'Id') #读取数据

2.数据标准化

data_zs = 1.0*(data - data.mean())/data.std() #数据标准化

3.建立模型 

  1. from sklearn.cluster import KMeans
  2. model = KMeans(n_clusters = k,n_init='auto',max_iter = iteration)
  3. model.fit(data_zs) #开始聚类

4.打印结果

简单打印:

  1. r1 = pd.Series(model.labels_).value_counts() #统计各个类别的数目
  2. r2 = pd.DataFrame(model.cluster_centers_) #找出聚类中心
  3. r = pd.concat([r2, r1], axis = 1)
  4. r.columns = list(data.columns) + [u'类别数目']
  5. print(r)

输出详细结果到excel表:

  1. #详细输出原始数据及其类别
  2. outputfile = r'D:\daily\data1\data_type.xlsx'
  3. r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1)
  4. r.columns = list(data.columns) + [u'聚类类别']
  5. r.to_excel(outputfile) #保存结果

运行结果如下所示:

5.分群的概率密度函数图

 

分群1特点:R间隔相对较小,主要集中在0~30天;消费次数集中在10~25次;消费金额在 500~ 2000。 

 分群2特点:R间隔分布在0~30天;消费次数集中在0~12次;消费金额在0~1800。

分群3特点:R间隔相对较大,间隔分布在30~80天;消费次数集中在0~15次;消费金额在0~ 2000。 

对比分析:分群1时间间隔较短,消费次数多,而且消费金额较大,是高消费、高价值人群。分群2的时间间隔、消费次数和消费金额处于中等水平,代表着一般客户分群3的时间间隔较长,消费次数较少,消费金额也不是特别高,是价值较低的客户群体。 

 6.聚类结果可视化

 TSNE是高维数据的可视化,能够直观地展示研究结果。然而,通常来说输入的特征数是高维的(大于3维),一般难以直接以原特征对聚类结果进行展示。而TSNE 提供了一种有效的数据降维方式,让我们可以在2维或者3维的空间中展示聚类结果。下面我们用 TSNE 对上述K-Means 聚类的结果以二维的方式展示出来。

  1. from sklearn.manifold import TSNE
  2. import matplotlib.pyplot as plt
  3. plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
  4. plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
  5. tsne = TSNE()
  6. tsne.fit_transform(data_zs) #进行数据降维
  7. tsne = pd.DataFrame(tsne.embedding_, index = data_zs.index) #转换数据格式
  8. d = tsne[r[u'聚类类别'] == 0]
  9. plt.plot(d[0], d[1], 'r.')
  10. d = tsne[r[u'聚类类别'] == 1]
  11. plt.plot(d[0], d[1], 'go')
  12. d = tsne[r[u'聚类类别'] == 2]
  13. plt.plot(d[0], d[1], 'b*')
  14. plt.show()

 运行结果如下所示:

 整体代码:

  1. import pandas as pd
  2. from sklearn.cluster import KMeans
  3. from sklearn.manifold import TSNE
  4. import matplotlib.pyplot as plt
  5. plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
  6. plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
  7. inputfile = r'D:\daily\data1\consumption_data.xls'
  8. outputfile = r'D:\daily\data1\data_type.xlsx'
  9. k = 3 #聚类的类别
  10. iteration = 500 #聚类最大循环次数
  11. data = pd.read_excel(inputfile, index_col = 'Id') #读取数据
  12. data_zs = 1.0*(data - data.mean())/data.std() #数据标准化
  13. model = KMeans(n_clusters = k,n_init='auto',max_iter = iteration)
  14. model.fit(data_zs) #开始聚类
  15. #简单打印结果
  16. r1 = pd.Series(model.labels_).value_counts() #统计各个类别的数目
  17. r2 = pd.DataFrame(model.cluster_centers_) #找出聚类中心
  18. r = pd.concat([r2, r1], axis = 1)
  19. r.columns = list(data.columns) + [u'类别数目']
  20. print(r)
  21. #详细输出原始数据及其类别
  22. r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1) #详细输出
  23. r.columns = list(data.columns) + [u'聚类类别']
  24. r.to_excel(outputfile)
  25. #自定义作图函数
  26. def density_plot(data):
  27. import matplotlib.pyplot as plt
  28. plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
  29. plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
  30. p = data.plot(kind='kde', linewidth = 2, subplots = True, sharex = False)
  31. [p[i].set_ylabel(u'密度') for i in range(k)]
  32. plt.legend()
  33. return plt
  34. pic_output = r'D:\daily\data1\pd_' #概率密度图文件名前缀
  35. for i in range(k):
  36. density_plot(data[r[u'聚类类别']==i]).savefig(u'%s%s.png' %(pic_output, i))
  37. tsne = TSNE()
  38. tsne.fit_transform(data_zs) # 进行数据降维
  39. tsne = pd.DataFrame(tsne.embedding_, index=data_zs.index) # 转换数据格式
  40. d = tsne[r[u'聚类类别'] == 0]
  41. plt.plot(d[0], d[1], 'r.')
  42. d = tsne[r[u'聚类类别'] == 1]
  43. plt.plot(d[0], d[1], 'go')
  44. d = tsne[r[u'聚类类别'] == 2]
  45. plt.plot(d[0], d[1], 'b*')
  46. plt.show()
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/678894
推荐阅读
相关标签
  

闽ICP备14008679号