k均值聚类算法优缺点_机器学习算法之K均值聚类使用sklearn

K  -  均  值  聚  类 1、sklearn.cluster简介     ba9c11b045fadcdff5cee2f842903beb.png使用 sklearn.cluster 模块里的 KMeans 函数即可实现K均值聚类。同样,函数中参数众多。具体如下:

3483a49e7cb9763ab76672f1f9835456.png

52ddb7b7accb0f5676fdb96c8920c4b7.png

c5804fb4ffd9a59aa0c51dc60bb7750e.png

  • n_clusters:生成的聚类数,即产生的质心(centroids)数。默认为8

  • init:指定初始化方法。有三个可选值:’k-means++’, ‘random’,或者传递一个 ndarray 向量。默认值为 ‘k-means++’。

  • k-means++:用一种特殊的方法选定初始质心从而能加速迭代过程的收敛

  • random:随机从训练数据中选取初始质心。

  • 如果传递的是一个ndarray,则应该形如 (n_clusters, n_features) 并给出初始质心。

  • n_init:用不同的质心初始化值运行算法的次数,最终解是在inertia意义下选出的最优结果。默认为10。

  • max_iter:执行一次k-means算法所进行的最大迭代数。默认为300。

  • tol:与inertia结合来确定收敛条件。默认为1e-4 。

  • precompute_distances:预计算距离,计算速度更快但占用更多内存。三个可选值,‘auto’,True 或者 False。默认为auto。

  • auto:如果样本数乘以聚类数大于 12million 的话则不预计算距离。这相当于使用双倍精度的每个作业大约100mb的开销

  • True:总是预先计算距离。

  • False:永远不预先计算距离。

  • random_state:用于初始化质心的生成器(generator)。如果值为一个整数,则确定一个seed。此参数默认值为numpy的随机数生成器。

  • copy_x:默认值=True。当我们precomputing distances时,将数据中心化会得到更准确的结果。如果把此参数值设为True,则原始数据不会被改变。如果是False,则会直接在原始数据上做修改并在函数返回值时将其还原。但是在计算过程中由于有对数据均值的加减运算,所以数据返回后,原始数据和计算前可能会有细小差别。

  • n_jobs:指定计算所用的进程数,内部原理是同时进行n_init指定次数的计算。

  • 若值为 -1,则用所有的CPU进行运算。若值为1,则不进行并行运算,这样的话方便调试。

  • 若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1。

同样,里面也有相应的方法供我们调用。

9680c3ced91601bcfd4291303d634763.png

2、使用sklearn实现K-means   ba9c11b045fadcdff5cee2f842903beb.png这里,我们使用 m ake_ blobs函数自己创建一个数据集,并把数据画出来看一下。

109eb7d9c579da95fb2f003c17bdc6fe.png

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)  # X是数据特征值集合,y是类别 fig, ax1 = plt.subplots(1)  # 创建一个子图,返回 Figure对象(fig) 和 子图对象(ax1)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()

5d1b5ad4f1b78ee3e031b716710ad8f5.png

ee60e380f72881af9677f183cda46a00.png

接下来使用Kmeans进行聚类
from sklearn.cluster import KMeans k = 3  # 猜测的 簇 个数cluster0 = KMeans(n_clusters=k, random_state=0).fit(X)  # 创建模型并fit,先 猜测 数据中有 三簇# 属性 labels_:模型 聚类 得到的类别(每个样本所对应类)y_pred = cluster0.labels_ print("使用模型进行聚类得到的类别: \n", y_pred)# 属性 cluster_centers_:最终得到的所有的质心centroid = cluster0.cluster_centers_print("最终的质心: \n", centroid)print(centroid.shape)# 属性 inertia_:总距离平方和---越小越好inertia = cluster0.inertia_print("总距离平方和: ", inertia)

运行结果:

a40ce66d4ce8b36ee21389169e3cbbf4.png

下面,画图(结果可视化)。
color = ["red","pink","orange","gray"]fig, ax1 = plt.subplots(1)for i in range(k):    ax1.scatter(X[y_pred==i, 0], X[y_pred==i, 1], marker='o', s=8, c=color[i])  # 画出分类的数据散点图ax1.scatter(centroid[:,0], centroid[:,1], marker="x", s=30, c="black")  # 画出质心plt.show()
结果:

d2a183c7e39011759e2ff42bda90e287.png

可以看到,当 k=3 时,总距离平方和为1903,现在把 k 设为 4 ,看一下总距离平方和会不会降低一点。
k = 4cluster1 = KMeans(n_clusters=k, random_state=0).fit(X)# 属性 inertia_:总距离平方和---越小越好inertia = cluster1.inertia_print("总距离平方和: ", inertia)

0cf798a8d7096d426334ee135ba0da68.png

当 k=4 时,总距离平方和大大降低了。那 k=5 又会怎样呢?

我们把上述代码的k=4改为k=5,运行:

838939d8b05eb628abee8a85560d7aa5.png

可以看到,总距离平方和又再次降低了。实际上,当我们设的 k 越大(不超过样本数),总距离平方和就会越小。这是因为,k越大,则质心就越多,例如当k为500时,那么就相当于每一个数据点都是一个质心,那此时总距离平方和直接就会等于0了。

那如何才能衡量模型的好坏呢(评估模型)?

因为KMeans的目标是确保“簇内差异小,簇外差异大”,所以就可以通过衡量簇内差异来衡量聚类的效果。总距离平方和是用距离来衡量簇内差异的指标,但通过上面的实验,可以看到,他并不能作为衡量的标准。这里可以使用 轮廓系数 来衡量。 

  • 轮廓系数范围是(-1,1),其中:

  • 轮廓系数 越接近 1 表示 样本 与 自己所在的簇中的样本 很相似,并且与 其他簇 中的样本 不相似 

  • 轮廓系数就为 负 时,代表 样本点 与 簇外的样本 更相似 

  • 轮廓系数为 0 时,代表 两个簇 中的 样本相似度 一致,两个簇本应该是一个簇。

  • 如果一个簇中的大多数样本具有比较高的轮廓系数,则簇会有较高的总轮廓系数,则整个数据集的平均轮廓系数越高,则聚类是合适的。

  • 如果许多样本点具有低轮廓系数甚至负值,则聚类是不合适的,聚类的超参数K可能设定得 太大 或 太小。

在sklearn中,可以使用模块 metrics 中的类 silhouette_score 来计算轮廓系数,它返回的是一个数据集中,所有样本的轮廓系数的均值。

还有同在 metrics 模块中的 silhouette_sample,它的参数与轮廓系数一致,但返回的是数据集中每个样本自己的轮廓系数。

from sklearn.metrics import silhouette_scorefrom sklearn.metrics import silhouette_samples score0 = silhouette_score(X, cluster0.labels_)  # 使用k=3时,数据集 得到的聚类效果(轮廓系数)score1 = silhouette_score(X, cluster1.labels_)  # k=4score2 = silhouette_score(X, cluster2.labels_)  # k=5print(score0)print(score1)print(score2)

4396cb6d1539636ece9ae929b0a56995.png

可以看到,k=4时,轮廓系数最大,也就是聚类效果最好。我们也可以查看 数据集上 每个数据 的 轮廓系数(这里以k=4的聚类结果为例)。
print(silhouette_samples(X,cluster1.labels_))

6093bee5983f1a7742a381d9647b9e5f.png

可以看到,轮廓系数基本都为正,这代表聚类效果不错。 3、调参              ba9c11b045fadcdff5cee2f842903beb.png这里将介绍 基于轮廓系数来选择 KMeans 函数中的 n_clusters,也就是簇的个数 K。我们通常会 绘制 轮廓系数分布图聚类后的数据分布图 来选择我们的最佳n_clusters。
from sklearn.cluster import KMeansfrom sklearn.metrics import silhouette_samples, silhouette_scoreimport matplotlib.pyplot as pltimport matplotlib.cm as cmimport numpy as np# 下面两行用于使用 matplotlib 画图时 显示中文字体plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签plt.rcParams['axes.unicode_minus']=False  #用来正常显示负号for k in [2,3,4,5,6,7]:    n_clusters = k    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("当n_clusters为 ", n_clusters, " 时,所有样本点的轮廓系数是 ", silhouette_avg)        sample_silhouette_values = silhouette_samples(X, cluster_labels)  # 获得每个样本点的轮廓系数        y_lower = 10  # 设置 y轴 的初始取值     # 对每个簇进行循环    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_upper = y_lower + size_cluster_i  # 一个簇在y轴的取值由初始值(y_lower)开始,到初始值加上这个簇中的样本数量结束(y_upper)                color = cm.nipy_spectral(float(i)/n_clusters)  #用i的浮点数除以n_clusters,在不同的i下生成不同的小数,以确保所有的簇都有不同的颜色                # fill_between:让一个范围的柱状图都统一颜色的函数        # 其 范围是在 纵坐标 上,参数输入为:纵坐标的下限,纵坐标的上限,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("不同簇下的轮廓系数")  # 图的名字    ax1.set_xlabel("轮廓系数值")  # x轴标签    ax1.set_ylabel("簇标签")  # y轴标签    ax1.axvline(x=silhouette_avg, color="red", linestyle="--")  # 把整个数据集上的 轮廓系数的均值 以 虚线 形式放入图中    ax1.set_yticks([])  # 让y轴不显示任何刻度    ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])  # 让X轴上的刻度显示为规定的列表        # 第二个子图    # 首先获取新的颜色,由于没有循环需要一次性生成多个小数来获取多个颜色    #     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("聚类后的数据分布图")    ax2.set_xlabel("特征值1")    ax2.set_ylabel("特征值2")        # 为整个图设置标题    plt.suptitle(("Silhouette analysis for KMeans clustering on sample data with n_clusters = %d" % n_clusters), fontsize=14, fontweight='bold')    plt.show()
运行结果比较长,这里截取部分。

b60f936896ca51bd305293d0c7eba77a.png

通过对不同k值下的轮廓系数进行比较,会发现当 k=4 时,该数据集的聚类效果最好。其中柱状图中的三个颜色分别对应了其相应颜色的簇中的轮廓系数。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值