通过间隔统计和预测强度估计聚类数量

26

我正在尝试将gap统计和预测强度的R实现http://edchedch.wordpress.com/2011/03/19/counting-clusters/翻译为Python脚本,以估计3个群集的鸢尾花数据的数量。但是,每次运行时得到的结果都不同,估计出的群集数量与实际的3个相差很大。图表显示估计数量为10而不是3。我是否漏掉了什么?有人能帮我找出问题所在吗?

import random
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans


def dispersion (data, k):
    if k == 1:
        cluster_mean = np.mean(data, axis=0)
        distances_from_mean = np.sum((data - cluster_mean)**2,axis=1)
        dispersion_val = np.log(sum(distances_from_mean))
    else:
        k_means_model_ = KMeans(n_clusters=k, max_iter=50, n_init=5).fit(data)
        distances_from_mean = range(k)
        for i in range(k):
            distances_from_mean[i] = int()
            for idx, label in enumerate(k_means_model_.labels_):
                if i == label:
                    distances_from_mean[i] += sum((data[idx] - k_means_model_.cluster_centers_[i])**2)
        dispersion_val = np.log(sum(distances_from_mean))

    return dispersion_val

def reference_dispersion(data, num_clusters, num_reference_bootstraps):
    dispersions = [dispersion(generate_uniform_points(data), num_clusters) for i in range(num_reference_bootstraps)]
    mean_dispersion = np.mean(dispersions)
    stddev_dispersion = float(np.std(dispersions)) / np.sqrt(1. + 1. / num_reference_bootstraps) 
    return mean_dispersion

def generate_uniform_points(data):
    mins = np.argmin(data, axis=0)
    maxs = np.argmax(data, axis=0)

    num_dimensions = data.shape[1]
    num_datapoints = data.shape[0]

    reference_data_set = np.zeros((num_datapoints,num_dimensions))
    for i in range(num_datapoints):
        for j in range(num_dimensions):
            reference_data_set[i][j] = random.uniform(data[mins[j]][j],data[maxs[j]][j])

    return reference_data_set   

def gap_statistic (data, nthCluster, referenceDatasets):
    actual_dispersion = dispersion(data, nthCluster)
    ref_dispersion = reference_dispersion(data, nthCluster, num_reference_bootstraps)
    return actual_dispersion, ref_dispersion

if __name__ == "__main__":

    data=np.loadtxt('iris.mat', delimiter=',', dtype=float)

    maxClusters = 10
    num_reference_bootstraps = 10
    dispersion_values = np.zeros((maxClusters,2))

    for cluster in range(1, maxClusters+1):
        dispersion_values_actual,dispersion_values_reference = gap_statistic(data, cluster, num_reference_bootstraps)
        dispersion_values[cluster-1][0] = dispersion_values_actual
        dispersion_values[cluster-1][1] = dispersion_values_reference

    gaps = dispersion_values[:,1] - dispersion_values[:,0]

    print gaps
    print "The estimated number of clusters is ", range(maxClusters)[np.argmax(gaps)]+1

    plt.plot(range(len(gaps)), gaps)
    plt.show()

我甚至运行了我的数据的间隔统计r实现。当我增加最大聚类数时,估计的聚类数也会增加。 - Riyaz
1
你是怎么得到 0 个聚类的结果的??另外,不幸的是,鸢尾花数据是真实数据,很多这样的“研究”只有在合成数据集上才被验证过;所以我其实并不惊讶它不起作用。 - Has QUIT--Anony-Mousse
0只是一个数组索引,代表k=1。我已经翻译了预测强度。这在鸢尾花数据上得到了相当不错的结果。我猜r实现中有一些bug,我无法找出来。如何估计k取决于最大聚类数?当我尝试将最大聚类数设置为20时,它估计k=19。 - Riyaz
1
你可以参考这个链接:https://datasciencelab.wordpress.com/2013/12/27/finding-the-k-in-k-means-clustering/。另外,你的`stddev_dispersion`没有被使用到任何地方。 - Udayraj Deshmukh
1
你解决了吗?每次不同的预测结果都是由于random_state参数为None(这会导致使用np.random)。如果你想获得持久的结果,你应该像这样做:KMeans(n_clusters=k, max_iter=50, n_init=5, random_state=1234) - VnC
2个回答

1
您的图表显示了正确的值为3。让我解释一下。

enter image description here

  • 随着聚类数量的增加,距离度量肯定会减少。因此,您假设正确值为10。如果将其增加到10以上,则距离度量将进一步减少。但这不应该是我们的决策标准。
  • 我们需要找到拐点(在此处标记为红色)。这是斜率平滑的点。您可能想查看 弯曲图
  • 基于以上2点,拐点为3(也是正确的解决方案)

希望这有所帮助


0
你可以看一下这段代码,然后改变你的输出图表格式。
[![# coding: utf-8

# Implémentation de K-means clustering python


#Chargement des bibliothèques
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import datasets


#chargement de jeu des données Iris
iris = datasets.load_iris()

#importer le jeu de données Iris dataset à l'aide du module pandas
x = pd.DataFrame(iris.data)

x.columns = \['Sepal_Length','Sepal_width','Petal_Length','Petal_width'\]


y = pd.DataFrame(iris.target)


y.columns = \['Targets'\]


#Création d'un objet K-Means avec un regroupement en 3 clusters (groupes)
model=KMeans(n_clusters=3)



#application du modèle sur notre jeu de données Iris
model.fit(x)



#Visualisation des clusters
plt.scatter(x.Petal_Length, x.Petal_width)
plt.show()




colormap=np.array(\['Red','green','blue'\])



#Visualisation du jeu de données sans altération de ce dernier (affichage des fleurs selon leur étiquettes)
plt.scatter(x.Petal_Length, x.Petal_width,c=colormap\[y.Targets\],s=40)
plt.title('Classification réelle')
plt.show()

#Visualisation des clusters formés par K-Means
plt.scatter(x.Petal_Length, x.Petal_width,c=colormap\[model.labels_\],s=40)
plt.title('Classification K-means ')
plt.show()][1]][1]

输出 1 输出 2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接