用scikit-learn学习K-Means聚类

K-Means聚类算法原理中,咱们对K-Means的原理作了总结,本文咱们就来讨论用scikit-learn来学习K-Means聚类。重点讲述如何选择合适的k值。html

1、K-Means类概述

    在scikit-learn中,包括两个K-Means的算法,一个是传统的K-Means算法,对应的类是KMeans。另外一个是基于采样的Mini Batch K-Means算法,对应的类是MiniBatchKMeans。通常来讲,使用K-Means的算法调参是比较简单的。python

    用KMeans类的话,通常要注意的仅仅就是k值的选择,即参数n_clusters;若是是用MiniBatchKMeans的话,也仅仅多了须要注意调参的参数batch_size,即咱们的Mini Batch的大小。git

    固然KMeans类和MiniBatchKMeans类能够选择的参数还有很多,可是大多不须要怎么去调参。下面咱们就看看KMeans类和MiniBatchKMeans类的一些主要参数。github

2、2. KMeans类主要参数

    KMeans类的主要参数有:算法

    1) n_clusters: 即咱们的k值,通常须要多试一些值以得到较好的聚类效果。k值好坏的评估标准在下面会讲。微信

    2)max_iter: 最大的迭代次数,通常若是是凸数据集的话能够无论这个值,若是数据集不是凸的,可能很难收敛,此时能够指定最大的迭代次数让算法能够及时退出循环。dom

    3)n_init:用不一样的初始化质心运行算法的次数。因为K-Means是结果受初始值影响的局部最优的迭代算法,所以须要多跑几回以选择一个较好的聚类效果,默认是10,通常不须要改。若是你的k值较大,则能够适当增大这个值。post

    4)init: 即初始值选择的方式,能够为彻底随机选择'random',优化过的'k-means++'或者本身指定初始化的k个质心。通常建议使用默认的'k-means++'。学习

    5)algorithm:有“auto”, “full” or “elkan”三种选择。"full"就是咱们传统的K-Means算法, “elkan”是咱们原理篇讲的elkan K-Means算法。默认的"auto"则会根据数据值是不是稀疏的,来决定如何选择"full"和“elkan”。通常数据是稠密的,那么就是 “elkan”,不然就是"full"。通常来讲建议直接用默认的"auto"优化

3、MiniBatchKMeans类主要参数

    MiniBatchKMeans类的主要参数比KMeans类稍多,主要有:

    1) n_clusters: 即咱们的k值,和KMeans类的n_clusters意义同样。

    2)max_iter:最大的迭代次数, 和KMeans类的max_iter意义同样。

    3)n_init:用不一样的初始化质心运行算法的次数。这里和KMeans类意义稍有不一样,KMeans类里的n_init是用一样的训练集数据来跑不一样的初始化质心从而运行算法。而MiniBatchKMeans类的n_init则是每次用不同的采样数据集来跑不一样的初始化质心运行算法。

****4)batch_size:即用来跑Mini Batch KMeans算法的采样集的大小,默认是100.若是发现数据集的类别较多或者噪音点较多,须要增长这个值以达到较好的聚类效果。

    5)init: 即初始值选择的方式,和KMeans类的init意义同样。

    6)init_size: 用来作质心初始值候选的样本个数,默认是batch_size的3倍,通常用默认值就能够了。

    7)reassignment_ratio: 某个类别质心被从新赋值的最大次数比例,这个和max_iter同样是为了控制算法运行时间的。这个比例是占样本总数的比例,乘以样本总数就获得了每一个类别质心能够从新赋值的次数。若是取值较高的话算法收敛时间可能会增长,尤为是那些暂时拥有样本数较少的质心。默认是0.01。若是数据量不是超大的话,好比1w如下,建议使用默认值。若是数据量超过1w,类别又比较多,可能须要适当减小这个比例值。具体要根据训练集来决定。

    8)max_no_improvement:即连续多少个Mini Batch没有改善聚类效果的话,就中止算法, 和reassignment_ratio,****max_iter同样是为了控制算法运行时间的。默认是10.通常用默认值就足够了。

4、K值的评估标准

    不像监督学习的分类问题和回归问题,咱们的无监督聚类没有样本输出,也就没有比较直接的聚类评估方法。可是咱们能够从簇内的稠密程度和簇间的离散程度来评估聚类的效果。常见的方法有轮廓系数Silhouette Coefficient和Calinski-Harabasz Index。我的比较喜欢Calinski-Harabasz Index,这个计算简单直接,获得的Calinski-Harabasz分数值\(s\)越大则聚类效果越好。

    Calinski-Harabasz分数值\(s\)的数学计算公式是:
\[ s(k) = \frac{tr(B_k)}{tr(W_k)} \frac{m-k}{k-1} \]

    其中m为训练集样本数,k为类别数。\(B_k\)为类别之间的协方差矩阵,\(W_k\)为类别内部数据的协方差矩阵。\(tr\)为矩阵的迹。

    也就是说,类别内部数据的协方差越小越好,类别之间的协方差越大越好,这样的Calinski-Harabasz分数会高。在scikit-learn中, Calinski-Harabasz Index对应的方法是metrics.calinski_harabaz_score.

5、5. K-Means应用实例

    下面用一个实例来说解用KMeans类和MiniBatchKMeans类来聚类。咱们观察在不一样的k值下Calinski-Harabasz分数。

    完整的代码参见个人github: https://github.com/nickchen121/machinelearning/blob/master/classic-machine-learning/kmeans_cluster.ipynb

    首先咱们随机建立一些二维数据做为训练集,选择二维特征数据,主要是方即可视化。代码以下:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets.samples_generator import make_blobs
# X为样本特征,Y为样本簇类别, 共1000个样本,每一个样本2个特征,共4个簇,簇中心在[-1,-1], [0,0],[1,1], [2,2], 簇方差分别为[0.4, 0.2, 0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.2, 0.2, 0.2], 
                  random_state =9)
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()

    从输出图能够咱们看看咱们建立的数据以下:

   如今咱们来用K-Means聚类方法来作聚类,首先选择k=2,代码以下:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=2, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

    k=2聚类的效果图输出以下:

    如今咱们来看看咱们用Calinski-Harabasz Index评估的聚类分数:

from sklearn import metrics
metrics.calinski_harabaz_score(X, y_pred)

    输出以下:

3116.1706763322227
    如今k=3来看看聚类效果,代码以下:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()  

    k=3的聚类的效果图输出以下:

    如今咱们来看看咱们用Calinski-Harabaz Index评估的k=3时候聚类分数:

metrics.calinski_harabaz_score(X, y_pred)

    输出以下:

2931.625030199556
    可见此时k=3的聚类分数比k=2还差。

    如今咱们看看k=4时候的聚类效果:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=4, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

    k=4的聚类的效果图输出以下:

    如今咱们来看看咱们用Calinski-Harabasz Index评估的k=4时候聚类分数:

metrics.calinski_harabaz_score(X, y_pred)

    输出以下:

5924.050613480169
    可见k=4的聚类分数比k=2和k=3都要高,这也符合咱们的预期,咱们的随机数据集也就是4个簇。当特征维度大于2,咱们没法直接可视化聚类效果来肉眼观察时,用Calinski-Harabaz Index评估是一个很实用的方法。

    如今咱们再看看用MiniBatchKMeans的效果,咱们将batch size设置为200. 因为咱们的4个簇都是凸的,因此其实batch size的值只要不是很是的小,对聚类的效果影响不大。

for index, k in enumerate((2,3,4,5)):
    plt.subplot(2,2,index+1)
    y_pred = MiniBatchKMeans(n_clusters=k, batch_size = 200, random_state=9).fit_predict(X)
    score= metrics.calinski_harabaz_score(X, y_pred)  
    plt.scatter(X[:, 0], X[:, 1], c=y_pred)
    plt.text(.99, .01, ('k=%d, score: %.2f' % (k,score)),
                 transform=plt.gca().transAxes, size=10,
                 horizontalalignment='right')
plt.show()

   对于k=2,3,4,5对应的输出图为:

    可见使用MiniBatchKMeans的聚类效果也不错,固然因为使用Mini Batch的缘由,一样是k=4最优,KMeans类的Calinski-Harabasz Index分数为5924.05,而MiniBatchKMeans的分数稍微低一些,为5921.45。这个差别损耗并不大。

 

(欢迎转载,转载请注明出处。欢迎沟通交流: 微信:nickchen121)

相关文章
相关标签/搜索