基于它们在python中的合并顺序的层次聚类标签

Posted

技术标签:

【中文标题】基于它们在python中的合并顺序的层次聚类标签【英文标题】:Hierarchical clustering label based on their merging order in python 【发布时间】:2021-10-26 20:14:52 【问题描述】:

可以说,我有这种类型的层次聚类,如下图所示。要获得聚类标签,我需要定义适当的阈值距离。例如,如果我将阈值设置为 0.32,我可能会得到 3 个集群,如果我设置为 3.5 左右,我会从下图中得到 2 个集群。

我想根据它们的合并顺序获取聚类标签,而不是使用阈值并使用一些固定距离。

我想根据它们的合并来定义聚类;比如第一次合并,第二次合并等等。

例如,在这里我想获得聚类标签,当它们至少第一次合并时,那将是 3 个聚类;

cluster1: p1
cluster2: p3 and p4
cluster3: p2 and p5.

如果我在这里设置,则在至少发生第二次合并时找到聚类。 在这种情况下,我将有 2 个集群,例如:

cluster1: p1
cluster2 = p3, p4, p2 and p5.

scipy 是否有内置方法来提取此类信息。如果没有,有什么方法可以从hierarchical clustering 中提取此类信息?任何建议都会很棒。

示例:

这个想法是,我不想硬编码任何阈值限制来定义集群的数量,而是根据它们的合并顺序找到集群。例如,如果存在 p1、p2 和 p3,并且在一种情况下,p1 和 p2 在 0.32 处属于同一个簇,另一种情况下,为 p1、p2 和 p3 添加更多数据,现在它们可能属于同一个簇,但距离为它们的集群的合并可能已经改变。这样,p1 和 p2 仍然在同一个集群中。所以,这里定义聚类的距离阈值是无关紧要的

【问题讨论】:

你需要使用'scipy'吗? @wundermahn 不,我不必使用 scipy。如果他们有这个功能,我也可以使用其他库 【参考方案1】:

scipy.cluster.hierarchy 函数产生的链接矩阵有一个额外的字段,用于表示新形成的集群中的观察数:

scipy.cluster.hierarchy.linkage:返回一个 (n−1) × 4 矩阵 Z。在第 i 次迭代中,索引为 Z[i, 0]Z[i, 1] 的簇被组合成簇 n+i。索引小于 n 的集群对应于 n 个原始观测值之一。集群Z[i, 0]Z[i, 1] 之间的距离由Z[i, 2] 给出。第四个值Z[i, 3]表示新形成的聚类中原始观测值的数量。

我不确定我是否完全遵循您的示例[1],但是您可以使用集群大小来定义切割的深度,从而生成您的集群的平面列表,以得到一些东西线。例如,逻辑可以是“在集群大小仍为 2 或更少的最后一次合并处停止”(给出 3 个集群的第一个列表)或“当集群大小为 3 或更大时在第一次合并处停止”(给出您的第二个 2 个集群列表)。

这是一个数据集示例,它提供与图中所示相似的层次聚类,显示与您的两个示例匹配的结果:

import numpy as np
from scipy.cluster.hierarchy import single, fcluster
from scipy.spatial.distance import pdist

X = [
    (0, 0, .45), # P1
    (0, .36, 0), # P2
    (0, 0, 0), # P3
    (.3, 0, 0), # P4
    (.31, .36, 0), # P5
]

Z = single(pdist(X))

i1 = np.argwhere(Z[:,3] <= 2)[-1,0]        # => i1 = 1
d1 = Z[i1, 2]                              # => d = 0.31
c1 = fcluster(Z, d1, criterion='distance') # => c1 = [3, 2, 1, 1, 2]
# i.e., three clusters: P3, P4, P2, P5 and P1

i2 = np.argwhere(Z[:,3] >= 3)[0,0]         # => i2 = 2
d2 = Z[i2, 2]                              # => d2 = 0.36
c2 = fcluster(Z, d2, criterion='distance') # => c2 = [2, 1, 1, 1, 1]
# i.e., two clusters: P2, P3, P4, P5 and P1

[1] 当 P3 和 P4 合并时,“至少第一次合并”会不会立即出现,留下 4 个集群?并且没有理由期望“第二次合并”总是将两对合并:它也可以将单个观察与一对合并。这就是为什么我建议使用集群大小而不是“N 次合并”。

【讨论】:

感谢您的回答,我必须更仔细地检查此解决方案。这个想法是,我不想硬编码任何阈值限制来定义集群的数量,而是根据它们的合并顺序找到集群。例如,如果存在 p1、p2 和 p3,并且在一种情况下,p1 和 p2 在 0.32 处属于同一个簇,另一种情况下,为 p1、p2 和 p3 添加更多数据,现在它们可能属于同一个簇,但距离为它们的集群的合并可能已经改变。这样,p1 和 p2 仍然在同一个集群中。所以,这里定义聚类的距离阈值是无关紧要的 我这里没有按照你的例子。当您说“为 p1、p2 和 p3 添加更多数据”时,您是什么意思?你的意思是更多的观察或更多的变量?在这两种情况下,为什么您希望 p1 和 p2 在获得更多数据后保持在同一个集群中?总是可以通过选择足够大的距离来强制任何一组点在同一个簇中,但这不一定有用。 我不认为“基于它们的合并顺序”是明确的。但是这个答案中的例子没有硬编码距离或集群数量的阈值。相反,它基于在(在合并过程中)新创建的集群首先达到一定大小(就其中的观察数量而言)时停止。通过了解链接矩阵的结构(按顺序列出合并步骤的顺序),您应该能够实现您可以明确定义的任何其他展平条件。 @Ryan 如果有新数据出现并定义了新集群,我不想每次都检查树状图并查看它们是否仍然是相同的集群,然后确定距离的阈值。 thershold 的距离无关紧要,但主要目标是发现它们仍然是同一簇的一部分,而无需每次都检查树状图。

以上是关于基于它们在python中的合并顺序的层次聚类标签的主要内容,如果未能解决你的问题,请参考以下文章

聚类:层次聚类基于划分的聚类(k-means)基于密度的聚类基于模型的聚类

层次聚类

层次聚类及scipy中的层次聚类python代码解释

层次聚类算法的原理及实现Hierarchical Clustering

Python中的层次聚类,详细讲解

Python机器学习——Agglomerative层次聚类