Python - 使用 K-means 进行聚类。一些方差为零的列

Posted

技术标签:

【中文标题】Python - 使用 K-means 进行聚类。一些方差为零的列【英文标题】:Python - Clustering with K-means. Some columns with zero variance 【发布时间】:2013-03-11 06:54:46 【问题描述】:

我有一个由约 200 个 99x20 频率数组组成的数据集,每列总和为单位。我已经使用像 这样的热图绘制了这些图。每个数组都非常稀疏,每 99 个位置只有大约 1-7/20 个非零值。

但是,我想根据它们的频率分布的相似程度(最小欧几里德距离或类似的东西)对这些样本进行聚类。我将每个 99x20 阵列排列成一个 1980x1 阵列,并将它们聚合成一个 200x1980 观察阵列。

在找到集群之前,我尝试使用scipy.cluster.vq.whiten 对数据进行白化。 whiten 通过方差对每列进行归一化,但由于我展平数据数组的方式,我有一些 (8) 列的频率全为零,因此方差为零。因此,白化后的数组具有无限值,质心查找失败(或给出约 200 个质心)。

我的问题是,我应该如何解决这个问题?到目前为止,我已经尝试过

不要白化数据。这会导致 k-means 每次运行时都给出不同的质心(有点预期),尽管大大增加了 iter 关键字。 在展平阵列之前转置阵列。零方差列只是移动。

可以只删除其中一些零方差列吗?这会以任何方式偏向聚类吗?

编辑:我也尝试过使用我自己的 whiten 函数

for i in range(arr.shape[1]):
    if np.abs(arr[:,i].std()) < 1e-8: continue
    arr[:,i] /= arr[:,i].std()

这似乎可行,但我不确定这是否会以任何方式偏向集群。

谢谢

【问题讨论】:

作为次要编码点,在检查 0.0 浮点值时不要使用相等检查。 if arr[:,i].std() == 0 应该是 if abs(arr[:,i].std()) &lt; epsilon,其中 epsilon 是一个非常小的值,例如 0.0000001。否则,您可能会得到舍入错误,导致 0 值浮点数显示为非零。对于给定的问题,它可能总是可以正常工作,但总的来说,上述方法是进行浮动“平等”检查的更好方法。 @Pyrce 谢谢,已编辑。 【参考方案1】:

删除所有 0 的列不应使数据产生偏差。如果你有 N 维数据,但一维都是同一个数,这与拥有 N-1 维数据完全一样。这种有效维数的属性称为rank。

考虑 3-D 数据,但您的所有数据点都在 x=0 平面上。你能看出这与二维数据完全相同吗?

【讨论】:

那么你会考虑我已经做了一个有效的解决方案吗? 我不确定,但您可能需要将 if 更改为: if all(np.abs(arr[:,i].std()) arr[:,i].std() 返回一个浮点数,所以我认为没有必要。【参考方案2】:

首先,删除常量列是非常好的。显然他们不提供信息,所以没有理由保留它们。

然而,K-means 对于稀疏向量并不是特别好。问题在于,生成的“质心”很可能与集群成员之间的彼此更相似。 看,在稀疏数据中,每个对象在某种程度上都是一个异常值。而且 K-means 对异常值非常敏感,因为它试图最小化 平方和

我建议您执行以下操作:

    找到一个适用于您的域的相似性度量。在如何为您的特定用例捕获相似性方面花费大量时间。

    一旦你有了相似度,计算 200x200 的相似度矩阵。由于您的数据集非常小,您实际上可以运行昂贵的聚类方法,例如层次聚类,这些方法无法扩展到数千个对象。如果需要,您还可以尝试 OPTICS 集群或 DBSCAN。但特别是如果您的数据集更大,DBSCAN 实际上会更有趣。对于微小的数据集,层次聚类很好。

【讨论】:

以上是关于Python - 使用 K-means 进行聚类。一些方差为零的列的主要内容,如果未能解决你的问题,请参考以下文章

k-means聚类分析 python 代码实现(不使用现成聚类库)

k-means聚类分析 python 代码实现(不使用现成聚类库)

Python - 使用 K-means 进行聚类。一些方差为零的列

python 使用Scipy k-means进行聚类,使用简单的欧几里德距离

如何在 Python 中使用 K-Means 聚类找到最佳的聚类数量

OpenCV-Python实战(番外篇)——利用 K-Means 聚类进行色彩量化