聚类算法--K值估计及效果评估

上周实习工作中用到了聚类分析的相关内容,故又对聚类分析算法重温一遍,中间发现我前面所写博客有两个比较关键的步骤是缺失的:

  • 利用肘部法则估计参数数目

  • 利用轮廓系数评估聚类算法的优劣

Python有现成的轮子,只需更改传入的数据集即可
由于我所有的数据、代码及结果均在公司所配电脑上,所以以下仅附上Python的实现。

本文参考博客:http://blog.csdn.net/u013719780/article/details/51755124

成本(目标)函数

其实在博文http://blog.csdn.net/buracag_mc/article/details/74139768中已经提到过,我们要寻找的聚类是使得类内离差平方和最小下的类,即:
argminki=1(xSi(|xui|2))

我们这里使用的说法是类内离差平方和最小,典型的统计学上的说法,一看就是学统计=_=;

其实也就是数据挖掘与统计机器学习中常说的成本(目标)函数,最小化类内离差平方和即是最小化成本函数。

使用肘部法则估计聚类数目

如果问题中没有指定聚类数目K的值,可以通过肘部法则这一技术来估计聚类数量。

肘部法则会把不同K值的成本函数值画出来。随着K值的增大,平均畸变程度会减小;每个类包含的样本数会减少,于是样本离其重心会更近。但是,随着K值继续增大,平均畸变程度的改善效果会不断减低。K值增大过程中,畸变程度的改善效果下降幅度最大的位置对应的K值就是肘部。

其中需要解释的一点是:
每个类的畸变程度等于该类重心与其内部成员位置距离的平方和。也即我们前面所说的每个类的类内离差平方和。若类内部的成员彼此间越紧凑则类的畸变程度越小,反之,若类内部的成员彼此间越分散则类的畸变程度越大。

当然Python已经有了现成的轮子可以用了,关键命令如下:

# coding:utf-8

from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist  # 计算距离时
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
# 正常显示中文字体
font = FontProperties(fname=r"c:\windows\fonts\msyh.ttc", size=10) 

K = range(1, 10)
meandistortions = []

for k in K:
    kmeans = KMeans(n_clusters=k)
    kmeans.fit(X)
    meandistortions.append(sum(np.min(cdist(X, kmeans.cluster_centers_, 'euclidean'), axis=1)) / X.shape[0])

plt.plot(K, meandistortions, 'bx-')
plt.xlabel('k')
plt.ylabel(u'平均畸变程度',fontproperties=font)
plt.title(u'用肘部法则来确定最佳的K值',fontproperties=font);
plt.show()

最后效果图大致形如:
《聚类算法--K值估计及效果评估》

聚类效果评估

K-Means是一种典型的非监督学习,没有标签和其他信息来比较聚类结果。但是,我们还是有一些指标可以评估算法的性能。

====下面是百度百科的解释====
轮廓系数(Silhouette Coefficient),是聚类效果好坏的一种评价方式。最早由 Peter J. Rousseeuw 在 1986 提出。它结合内聚度和分离度两种因素。可以用来在相同原始数据的基础上用来评价不同算法、或者算法不同运行方式对聚类结果所产生的影响。

假设我们已经通过聚类算法将待分类数据进行了聚类,分为了 k 个簇 。对于簇中的每个向量。分别计算它们的轮廓系数。
对于其中的一个点 i 来说:

  • 计算 a(i) = average(i向量到所有它属于的簇中其它点的距离)

  • 计算 b(i) = min (i向量到所有非本身所在簇的点的平均距离)
    那么 i 向量轮廓系数就为:
    S(i)=b(i)a(i)max{a(i),b(i)}

这里,再附上百度百科的图片,直观形象:
《聚类算法--K值估计及效果评估》

可见轮廓系数的值是介于 [-1,1] ,越趋近于1代表内聚度和分离度都相对较优。

最后将所有样本点的轮廓系数求平均,就是该聚类结果总的轮廓系数。

同样,Python已经有了现成的轮子可用,关键命令如下

import numpy as np
from sklearn.cluster import KMeans
from sklearn import metrics

X = np.array()       # X为待聚类的数据集
kmeans_model=KMeans(n_clusters=k).fit(X)  # K-Means聚类,聚类数为k

s = metrics.silhouette_score(X,kmeans_model.labels_,metric='euclidean') # 轮廓系数得分

这里我再给出metrics.silhouette_score的帮助文档:

Compute the mean Silhouette Coefficient of all samples.

The Silhouette Coefficient is calculated using the mean intra-cluster
distance (``a``) and the mean nearest-cluster distance (``b``) for each
sample.  The Silhouette Coefficient for a sample is ``(b - a) / max(a,
b)``.  To clarify, ``b`` is the distance between a sample and the nearest
cluster that the sample is not a part of.
Note that Silhouette Coefficent is only defined if number of labels
is 2 <= n_labels <= n_samples - 1.

This function returns the mean Silhouette Coefficient over all samples.
To obtain the values for each sample, use :func:`silhouette_samples`.

The best value is 1 and the worst value is -1. Values near 0 indicate
overlapping clusters. Negative values generally indicate that a sample has
been assigned to the wrong cluster, as a different cluster is more similar.

Parameters
----------
X : array [n_samples_a, n_samples_a] if metric == "precomputed", or, \
         [n_samples_a, n_features] otherwise
    Array of pairwise distances between samples, or a feature array.

labels : array, shape = [n_samples]
     Predicted labels for each sample.

metric : string, or callable
    The metric to use when calculating distance between instances in a
    feature array. If metric is a string, it must be one of the options
    allowed by :func:`metrics.pairwise.pairwise_distances
    <sklearn.metrics.pairwise.pairwise_distances>`. If X is the distance
    array itself, use ``metric="precomputed"``.

sample_size : int or None
    The size of the sample to use when computing the Silhouette Coefficient
    on a random subset of the data.
    If ``sample_size is None``, no sampling is used.

random_state : integer or numpy.RandomState, optional
    The generator used to randomly select a subset of samples if
    ``sample_size is not None``. If an integer is given, it fixes the seed.
    Defaults to the global numpy random number generator.

`**kwds` : optional keyword parameters
    Any further parameters are passed directly to the distance function.
    If using a scipy.spatial.distance metric, the parameters are still
    metric dependent. See the scipy docs for usage examples.

Returns
-------
silhouette : float
    Mean Silhouette Coefficient for all samples.

大概解读一下,metrics.silhouette_score函数的功能及参数情况:

 计算所有样本的平均轮廓系数。

 使用前面我们说的公式计算平均集群计算轮阔系数

 另外请注意,Silhouette Coefficent仅在标签数量上被定义
 是2 <= n_labels <= n_samples - 1。

 该函数返回所有样本的平均轮廓系数。
 要获取每个样本的值,请使用:func:`silhouette_samples`。

 最佳值为1,最差值为-1。 0附近的值表示聚类群可能会有重叠,负值通常表示样品具有被分配到错误的群集的概率,因为不同的群集更相似。


 参数情况
 -------
 X:样本之间的特征数组或成对距离数组

 labels:每个样本的预测标签

 metric:string表示采用的度量距离的方式; 如果X是距离数组本身,使用metric ="precomputed"。

 sample_size:int或None
 如果为int,则在数据的随机子集上计算轮廓系数时要使用的样本的大小;如果为None,则不使用抽样。

 random_state:integer或numpy.RandomState,可选;用于随机选择样本子集的生成器。默认为全局numpy随机数生成器。


 Returns
 -------
 所有样本的轮廓系数均值

所以啊,文档很重要啊!!!文档很重要啊!!!很重要啊!!!

    原文作者:聚类算法
    原文地址: https://blog.csdn.net/buracag_mc/article/details/75727895
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞