我有五点,我需要从这些点创建树状图。函数'dendrogram'可用于查找这些点的顺序,如下所示。但是,我不想使用树形图,因为它很慢并导致大量点的错误(我在这里问了这个问题Python alternate way to find dendrogram)。有人能指出我如何将'连锁'输出(Z)转换为“树状图(Z)['ivl']”值。
>>> from hcluster import pdist, linkage, dendrogram
>>> import numpy
>>> from numpy.random import rand
>>> x = rand(5,3)
>>> Y = pdist(x)
>>> Z = linkage(Y)
>>> Z
array([[ 1. , 3. , 0.11443378, 2. ],
[ 0. , 4. , 0.47941843, 2. ],
[ 5. , 6. , 0.67596472, 4. ],
[ 2. , 7. , 0.79993986, 5. ]])
>>>
>>> dendrogram(Z)['ivl']
['2', '1', '3', '0', '4']
>>>
答案 0 :(得分:4)
有一个专用函数用于计算scipy中的线性化叶子顺序。这里是。 scipy.cluster.hierarchy.leaves_list
答案 1 :(得分:2)
为什么慢?当然,计算链接聚类的天真方式是O(n^3)
,但对于n=5
来说,它的价格便宜......
对于scipy连接矩阵的格式,请参阅以下问题: scipy linkage format
请注意,您可能仍需要以最佳方式对数据进行排序。上面编码的链接矩阵给出了
但它可能是通过链接距离来排序的,而不是用于可视化的1d排序(因为使用链接聚类的任何人都不希望之后运行树状图viusalization)。但无论如何,如果你需要排序,那么计算树形图应该是O(n log n)
的量级,与实际的聚类相比相当便宜。
这些方面的东西应该可以解决问题:
n = len(Z) + 1
cache = dict()
for k in range(len(Z)):
c1, c2 = int(Z[k][0]), int(Z[k][1])
c1 = [c1] if c1 < n else cache.pop(c1)
c2 = [c2] if c2 < n else cache.pop(c2)
cache[n+k] = c1 + c2
print cache[2*len(Z)]
这似乎是线性的,但数组的预期大小为log n
,因此根据您的列表类型,它可能仍然是O(n log n)
,而对于链接列表,它确实可以在O(n)
。
但最后,您可能希望避免分层聚类。它是聚类分析的一个流行的介绍性示例,因为它在概念上很容易理解。有一些非常棘手的算法(SLINK)可以将其降低到O(n^2)
复杂度。但是有更多现代和强大的聚类算法具有较低的复杂性。实际上,OPTICS (Wikipedia)计算的东西非常相似(当你设置minPts = 2时),当你有一个好的索引结构时,它将在O(n log n)
中运行。另外,您可以增加minPts以获得更有意义的集群。 (但是不要在Weka中使用OPTICS,或者那些漂浮在周围的python版本 - 假设它们都是不完整或有缺陷的!)