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

时间:2013-03-21 16:29:45

标签: python cluster-analysis bioinformatics k-means variance

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

然而,我想根据它们的频率曲线的相似程度(最小的欧氏距离或类似的东西)来聚类这些样本。我已经将每个99x20阵列安排到一个1980x1阵列中,并将它们聚合成一个200x1980的观察阵列。

在找到群集之前,我尝试使用scipy.cluster.vq.whiten对数据进行白化。 whiten通过其方差对每列进行标准化,但由于我将数据数据平铺的方式,我有一些(8)列的所有零频率,因此方差为零。因此,白化的数组具有无限值,并且质心发现失败(或者提供~200个质心)。

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

  • 不要对数据进行白化。这导致k-means每次运行时都会给出不同的质心(有些预期),尽管iter关键字大大增加。
  • 在展平数据之前调换数组。零方差列只是移位。

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

编辑:我也尝试过使用我自己的白化功能

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

这似乎有效,但我不确定这是否会以任何方式偏向聚类。

由于

2 个答案:

答案 0 :(得分:3)

删除所有0的列不应该偏向数据。如果你有N维数据,但是一个维度都是相同的数字,它与具有N-1维数据完全相同。有效维度的这个属性称为rank

考虑三维数据,但所有数据点都在x = 0平面上。你能看到这与2D数据完全一样吗?

答案 1 :(得分:2)

首先,丢弃常量列非常好。显然他们没有提供信息,所以没有理由保留信息。

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

我建议您执行以下操作:

  1. 查找适用于您的域的相似性度量。花费大量时间在此,如何捕获特定用例的相似性。

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