如何解读SciPy层次聚类树状图的输出?(可能发现了bug…)

我在尝试弄明白scipy.cluster.hierarchy.dendrogram的输出是如何工作的…我原本以为我已经明白了它的工作原理,并且能够利用输出重建树状图,但现在似乎我不再理解它了,或者是Python 3版本的这个模块中存在bug。

这个回答,如何获取由scipy.cluster.hierarchy生成的树状图的子树,暗示dendrogram输出的字典提供了dict_keys(['icoord', 'ivl', 'color_list', 'leaves', 'dcoord']),这些键的值大小相同,因此你可以使用zip函数将它们组合,并用plt.plot重建树状图。

这看起来很简单,实际上我在使用Python 2.7.11时确实成功了,但是一旦我升级到Python 3.5.1,我的旧脚本就不再产生相同的结果了。

我开始重新调整我的聚类,以便创建一个非常简单的可重复示例,我认为我可能在Python 3.5.1SciPy版本0.17.1-np110py35_1中发现了一个bug。将使用Scikit-learn的数据集,因为大多数人从conda分发中拥有这个模块。

为什么这些数据无法对齐?为什么我无法用这种方式重建树状图?

# Initimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as sns; sns.set()# Load datafrom sklearn.datasets import load_diabetes# Clusteringfrom scipy.cluster.hierarchy import dendrogram, fcluster, leaves_listfrom scipy.spatial import distancefrom fastcluster import linkage # You can use SciPy one too%matplotlib inline# DatasetA_data = load_diabetes().dataDF_diabetes = pd.DataFrame(A_data, columns = ["attr_%d" % j for j in range(A_data.shape[1])])# Absolute value of correlation matrix, then subtract from 1 for disimilarityDF_dism = 1 - np.abs(DF_diabetes.corr())# Compute average linkageA_dist = distance.squareform(DF_dism.as_matrix())Z = linkage(A_dist,method="average")# I modded the SO code from the above answer for the plot functiondef plot_tree( D_dendro, ax ):    # Set up plotting data    leaves = D_dendro["ivl"]    icoord = np.array( D_dendro['icoord'] )    dcoord = np.array( D_dendro['dcoord'] )    color_list = D_dendro["color_list"]    # Plot colors    for leaf, xs, ys, color in zip(leaves, icoord, dcoord, color_list):        print(leaf, xs, ys, color, sep="\t")        plt.plot(xs, ys,  color)    # Set min/max of plots    xmin, xmax = icoord.min(), icoord.max()    ymin, ymax = dcoord.min(), dcoord.max()    plt.xlim( xmin-10, xmax + 0.1*abs(xmax) )    plt.ylim( ymin, ymax + 0.1*abs(ymax) )    # Set up ticks    ax.set_xticks( np.arange(5, len(leaves) * 10 + 5, 10))    ax.set_xticklabels(leaves, fontsize=10, rotation=45)    plt.show()fig, ax = plt.subplots()D1 = dendrogram(Z=Z, labels=DF_dism.index, color_threshold=None, no_plot=True)plot_tree(D_dendro=D1, ax=ax)

enter image description here

attr_1  [ 15.  15.  25.  25.]   [ 0.          0.10333704  0.10333704  0.        ]   gattr_4  [ 55.  55.  65.  65.]   [ 0.          0.26150727  0.26150727  0.        ]   rattr_5  [ 45.  45.  60.  60.]   [ 0.          0.4917828   0.4917828   0.26150727]   rattr_2  [ 35.   35.   52.5  52.5]   [ 0.          0.59107459  0.59107459  0.4917828 ]   battr_8  [ 20.    20.    43.75  43.75]   [ 0.10333704  0.65064998  0.65064998  0.59107459]   battr_6  [ 85.  85.  95.  95.]   [ 0.          0.60957062  0.60957062  0.        ]   battr_7  [ 75.  75.  90.  90.]   [ 0.          0.68142114  0.68142114  0.60957062]   battr_0  [ 31.875  31.875  82.5    82.5  ]   [ 0.65064998  0.72066112  0.72066112  0.68142114]   battr_3  [  5.       5.      57.1875  57.1875]   [ 0.          0.80554653  0.80554653  0.72066112]   b

这里有一个没有标签的例子,只显示x轴的icoordenter image description here

所以请注意颜色映射不正确。它说[ 15. 15. 25. 25.]icoord对应attr_1,但根据数值来看,它似乎对应attr_4。此外,它没有一直延伸到最后一个叶子节点(attr_9),这是因为icoorddcoord的长度比ivl标签的数量少1。

print([len(x) for x in [leaves, icoord, dcoord, color_list]]) #[10, 9, 9, 9]

回答:

icoorddcoordcolor_list描述的是连接,而不是叶子节点。icoorddcoord给出每个连接在图表中的“拱形”(即倒U形或J形)的坐标,而color_list则是这些拱形的颜色。在完整的图表中,icoord等的长度会比ivl的长度少1,正如你所观察到的那样。

不要试图将ivl列表与icoorddcoordcolor_list列表对齐。它们关联的是不同的东西。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注