用于分层聚类Python的三角形与方形距离矩阵?

时间:2016-04-09 17:04:31

标签: python numpy machine-learning scipy hierarchical-clustering

我一直在尝试使用Hierarchical Clustering,而R就这么简单hclust(as.dist(X),method="average")。我在Python中找到了一个非常简单的方法,除了我对输入距离矩阵的进展感到有些困惑。

我有一个相似度矩阵(DF_c93tom w /较小的测试版本DF_sim),我将其转换为相异矩阵DF_dissm = 1 - DF_sim

我将此作为来自linkage的{​​{1}}的输入,但文档说明它采用方形或三角形矩阵。我输入了一个不同的群集来输入scipylower triangleupper triangle。为什么是这样?它需要文档中的上三角形,但下三角形簇看起来非常相似。

我的问题是,为什么所有群集都不同?哪一个是正确的?

这是square matrix

的输入距离矩阵的文档
linkage

这是我的代码:

y : ndarray
A condensed or redundant distance matrix. A condensed distance matrix is a flat array containing the upper triangular of the distance matrix. 

enter image description here

1 个答案:

答案 0 :(得分:5)

当一个2D数组作为第一个参数传递给scipy.cluster.hierarchy.linkage时, 它被视为一系列观察,并scipy.spatial.pdist is used将其转换为观察之间成对距离的序列。

有关此行为的github issue,因为这意味着传递“距离矩阵”(例如DF_dissm.values(静默)会产生错误结果

所以the upshot of this就是没有这些

Z_square = linkage((DF_dissm.values),method="average")
Z_triu = linkage(np.triu(DF_dissm.values),method="average")
Z_tril = linkage(np.tril(DF_dissm.values),method="average")

产生所需的结果。 改为使用

  • np.triu_indices

    h, w = arr.shape
    Z = linkage(arr[np.triu_indices(h, 1)], method="average")
    
  • spatial.distance.squareform

    from scipy.spatial import distance as ssd
    Z = linkage(ssd.squareform(arr), method="average")
    
  • 或将spatial.distance.pdist应用于原始点:

    Z = hierarchy.linkage(ssd.pdist(points), method="average")
    
  • 或传递2D数组points

    Z = hierarchy.linkage(points, method="average")
    
import matplotlib.pyplot as plt
import numpy as np
from scipy.cluster import hierarchy as hier
from scipy.spatial import distance as ssd
np.random.seed(2016)

points = np.random.random((10, 2))
arr = ssd.cdist(points, points)

fig, ax = plt.subplots(nrows=4)

ax[0].set_title("condensed upper triangular")
Z = hier.linkage(arr[np.triu_indices(arr.shape[0], 1)], method="average")
hier.dendrogram(Z, ax=ax[0])

ax[1].set_title("squareform")
Z = hier.linkage(ssd.squareform(arr), method="average")
hier.dendrogram(Z, ax=ax[1])

ax[2].set_title("pdist")
Z = hier.linkage(ssd.pdist(points), method="average")
hier.dendrogram(Z, ax=ax[2])

ax[3].set_title("sequence of observations")
Z = hier.linkage(points, method="average")
hier.dendrogram(Z, ax=ax[3])

plt.show()

enter image description here