scikit kmeans的成本/惯性不准确

我想获取k-means的成本(在scikit kmeans中称为inertia)。提醒一下:

成本是每个点到最近的聚类中心的平方距离之和。

我在scikit的成本计算(’inertia’)和自己简单计算成本的方法之间发现了一个奇怪的差异

请看以下示例:

p = np.random.rand(1000000,2)from sklearn.cluster import KMeansa = KMeans(n_clusters=3).fit(p)print a.inertia_ , "****"means = a.cluster_centers_s = 0for x in p:    best = float("inf")    for y in means:        if np.linalg.norm(x-y)**2 < best:            best = np.linalg.norm(x-y)**2    s += bestprint s, "*****"

在我的运行中,输出结果是:

66178.4232156 ****66173.7928716 *****

在我的数据集上,结果差异更大(20%的差异)。
这是scikit实现中的一个错误吗?


回答:

首先 – 这似乎不是一个错误(但确实存在明显的不一致性)。为什么会这样呢?你需要仔细查看代码实际在做什么。对于这个通用目的,它调用了_k_means.pyx中的cython代码

(第577-578行)

    inertia = _k_means._assign_labels_array(        X, x_squared_norms, centers, labels, distances=distances)

它所做的基本上与你的代码相同,但是…在C语言中使用了双精度浮点数。所以这可能只是一个数值问题吗?让我们测试你的代码,但这次使用清晰的聚类结构(因此没有可能被分配到多个中心的点 – 这取决于数值精度)。

import numpy as npfrom sklearn.metrics import euclidean_distancesp = np.random.rand(1000000,2)p[:p.shape[0]/2, :] += 100 #我将一半的点移到很远的地方from sklearn.cluster import KMeansa = KMeans(n_clusters=2).fit(p) #改为两个聚类print a.inertia_ , "****"means = a.cluster_centers_s = 0for x in p:    best = float("inf")    for y in means:        d = (x-y).T.dot(x-y)        if d < best:            best = d    s += bestprint s, "*****"

结果

166805.190832 ****166805.190946 *****

这是有道理的。因此问题在于存在“接近边界”的样本,这些样本可能会根据算术精度被分配到多个聚类中。不幸的是,我无法准确追踪差异的来源。

有趣的是,实际上存在一个不一致性,因为inertia_字段是由Cython代码填充的,而.score调用的是NumPy的代码。因此如果你调用

print -a.score(p)

你将得到你的惯性值。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注