当前位置:   article > 正文

KMeans算法( 聚类分析)_kmeans聚类分析

kmeans聚类分析

数据集在文末链接

1 聚类分析相关概念

   1.1 聚类与分类

    分类其实是从特定的数据中挖掘模式,作出判断的过程。比如Gmail邮箱里有垃圾邮件分类器,一开始的时候可能什么都不过滤,在日常使用过程中,我人工对于每一封邮件点选“垃圾”或“不是垃圾”,过一段时间,Gmail就体现出一定的智能,能够自动过滤掉一些垃圾邮件了。这是因为在点选的过程中,其实是给每一条邮件打了一个“标签”,这个标签只有两个值,要么是“垃圾”,要么“不是垃圾”,Gmail就会不断研究哪些特点的邮件是垃圾,哪些特点的不是垃圾,形成一些判别的模式,这样当一封信的邮件到来,就可以自动把邮件分到“垃圾”和“不是垃圾”这两个我们人工设定的分类的其中一个。

      聚类的的目的也是把数据分类,但是事先是不知道如何去分的,完全是算法自己来判断各条数据之间的相似性,相似的就放在一起。在聚类的结论出来之前,我完全不知道每一类有什么特点,一定要根据聚类的结果通过人的经验来分析,看看聚成的这一类大概有什么特点。

    简而言之,聚类分析,没给定划分类别,根据数据的相似度进行分组的一种方法,分组原则是组内距离最小化而组间距离最大化

   1.2 核心思想

    通过迭代寻找k个类簇的一种划分方案,使得用这k个类簇的均值来代表相应各类样本时所得的总体误差最小。

k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。k-means算法的基础是最小误差平方和准则,其代价函数是:

                                                在这里插入图片描述

式中,μc(i)表示第i个聚类的均值。

各类簇内的样本越相似,其与该类均值间的误差平方越小,对所有类所得到的误差平方求和,即可验证分为k类时,各聚类是否是最优的。

  1.3  算法过程

   ①从N个样本数据中随机选取K个对象作为初始的聚类质心;
    ②分别计算每个样本到各个聚类中心的距离,将对象分配到距离最近的聚类中;
    ③所有对象分配完成之后,重新计算K个聚类的质心;
    ④与前一次的K个聚类中心比较,如果发生变化,重复步骤②,否则转到⑤;
    ⑤当质心不在发生变化时,停止聚类过程,并输出聚类结果;
    伪代码:
        随机选择K个点作为初始质心点
        当任意一个点的簇分配结果发生改变时
            对数据集中的每一个数据点
                对每一个质心
                    计算质心与数据点的距离
                将数据点分配到距离最近的簇
        对每一个簇,计算簇中所有点的均值,并将均值作为质心

 1.4 KMeans主要参数

  1. sklearn.cluster.KMeans(
  2. n_cluster = 8, #簇的个数,即拟聚成几类
  3. init = "k-means++", #初始簇中心的获取方法
  4. n_init = 10, #获取初始簇中心的迭代次数,为了弥补初始质心的影响,算法默认会初始10次质心,实现算法,然后返回最优的结果
  5. max_iter = 300, #最大迭代次数,(K-Means算法的实现需要迭代)
  6. tol = 0.0001, #容忍度,即K_Means运行准则收敛的条件
  7. precomoputer_distance = "auto", #用于确认是否需要提前计算距离,有三个值可选,auto,True,False,默认auto,
  8. "auto":如果样本数乘以聚类数(feature*samples)大于12*6则不计算距离.True:总是预算距离,Flase永不预算距离
  9. verbose = 0, #冗长模式
  10. random_state = None, #随机生成簇中心的状态条件
  11. copy_x = True, #是否修改一条数据的标记,如果为True.即复制不修改源数据。bool在sklearn接口中都用到这个参数,即是否对输入的数据继续
  12. copy操作,以便不修改用户的输入数据。
  13. n_jobs = 1, #默认1,计算所用进程数,几核并行,若为-1,则用所有的CPU进行计算,若值为1,不进行并行运算,以方便调试,。
  14. 若为-1,所用CPU(n_cpus+1+n_jobs),值为-2,则用到的CPU为总CPU数减1
  15. algorithm = "auto" #KMeans的实现算法,有auto,full,elkan3种状态,其中full表示用EM方式实现
  16. )

2 问题的提出:

     航空公司经常会对客户进行分类,那么怎样对客户分群,才能区分高价值客户、无价值客户等,
并对不同的客户群体实施个性化的营销策略,以实现利润最大化?
    餐饮企业也会经常碰到此类问题。如何通过对客户的消费行为来评价客户 对企业的贡献度,
从而提高对某些客户群体的关注度,以实现企业利润的最 大化?如何通过客户对菜品的消费明细,
  来判断哪些菜品是招牌菜(客户必点),哪些又是配菜(点了招牌菜或许会点的菜品),以此来提高餐饮的精准采购?

3 模型的建立

对于上面的情景,可使用聚类分析方法处理。

根据航空公司目前积累的大量客户会员信息及其乘坐的航班记录,可以得到包括姓名、乘机的间隔、乘机次数 、消费金额等十几条属性信息。
    本情景案例是想要获取客户价值,识别客户价值应用的最广泛的模型是RFM模型,三个字母分别代表Recency(最近消费时间间隔)、
Frequency(消费频率)、 Monetary(消费金额)这三个指标。结合具体情景,最终选取客户消费时间间隔R、消费频率F、消费金额M这三个指标作为
航空公司识别客户价值的指标。
    为了方便说明操作步骤,本案例简单选择三个指标进行K-Means聚类分析来识别出最优价值的客户。航空公司在真实的判断客户类别时,
选取的观测维度要大得多。

                         在这里插入图片描述

本情景案例的 主要步骤包括 :

(1)对数据集进行清洗处理,包括数据缺失与异常处理、数据属性的规 约、数据清洗和变换,把数据处理成可使用的数据( Data);
(2)利用已预 处理的数据(data),基于盯M 模型进行客户分群,对各个 客户群进行特征分析,对客户进行分类;
(3)针对不同 类型的客户制定不同的营销政策,实行个性化服务。

4 Python 代码实现 

步骤一: 参数初始化

  1. from pylab import mpl
  2. mpl.rcParams['font.sans-serif'] = ['SimHei']
  3. mpl.rcParams['axes.unicode_minus'] = False
  4. import pandas as pd
  5. from matplotlib import pyplot as plt
  6. from sklearn.cluster import KMeans
  7. from pandas import Series,DataFrame
  8. import time
  9. class KMeans_AirPlane(object):
  10. def __init__(self):
  11. self.data = pd.read_excel(r'./files/AirPlane.xlsx',index_col="Id",sheet_name=0,encoding="utf-8-sig") #读取数据
  12. self.cleanedfile = r'./files/CleanedData.xls' #数据清洗后的结果文件
  13. self.zscoredfile = r'./files/ZscoredData.xls' #标准化后的数据文件
  14. self.outputfile = r'./files/DataType.xls' #样本类别对应的文件
  15. self.outputpic = "./files/pd_" #概率密度图文件名前缀
  16. self.k = 3 #聚类的类别
  17. self.maxIteration = 500 #聚类最大循环数

步骤二: 读取数据,清洗:去除缺失数据,对部分数据转化

  1. def cleanData(self):
  2. df = self.data.drop_duplicates() #以防万一,去除重复数据
  3. df = df[df["Monetary"].notnull()] #保留总消费非空的数据 inuc 877
  4. #瞎处理的数据,练习练习
  5. index1 = df["Recency"] != 0
  6. index2 = df["Frequency"] != 0
  7. index3 = (df["Monetary"] != 0)&(df["Frequency"] != 0) #逻辑与
  8. df = df[index1 | index2 | index3] # 逻辑或
  9. try:
  10. df.to_excel(self.cleanedfile)
  11. except:
  12. print("数据清理保存失败。")
  13. else:
  14. print("数据清理完成,保存成功。")

步骤三: 标准化处理

  1. def standard(self):
  2. data = pd.read_excel(self.cleanedfile,encoding="utf-8-sig",index_col="Id",sheet_name=0)#读取处理后的数据
  3. data = (data-data.mean(axis=0)) / data.std(axis=0) #数据表标准化
  4. try:
  5. data.to_excel(self.zscoredfile,index=False) #标准化后数据写入zscoredfile
  6. except:
  7. print("数据标准化失败。")
  8. else:
  9. print("数据标准化成功。")

步骤四: K-Means算法聚类消费行为特征数据

  1. def kmeansProcessData(self):
  2. kdata = pd.read_excel(self.zscoredfile,encoding="utf-8-sig")
  3. #分为k类;n_jobs为并发数,一般最好等于CPU核数;
  4. kmodel = KMeans(n_clusters=self.k,n_jobs=4,max_iter=self.maxIteration)
  5. kmodel.fit(kdata) #训练模型,开始聚类
  6. # print(kmodel)
  7. r1 = Series(kmodel.labels_).value_counts() #统计各个类别的数目
  8. r2 = DataFrame(kmodel.cluster_centers_) #找出聚类中心
  9. r = pd.concat([r1,r2],axis=1)
  10. r.columns = list(kdata.columns) + [u"类别数目"] #重命名表头
  11. # print(r)
  12. '''
  13. Recency Frequency Monetary 类别数目
  14. 0 520 -0.165820 -0.671795 -0.299179
  15. 1 339 -0.147391 1.070541 0.403429
  16. 2 40 3.405259 -0.295940 0.487837
  17. '''
  18. r = pd.concat([kdata,Series(kmodel.labels_,index=kdata.index)],axis=1)
  19. r.columns = list(kdata.columns) + [u'聚类类别'] #重命名表头
  20. # print(r)
  21. '''
  22. Recency Frequency Monetary 聚类类别
  23. 0 0.309287 1.024322 0.303116 2
  24. 1 -1.161483 1.300817 0.992527 2
  25. 2 -0.646714 -0.772894 -0.628962 1
  26. 3 -0.499637 -0.081657 0.484777 1
  27. 4 -0.940868 -0.911141 1.072565 1
  28. .. ... ... ... ...
  29. 894 0.309287 -0.496399 0.698166 1
  30. 895 -1.161483 1.439064 1.316807 2
  31. 896 -0.279021 2.406796 -0.481132 2
  32. 897 -0.058405 -0.496399 -0.457503 1
  33. 898 2.883135 -0.772894 1.198429 0
  34. [899 rows x 4 columns]
  35. '''
  36. try:
  37. r.to_excel(self.outputfile,encoding="utf-8-sig")
  38. except:
  39. print("数据聚类分析失败")
  40. else:
  41. print("数据聚类分析成功!!!")

步骤五:导出各自类别的概率密度图

  1. def dent_plt_pic(self,kdata,index):
  2. p = kdata.plot(kind='kde', linewidth=2, subplots=True, sharex=False)
  3. [p[i].set_ylabel(u'密度') for i in range(self.k)]
  4. plt.xlabel('分群%s'%(int(index)+1))
  5. plt.legend()
  6. return plt
  7. def plt_pic(self):
  8. kdata = pd.read_excel(self.outputfile, encoding="utf-8-sig")
  9. cdata = pd.read_excel(self.cleanedfile,encoding="utf-8-sig")
  10. time.sleep(1)
  11. for i in range(self.k):
  12. self.dent_plt_pic(cdata[kdata[u'聚类类别']==i],index=i).savefig(u'%s%s.png'%(self.outputpic, i))
  13. print("概率密度函数图文绘画完毕!!")

 整体代码

  1. # -*- coding: UTF-8 -*-
  2. '''
  3. @Author :Jason
  4. '''
  5. from pylab import mpl
  6. mpl.rcParams['font.sans-serif'] = ['SimHei']
  7. mpl.rcParams['axes.unicode_minus'] = False
  8. import pandas as pd
  9. from matplotlib import pyplot as plt
  10. from sklearn.cluster import KMeans
  11. from pandas import Series,DataFrame
  12. import time
  13. class KMeans_AirPlane(object):
  14. def __init__(self):
  15. self.data = pd.read_excel(r'./files/AirPlane.xlsx',index_col="Id",sheet_name=0,encoding="utf-8-sig") #读取数据
  16. self.cleanedfile = r'./files/CleanedData.xls' #数据清洗后的结果文件
  17. self.zscoredfile = r'./files/ZscoredData.xls' #标准化后的数据文件
  18. self.outputfile = r'./files/DataType.xls' #样本类别对应的文件
  19. self.outputpic = "./files/pd_" #概率密度图文件名前缀
  20. self.k = 3 #聚类的类别
  21. self.maxIteration = 500 #聚类最大循环数
  22. def cleanData(self):
  23. df = self.data.drop_duplicates() #以防万一,去除重复数据
  24. df = df[df["Monetary"].notnull()] #保留总消费非空的数据 inuc 877行
  25. #瞎处理的数据,练习练习
  26. index1 = df["Recency"] != 0
  27. index2 = df["Frequency"] != 0
  28. index3 = (df["Monetary"] != 0)&(df["Frequency"] != 0) #逻辑与
  29. df = df[index1 | index2 | index3] # 逻辑或
  30. try:
  31. df.to_excel(self.cleanedfile)
  32. except:
  33. print("数据清理保存失败。")
  34. else:
  35. print("数据清理完成,保存成功。")
  36. def standard(self):
  37. #此函数用来将数据标准化
  38. data = pd.read_excel(self.cleanedfile,encoding="utf-8-sig",index_col="Id",sheet_name=0)#读取处理后的数据
  39. data = (data-data.mean(axis=0)) / data.std(axis=0) #数据表标准化
  40. try:
  41. data.to_excel(self.zscoredfile,index=False) #标准化后数据写入zscoredfile
  42. except:
  43. print("数据标准化失败。")
  44. else:
  45. print("数据标准化成功。")
  46. def kmeansProcessData(self):
  47. kdata = pd.read_excel(self.zscoredfile,encoding="utf-8-sig")
  48. #分为k类;n_jobs为并发数,一般小于CPU核数;
  49. kmodel = KMeans(n_clusters=self.k,n_jobs=4,max_iter=self.maxIteration)
  50. kmodel.fit(kdata) #训练模型,开始聚类
  51. # print(kmodel)
  52. r1 = Series(kmodel.labels_).value_counts() #统计各个类别的数目
  53. r2 = DataFrame(kmodel.cluster_centers_) #找出聚类中心
  54. r = pd.concat([r1,r2],axis=1) #1横向连接,得到聚类中心对应的类别下的数目
  55. r.columns = list(kdata.columns) + [u"类别数目"] #重命名表头
  56. # print(r)
  57. '''
  58. Recency Frequency Monetary 类别数目
  59. 0 520 -0.165820 -0.671795 -0.299179
  60. 1 339 -0.147391 1.070541 0.403429
  61. 2 40 3.405259 -0.295940 0.487837
  62. '''
  63. r = pd.concat([kdata,Series(kmodel.labels_,index=kdata.index)],axis=1)
  64. r.columns = list(kdata.columns) + [u'聚类类别'] #重命名表头
  65. # print(r)
  66. '''
  67. Recency Frequency Monetary 聚类类别
  68. 0 0.309287 1.024322 0.303116 2
  69. 1 -1.161483 1.300817 0.992527 2
  70. 2 -0.646714 -0.772894 -0.628962 1
  71. 3 -0.499637 -0.081657 0.484777 1
  72. 4 -0.940868 -0.911141 1.072565 1
  73. .. ... ... ... ...
  74. 894 0.309287 -0.496399 0.698166 1
  75. 895 -1.161483 1.439064 1.316807 2
  76. 896 -0.279021 2.406796 -0.481132 2
  77. 897 -0.058405 -0.496399 -0.457503 1
  78. 898 2.883135 -0.772894 1.198429 0
  79. [899 rows x 4 columns]
  80. '''
  81. try:
  82. r.to_excel(self.outputfile,encoding="utf-8-sig")
  83. except:
  84. print("数据聚类分析失败")
  85. else:
  86. print("数据聚类分析成功!!!")
  87. def dent_plt_pic(self,kdata,index):
  88. '''
  89. 自定义作图函数
  90. :return:
  91. '''
  92. p = kdata.plot(kind='kde', linewidth=2, subplots=True, sharex=False)
  93. [p[i].set_ylabel(u'密度') for i in range(self.k)]
  94. plt.xlabel('分群%s'%(int(index)+1))
  95. plt.legend()
  96. return plt
  97. def plt_pic(self):
  98. kdata = pd.read_excel(self.outputfile, encoding="utf-8-sig")
  99. cdata = pd.read_excel(self.cleanedfile,encoding="utf-8-sig")
  100. print(kdata)
  101. time.sleep(1)
  102. for i in range(self.k):
  103. self.dent_plt_pic(cdata[kdata[u'聚类类别']==i],index=i).savefig(u'%s%s.png'%(self.outputpic, i))
  104. print("概率密度函数图文绘画完毕!!")
  105. if __name__ == "__main__":
  106. km = KMeans_AirPlane()
  107. km.main()

5 分类结果与相应分析

类别数目和聚类类别在代码中已有相应的print,如下:

  1. '''
  2. Recency Frequency Monetary 类别数目
  3. 0 520 -0.165820 -0.671795 -0.299179
  4. 1 339 -0.147391 1.070541 0.403429
  5. 2 40 3.405259 -0.295940 0.487837
  6. '''
  7. '''
  8. Recency Frequency Monetary 聚类类别
  9. 0 0.309287 1.024322 0.303116 2
  10. 1 -1.161483 1.300817 0.992527 2
  11. 2 -0.646714 -0.772894 -0.628962 1
  12. 3 -0.499637 -0.081657 0.484777 1
  13. 4 -0.940868 -0.911141 1.072565 1
  14. .. ... ... ... ...
  15. 894 0.309287 -0.496399 0.698166 1
  16. 895 -1.161483 1.439064 1.316807 2
  17. 896 -0.279021 2.406796 -0.481132 2
  18. 897 -0.058405 -0.496399 -0.457503 1
  19. 898 2.883135 -0.772894 1.198429 0
  20. [899 rows x 4 columns]
  21. '''

各分群的概率密度图像如下:

分群1:

                         

分群2:

                         

分群3:

                     

分析:

     分群1客户特点:

         Recency 间隔分布在0-30天,Frequency集中在0-12次,Monetray在0-2000元之间

    分群2客户特点:

         Recency 间隔分布在0-30天,Frequency集中在10-24次,Monetray在0-2000元之间

    分群3客户特点:

         Recency 间隔分布在25-100天,Frequency集中在0-18次,Monetray在0-2000元之间

对比分析:

    基于特征描述,本案例定义4个等级的客户案例:重要保持客户、重要发展客户、重要挽留客户、一般客户或低价值客户,每种客户类型特征如下:

      1、重要保持客户:最近乘坐公司航班(R)较低,乘坐的次数(F)或总消费额度(M)较高。这类客户对航空公司贡献最高,应尽可能延长这类客户的高消费水平。
       2、重要发展客户:最近乘坐公司航班(R)较低,乘坐的次数(F)或总消费额度(M)较低。这类客户是航空公司的潜在价值客户,需要努力促使增加他们的乘机消费。
       3、重要挽留客户:乘坐的次数(F)或总消费额度(M)较高,但最近乘坐公司航班(R)较低,很久没有乘坐本公司的航班,原因各不相同,需要采取一定的营销手段,延长客户的生命周期。
       4、一般与低价值客户:乘坐的次数(F)或总消费额度(M)较低,最近乘坐公司航班(R)很高,他们是公司的低价值客户,可能只在航空公司打折的时候才会乘坐航班。

     可以看出重要保持客户、重要发展客户、重要挽留客户是最具价值的前三名客户类型,为了深度挖掘航空公司各类型客户的价值,需要提升重要发展客户的价值、稳定和延长重要保持客户的高水平消费、对重要挽留客户积极进行关系恢复,并策划相应的营销策略加强巩固客户关系。

链接:https://pan.baidu.com/s/145mi9UUi9rm8RHOmceThhw 
提取码:v7g9 

参照:《基于Python的大数据分析基础及实战》

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

闽ICP备14008679号