层次聚类Python中的三角形与正方形距离矩阵?

4

我一直在尝试使用“层次聚类”并且在R中非常简单,只需使用“hclust(as.dist(X),method="average")”。我在Python中找到了一个相当简单的方法,但是对于我的输入距离矩阵发生了一些混淆。

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

我将其用作scipy中linkage的输入,但文档说它接受一个正方形或三角形矩阵。我通过输入下三角、上三角和正方形矩阵获得了不同的聚类结果。为什么会这样?文档要求一个上三角,但下三角聚类看起来非常相似。

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

这是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. 

这是我的代码:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
from scipy.cluster.hierarchy import dendrogram, linkage

%matplotlib inline

#Test Data
DF_sim = DF_c93tom.iloc[:10,:10] #Similarity Matrix
DF_sim.columns = DF_sim.index = range(10) 
#print(DF_test)
#           0  1         2         3  4  5  6  7  8  9
# 0  1.000000  0  0.395833  0.083333  0  0  0  0  0  0
# 1  0.000000  1  0.000000  0.000000  0  0  0  0  0  0
# 2  0.395833  0  1.000000  0.883792  0  0  0  0  0  0
# 3  0.083333  0  0.883792  1.000000  0  0  0  0  0  0
# 4  0.000000  0  0.000000  0.000000  1  0  0  0  0  0
# 5  0.000000  0  0.000000  0.000000  0  1  0  0  0  0
# 6  0.000000  0  0.000000  0.000000  0  0  1  0  0  0
# 7  0.000000  0  0.000000  0.000000  0  0  0  1  0  0
# 8  0.000000  0  0.000000  0.000000  0  0  0  0  1  0
# 9  0.000000  0  0.000000  0.000000  0  0  0  0  0  1

#Dissimilarity Matrix
DF_dissm = 1 - DF_sim

#Redundant Matrix
#np.tril(DF_dissm).T == np.triu(DF_dissm)
#True for all values

#Hierarchical Clustering for square and triangle matrices
fig_1 = plt.figure(1)
plt.title("Square")
Z_square = linkage((DF_dissm.values),method="average")
dendrogram(Z_square)

fig_2 = plt.figure(2)
plt.title("Triangle Upper")
Z_triu = linkage(np.triu(DF_dissm.values),method="average")
dendrogram(Z_triu)

fig_3 = plt.figure(3)
plt.title("Triangle Lower")
Z_tril = linkage(np.tril(DF_dissm.values),method="average")
dendrogram(Z_tril)

plt.show()

enter image description here

1个回答

8
当一个二维数组作为第一个参数传递给scipy.cluster.hierarchy.linkage时,它被视为一系列观测值,并使用scipy.spatial.pdist将其转换为观测值之间的成对距离序列。
关于这种行为有一个github问题,因为这意味着传递“距离矩阵”(如DF_dissm.values)会(悄悄地)产生错误结果。
因此,这意味着这些中没有任何一个。
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")
    
  • or spatial.distance.squareform:

    from scipy.spatial import distance as ssd
    Z = linkage(ssd.squareform(arr), method="average")
    
  • or apply spatial.distance.pdist to the original points:

    Z = hierarchy.linkage(ssd.pdist(points), method="average")
    
  • or pass the 2D array 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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接