sklearn中的KMeans算法

  1、聚类算法又叫做“无监督分类”,其目的是将数据划分成有意义或有用的组(或簇)。这种划分可以基于我们的业务需求或建模需求来完成,也可以单纯地帮助我们探索数据的自然结构和分布。

  2、KMeans算法将一组N个样本的特征矩阵X划分为K个无交集的簇,直观上来看是簇是一组一组聚集在一起的数据,在一个簇中的数据就认为是同一类。簇就是聚类的结果表现。簇中所有数据的均值通常被称为这个簇的“质心”(centroids)。在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。

  3、KMeans追求的是‘簇内差异小,簇间差异大’。

  所有簇的簇内平方和相加,就得到了整体平方和,又叫做total inertia。Total Inertia越小,代表着每个簇内样本越相似,聚类的效果就越好。因此KMeans追求的是,求解能够让Inertia最小化的质心。实际上,在质心不断变化不断迭代的过程中,总体平方和是越来越小的。

  注:损失函数本质是用来衡量模型的拟合效果的,只有有着求解参数需求的算法,才会有损失函数。Kmeans不求解什么参数,它的模型本质也没有在拟合数据,而是在对数据进行一种探索,故Kmeans不存在损失函数,Inertia更像是Kmeans的评估指标,而不是损失函数。

  除了模型本身的效果之外,我们还使用另一种角度来度量算法:算法复杂度。算法的复杂度分为时间复杂度和空间复杂度,时间复杂度是指执行算法所需要的计算工作量,常用大O符号表述;而空间复杂度是指执行这个算法所需要的内存空间。如果一个算法的效果很好,但需要的时间复杂度和空间复杂度都很大,那我们将会权衡算法的效果

  和所需的计算成本。和KNN一样,KMeans算法是一个计算成本很大的算法。

  聚类模型的结果不是某种标签输出,并且聚类的结果是不确定的,其优劣由业务需求或者算法需求来决定,并且没有永远的正确答案。

  用inertia作为衡量指标并不合适,一个较小的Inertia究竟有没有达到模型的极限,能否继续提高;Inertia的计算太容易受到特征数目的影响,数据维度很大的时候,Inertia的计算量会陷入维度诅咒之中,计算量会爆炸,不适合用来一次次评估模型;Inertia还会受到超参数K的影响,随着K越大,Inertia注定会越来越小,但这并不代表模型的效果越来越好了;Inertia对数据的分布有假设,它假设数据满足凸分布并且它假设数据是各向同性的,即是说数据的属性在不同方向上代表着相同的含义,但是现实中的数据往往不是这样,所以使用Inertia作为评估指标,会让聚类算法在一些细长簇,环形簇,或者不规则形状的流形时表现不佳。

  4、KMeans模型评估指标,分两种:

  标签已知时,如果拥有真实标签,我们更倾向于使用分类算法。但不排除我们依然可能使用聚类算法的可能性。如果我们有样本真实聚类情况的数据,我们可以对于聚类算法的结果和真实结果来衡量聚类的效果。常用的有以下三种方法:

  互信息分;V-measure(基于条件上分析的一系列直观度量);调整兰德系数

  真实标签未知时,轮廓系数(评价簇内的稠密程度(簇内差异小)和簇间的离散程度(簇外差异大)来评估聚类的效果),卡林斯基-哈拉巴斯指数(Calinski-Harabaz Index,简称CHI,也被称为方差比标准),戴维斯-布尔丁指数(Davies-Bouldin)以及权变矩阵(Contingency Matrix)

  轮廓系数的范围是(-1,1),值越接近1表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似;当样本点与簇外的样本更相似的时候,轮廓系数就为负;当轮廓系数为0时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。在sklearn中,我们使用模块metrics中的类silhouette_score来计算轮廓系数,它返回的是一个数据集中,所有样本的轮廓系数的均值。但我们还有同在metrics模块中的silhouette_sample,它的参数与轮廓系数一致,但返回的是数据集中每个样本自己的轮廓系数。

  基于轮廓系数选择最佳的n_clusters

  from sklearn.datasets import make_blobs

  import matplotlib.pyplot as plt

  #创建数据集

  X,y=make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)

  fig,ax1=plt.subplots(1)

  ax1.scatter(X[:,0],X[:,1],marker='o',s=8)

  plt.show()

  #添加颜色

  color=['red','pink','orange','gray']

  fig,ax1=plt.subplots(1)

  for i in range(4):

  ax1.scatter(X[y==i,0],X[y==i,1],marker='o',s=8,c=color[i])

  plt.show()

  from sklearn.cluster import KMeans

  from sklearn.metrics import silhouette_samples,silhouette_score

  import matplotlib.pyplot as plt

  import matplotlib.cm as cm

  import numpy as np

  #基于轮廓系数来选择最佳的n_clusters

  #知道每个聚出来的类的轮廓系数是多少,还有各个类之间的轮廓系数的对比

  #知道聚类完毕以后图像的分布是什么样的

  #先设定要分成的簇数

  n_clusters=4

  #创建一个画布,画布上有一行两列两个图

  fig,(ax1,ax2)=plt.subplots(1,2)

  #设置画布尺寸

  fig.set_size_inches(18,7)

  ax1.set_xlim([-0.1,1])

  ax1.set_ylim([0,X.shape[0]+(n_clusters+1)*10])

  #建模,调用聚类好的标签

  clusterer=KMeans(n_clusters=n_clusters,random_state=10).fit(X)

  cluster_labels=clusterer.labels_

  #调用轮廓系数分数,silhouette_avg生成所有样本点轮廓系数的均值

  #需要输入两个参数,特征矩阵X与聚类完毕的标签

  silhouette_avg = silhouette_score(X, cluster_labels)

  #打印现有簇数量下,轮廓系数是多少

  print("For n_clusters =", n_clusters,

  "The average silhouette_score is :", silhouette_avg)

  #调用silhouette_samples,返回每个样本点的轮廓系数,就是横坐标

  sample_silhouette_values = silhouette_samples(X, cluster_labels)

  #设置Y轴的初始取值

  y_lower = 10

  #对每个簇进行循环

  for i in range(n_clusters):

  #从每个样本的轮廓系数结果中抽取第i个簇的轮廓系数,并进行排序

  ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]

  #注意,.sort会直接改掉原数据的顺序

  ith_cluster_silhouette_values.sort()

  #查看簇中究竟有多少个样本

  size_cluster_i = ith_cluster_silhouette_values.shape[0]

  #一个簇在y州的取值是由初始值(y_lower)开始,到初始值加上这个簇中的样本数量结束(y_upper)

  y_upper = y_lower + size_cluster_i

  #用i的浮点数除以n_clusters,在不同的i下生成不同的小数,以确保所有的簇都有不同的颜色

  color = cm.nipy_spectral(float(i)/n_clusters)

  #fill_between是让一个范围的柱状图都统一颜色的函数,

  #fill_betweenx的范围是在纵坐标上,参数输入(纵坐标的下限,纵坐标的上限,X轴上的取值,柱状图的颜色)

  ax1.fill_betweenx(np.arange(y_lower, y_upper)

  ,ith_cluster_silhouette_values

  ,facecolor=color

  ,alpha=0.7)

  #为每个簇的轮廓系数写上编号,并让簇的编号显示在坐标轴每个条形图的中间位置

  #text参数(要显示编号位置的横坐标,纵坐标,编号内容)

  ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))

  #为下一个簇计算新的y轴上的初始值,每一次迭代后y再加上10以保证不同簇的图像之间显示有空隙

  y_lower = y_upper + 10

  ax1.set_title("The silhouette plot for the various clusters.")

  ax1.set_xlabel("The silhouette coefficient values")

  ax1.set_ylabel("Cluster label")

  # 把整个数据集上的轮廓系数的均值以虚线形式放入图中

  ax1.axvline(x=silhouette_avg, color="red", linestyle="--")

  #让y轴不显示任何刻度

  ax1.set_yticks([])

  #让X轴上的刻度显示为规定的列表

  ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

  #开始处理第二个图,首先获取新的颜色,由于没有循环需要一次性生成多个小数来获取多个颜色

  #cluster_labels.astype(float) 生成浮点数,nipy_spectral只能用浮点数,500个值只有4个颜色

  colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)

  ax2.scatter(X[:, 0], X[:, 1],marker='o',s=8,c=colors)

  #把生成的质心放在图像中

  centers = clusterer.cluster_centers_

  ax2.scatter(centers[:, 0], centers[:, 1], marker='x',c="red", alpha=1, s=200)

  ax2.set_title("The visualization of the clustered data.")

  ax2.set_xlabel("Feature space for the 1st feature")

  ax2.set_ylabel("Feature space for the 2nd feature")

  #为整个图设置标题

  plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "

  "with n_clusters = %d" % n_clusters),

  fontsize=14, fontweight='bold')

  plt.show()无锡妇科医院 http://www.bhnnk120.com/

  #将上述过程包装称循环

  for n_clusters in [2,3,4,5,6,7]:

  n_clusters = n_clusters

  fig, (ax1, ax2) = plt.subplots(1, 2)

  fig.set_size_inches(18, 7)

  ax1.set_xlim([-0.1, 1])

  ax1.set_ylim([0, X.shape[0] + (n_clusters + 1) * 10])

  clusterer = KMeans(n_clusters=n_clusters, random_state=10).fit(X)

  cluster_labels = clusterer.labels_

  silhouette_avg = silhouette_score(X, cluster_labels)

  print("For n_clusters =", n_clusters,"The average silhouette_score is :", silhouette_avg)

  sample_silhouette_values = silhouette_samples(X, cluster_labels)

  y_lower = 10

  for i in range(n_clusters):

  ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]

  ith_cluster_silhouette_values.sort()

  size_cluster_i = ith_cluster_silhouette_values.shape[0]

  y_upper = y_lower + size_cluster_i

  color = cm.nipy_spectral(float(i)/n_clusters)

  ax1.fill_betweenx(np.arange(y_lower, y_upper)

  ,ith_cluster_silhouette_values

  ,facecolor=color

  ,alpha=0.7)

  ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))

  y_lower = y_upper + 10

  ax1.set_title("The silhouette plot for the various clusters.")

  ax1.set_xlabel("The silhouette coefficient values")

  ax1.set_ylabel("Cluster label")

  ax1.axvline(x=silhouette_avg, color="red", linestyle="--")

  ax1.set_yticks([])

  ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

  colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)

  ax2.scatter(X[:, 0], X[:, 1],marker='o',s=8,c=colors)

  centers = clusterer.cluster_centers_

  # Draw white circles at cluster centers

  ax2.scatter(centers[:, 0], centers[:, 1], marker='x',c="red", alpha=1, s=200)

  ax2.set_title("The visualization of the clustered data.")

  ax2.set_xlabel("Feature space for the 1st feature")

  ax2.set_ylabel("Feature space for the 2nd feature")

  plt.suptitle(("Silhouette analysis for KMeans clustering"

  "with n_clusters = %d" % n_clusters),fontsize=14, fontweight='bold')

  plt.show()

  5、初始质心(init)

  init:可输入**“k-means++”,“random"或者一个n维数组**。这是初始化质心的方法,默认"k-means++"。

  输入"kmeans++”:一种为K均值聚类选择初始聚类中心的聪明的办法(使得初始质心通常彼此远离),以加速收敛。

  "random"下,如果不指定随机数种子,则sklearn中的K-means并不会只选择一个随机模式扔出结果,而会在每个随机数种子下运行多次,并使用结果最好的一个随机数种子来作为初始质心。可以使用参数n_init来选择每个随机数种子下运行的次数,这个参数不常用到,默认10次,如果我们希望运行的结果更加精确,那我们可以增加这个参数n_init的值来增加每个随机数种子下运行的次数。然而这种方法依然是基于随机性的。

  如果输入了n维数组,数组的形状应该是(n_clusters,n_features)并给出初始质心。

  6、max_iter & tol:让迭代停下来

  当质心不再移动,Kmeans算法就会停下来,但在完全收敛之前,可以使用max_iter(最大迭代次数)或者tol(两次迭代间Inertia下降的量),这两个参数来让迭代提前停下来。数据量特别大时可以使用。

  max_iter:整数,默认300,单次运行的k-means算法的最大迭代次数

  tol:浮点数,默认1e-4,两次迭代间Inertia下降的量,如果两次迭代之间Inertia下降的值小于tol所设定的值,迭代就会停下

转载于:https://www.cnblogs.com/djw12333/p/11411182.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值