Python Scikit学习-K-均值-肘部-标准

Python Scikit学习-K-均值-肘部-标准,python,machine-learning,scikit-learn,cluster-analysis,k-means,Python,Machine Learning,Scikit Learn,Cluster Analysis,K Means,今天我想学习一些关于K-means的知识。我理解这个算法,我知道它是如何工作的。现在我正在寻找合适的k。。。我发现肘部标准是检测右k的一种方法,但我不知道如何将其与scikit learn一起使用?!在scikit学习中,我以这种方式对事物进行聚类 kmeans = KMeans(init='k-means++', n_clusters=n_clusters, n_init=10) kmeans.fit(data) 所以我应该对n_clusters=1…n这样做几次,并以错误率观察以获得正确

今天我想学习一些关于K-means的知识。我理解这个算法,我知道它是如何工作的。现在我正在寻找合适的k。。。我发现肘部标准是检测右k的一种方法,但我不知道如何将其与scikit learn一起使用?!在scikit学习中,我以这种方式对事物进行聚类

kmeans = KMeans(init='k-means++', n_clusters=n_clusters, n_init=10) 
kmeans.fit(data)

所以我应该对n_clusters=1…n这样做几次,并以错误率观察以获得正确的k吗?你认为这会很愚蠢而且会花很多时间吗

肘部标准是一种可视化方法。我还没有看到一个可靠的数学定义。 但k-means也是一种相当粗糙的启发式方法

因此,是的,您需要使用
k=1…kmax运行k-means,然后绘制结果SSQ并确定“最佳”k

存在k-均值的高级版本,如X-均值,它将以
k=2
开始,然后增加,直到次要标准(AIC/BIC)不再改善。对分k-均值是一种方法,也是从k=2开始,然后重复分割簇,直到k=kmax。您可能可以从中提取临时SSQ

不管怎样,我的印象是,在任何实际用例中,如果k-means非常好,那么您确实事先知道您需要的k。在这些情况下,k-means实际上不是一个“聚类”算法,而是一个算法。例如,将图像的颜色数减少到k。(通常您会选择k为32,因为这是5位颜色深度,可以以位压缩方式存储)。或者,例如,在视觉词汇袋中,您可以手动选择词汇大小。一个流行的值似乎是k=1000。然后,您就不太关心“簇”的质量,但主要的一点是能够将图像减少到1000维稀疏向量。 900维或1100维表示的性能不会有实质性差异


对于实际的聚类任务,即当您想要手动分析生成的聚类时,人们通常使用比k-means更高级的方法。K-means更像是一种数据简化技术。

如果事先不知道真实标签(如您的情况),则可以使用肘部标准或轮廓系数来评估
K-means聚类

弯头标准方法:

肘部法背后的思想是在给定数据集上对一系列k值(
num_clusters
,例如k=1到10)运行k均值聚类,并对每个k值计算平方误差之和(SSE)

然后,为每个k值绘制SSE的折线图。如果线条图看起来像一个手臂-在下面的线条图中是一个红色的圆圈(如角度),那么手臂上的“肘部”就是最佳k(簇数)的值。 这里,我们要最小化SSE。当我们增加k时,SSE趋向于向0减小(当k等于数据集中的数据点数量时,SSE为0,因为每个数据点都是自己的簇,并且它与其簇中心之间没有误差)

因此,我们的目标是选择一个仍然具有较低SSE的
小值k
,肘部通常表示我们通过增加k开始获得递减回报的位置

让我们考虑IRIS数据集,

import pandas as pd
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris['feature_names'])
#print(X)
data = X[['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)']]

sse = {}
for k in range(1, 10):
    kmeans = KMeans(n_clusters=k, max_iter=1000).fit(data)
    data["clusters"] = kmeans.labels_
    #print(data["clusters"])
    sse[k] = kmeans.inertia_ # Inertia: Sum of distances of samples to their closest cluster center
plt.figure()
plt.plot(list(sse.keys()), list(sse.values()))
plt.xlabel("Number of cluster")
plt.ylabel("SSE")
plt.show()
上述代码的绘图:

我们可以在图中看到,3是iris数据集的最佳聚类数(红色包围),这确实是正确的



轮廓系数法:

较高的轮廓系数分数与具有更好定义的簇的模型相关。轮廓系数为每个样本定义,由两个分数组成: `

a:样本与同一类别中所有其他点之间的平均距离

b:一个样本与下一个样本中所有其他点之间的平均距离 最近的集群

单个样本的轮廓系数如下所示:

现在,为了找到
KMeans
k
的最佳值,在
KMeans
中循环通过n个簇的1..n,并计算每个样本的轮廓系数

较高的轮廓系数表示对象与其自身簇匹配良好,而与相邻簇匹配较差

from sklearn.metrics import silhouette_score
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans

X = load_iris().data
y = load_iris().target
   
for n_cluster in range(2, 11):
    kmeans = KMeans(n_clusters=n_cluster).fit(X)
    label = kmeans.labels_
    sil_coeff = silhouette_score(X, label, metric='euclidean')
    print("For n_clusters={}, The Silhouette Coefficient is {}".format(n_cluster, sil_coeff))
输出-

对于n_簇=2,轮廓系数为0.680813620271
对于n_簇=3,轮廓系数为0.552591944521
对于n_簇=4,轮廓系数为0.496992849949
对于n_簇=5,轮廓系数为0.488517550854
对于n_簇=6,轮廓系数为0.370380309351
对于n_簇=7,轮廓系数为0.356303270516
对于n_簇=8,轮廓系数为0.365164535737
对于n_簇=9,轮廓系数为0.346583642095
对于n_簇=10,轮廓系数为0.328266088778

如我们所见,n_clusters=2具有最高的轮廓系数。这意味着2应该是集群的最佳数量,对吗

但问题是

Iris数据集有3种花,这与2种作为最佳聚类数的结果相矛盾。因此,尽管n-团簇=2具有最高的剪影系数,但是我们认为n-簇=3是由于-< /p>的最佳簇数。
  • 鸢尾属植物有3种(最重要)
  • n_clusters=2具有第二高的轮廓系数值
  • 因此,选择n_clusters=3是iris数据集的最佳聚类数

    选择最佳集群数量将取决于数据集的类型和我们试图解决的问题。但在大多数情况下,采用最高的轮廓系数将产生最佳的聚类数


    希望有帮助

    这个答案的灵感来自奥普拉卡什的著作。其中包含绘制SSE和轮廓Sc的代码
    range_n_clusters = [2, 3, 4, 5, 6,7,8]
    elbow = []
    ss = []
    for n_clusters in range_n_clusters:
       #iterating through cluster sizes
       clusterer = KMeans(n_clusters = n_clusters, random_state=42)
       cluster_labels = clusterer.fit_predict(df1)
       #Finding the average silhouette score
       silhouette_avg = silhouette_score(df1, cluster_labels)
       ss.append(silhouette_avg)
       print("For n_clusters =", n_clusters,"The average silhouette_score is :", silhouette_avg)`
       #Finding the average SSE"
       elbow.append(clusterer.inertia_) # Inertia: Sum of distances of samples to their closest cluster center
    fig = plt.figure(figsize=(14,7))
    fig.add_subplot(121)
    plt.plot(range_n_clusters, elbow,'b-',label='Sum of squared error')
    plt.xlabel("Number of cluster")
    plt.ylabel("SSE")
    plt.legend()
    fig.add_subplot(122)
    plt.plot(range_n_clusters, ss,'b-',label='Silhouette Score')
    plt.xlabel("Number of cluster")
    plt.ylabel("Silhouette Score")
    plt.legend()
    plt.show()