scikit kmeans 不准确成本\惯性
scikit kmeans not accurate cost \ inertia
我想获得 k-means 成本(inertia
在 scikit kmeans 中)。
提醒一下:
成本是从每个点到最近的聚类的距离的平方和。
我在 scikit('inertia') 的成本计算之间发现了一个奇怪的差异,
以及我自己计算成本的简单方法
请看下面的例子:
p = np.random.rand(1000000,2)
from sklearn.cluster import KMeans
a = KMeans(n_clusters=3).fit(p)
print a.inertia_ , "****"
means = a.cluster_centers_
s = 0
for 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 += best
print 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 中使用 doubles。所以也许这只是一个数字问题?让我们测试您的代码,但现在,具有清晰的集群结构(因此没有可能分配给许多中心的点 - 取决于数值精度)。
import numpy as np
from sklearn.metrics import euclidean_distances
p = np.random.rand(1000000,2)
p[:p.shape[0]/2, :] += 100 #I move half of points far away
from sklearn.cluster import KMeans
a = KMeans(n_clusters=2).fit(p) #changed to two clusters
print a.inertia_ , "****"
means = a.cluster_centers_
s = 0
for x in p:
best = float("inf")
for y in means:
d = (x-y).T.dot(x-y)
if d < best:
best = d
s += best
print s, "*****"
结果
166805.190832 ****
166805.190946 *****
有道理。因此,问题在于样本 "near the boundary" 的存在,这些样本可能会根据算术精度分配给多个集群。不幸的是,我无法准确追踪差异的来源。
有趣的是实际上存在不一致,因为 inertia_
字段填充了Cython代码,.score
调用NumPy一个。因此,如果您调用
print -a.score(p)
你会得到完全你的惯性。
我想获得 k-means 成本(inertia
在 scikit kmeans 中)。
提醒一下:
成本是从每个点到最近的聚类的距离的平方和。
我在 scikit('inertia') 的成本计算之间发现了一个奇怪的差异,
以及我自己计算成本的简单方法
请看下面的例子:
p = np.random.rand(1000000,2)
from sklearn.cluster import KMeans
a = KMeans(n_clusters=3).fit(p)
print a.inertia_ , "****"
means = a.cluster_centers_
s = 0
for 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 += best
print s, "*****"
我的 运行 输出是:
66178.4232156 ****
66173.7928716 *****
在我自己的数据集上,结果更显着(20% 的差异)。
这是 scikit 实现中的错误吗?
首先 - 它似乎不是一个错误(但肯定是丑陋的不一致)。这是为什么?您需要仔细查看代码实际执行的操作。对于这个通用目的,它从 _k_means.pyx
(第 577-578 行)
inertia = _k_means._assign_labels_array(
X, x_squared_norms, centers, labels, distances=distances)
它所做的基本上就是您的代码,但是...在 C 中使用 doubles。所以也许这只是一个数字问题?让我们测试您的代码,但现在,具有清晰的集群结构(因此没有可能分配给许多中心的点 - 取决于数值精度)。
import numpy as np
from sklearn.metrics import euclidean_distances
p = np.random.rand(1000000,2)
p[:p.shape[0]/2, :] += 100 #I move half of points far away
from sklearn.cluster import KMeans
a = KMeans(n_clusters=2).fit(p) #changed to two clusters
print a.inertia_ , "****"
means = a.cluster_centers_
s = 0
for x in p:
best = float("inf")
for y in means:
d = (x-y).T.dot(x-y)
if d < best:
best = d
s += best
print s, "*****"
结果
166805.190832 ****
166805.190946 *****
有道理。因此,问题在于样本 "near the boundary" 的存在,这些样本可能会根据算术精度分配给多个集群。不幸的是,我无法准确追踪差异的来源。
有趣的是实际上存在不一致,因为 inertia_
字段填充了Cython代码,.score
调用NumPy一个。因此,如果您调用
print -a.score(p)
你会得到完全你的惯性。