sklearn AgglomerativeClustering 中的关键字参数“connectivity”无法按预期工作

问题描述 投票:0回答:1

在我的 Python 代码中,我想根据给定的距离矩阵对一组对象进行聚类。然而,有些对象永远不应该出现在同一个簇中。选择簇的数量以便问题是可解决的。我想使用 sklearn 库中的 AgglomerativeClustering 类。我将不兼容对象的距离设置为 1,这在某些情况下并不能阻止它们最终出现在同一个簇中。我还尝试通过关键字“connectivity”将连接矩阵传递给 AgglomerativeClustering。这并不适用于所有情况。下面是一个归结的问题。

如果我不使用连接关键字,我会得到集群标签 [0 1 0 1 0]。这是有道理的,因为不兼容的对象 0 和 1 不在同一簇中,不兼容的对象 2 和 3 也不在同一簇中。但是,当我提供连接矩阵时,我得到簇标签 [0 1 0 0 0]。这似乎与连接矩阵中的连接关系相矛盾,因为对象 2 和 3 不应该位于同一簇中。

我没有正确使用“连通性”这个论点吗?如果是这样,如何使用它来实现我上面描述的目标?

import numpy as np
from sklearn.cluster import AgglomerativeClustering

n_clusters = 2

distance_matrix = np.array([
[0.,1.,0.,0.,0.],
[1.,0.,0.,0.,0.], 
[0.,0.,0.,1.,0.], 
[0.,0.,1.,0.,0.], 
[0.,0.,0.,0.,0.]
])

connectivity_matrix = np.array([
[True, False, True, True, True],
[False, True, True, True, True],
[True, True, True, False, True],
[True, True, False, True, True],
[True, True, True, True, True]
])

agglomerativeClustering = AgglomerativeClustering(n_clusters=n_clusters, metric='precomputed', 
                                                  linkage='average')
cluster_labels_wo_connectivity_matrix = agglomerativeClustering.fit_predict(distance_matrix)

agglomerativeClustering = AgglomerativeClustering(n_clusters=n_clusters, metric='precomputed', 
                                                  linkage='average', connectivity=connectivity_matrix)
cluster_labels_with_connectivity_matrix = agglomerativeClustering.fit_predict(distance_matrix)

print("Cluster labels without considering connectivity matrix: ", cluster_labels_wo_connectivity_matrix)
print("Cluster labels with considering connectivity matrix: ", cluster_labels_with_connectivity_matrix)

我尝试选择其他类型的“链接”,有时有帮助,有时没有。我尝试创建一个返回连接矩阵的可调用函数,例如本例中的“kneighbors_graph”:https://scikit-learn.org/stable/auto_examples/cluster/plot_agglomerative_clustering.html 这没有什么区别。

stackoverflow 上最接近的相关问题是这个:Scikit-learn 聚合聚类连接矩阵

但是,在我的例子中,连接矩阵隐含的图形是相连的。

python scikit-learn hierarchical-clustering connectivity
1个回答
0
投票

我没有正确使用“连通性”这个论点吗?如果是这样,如何使用它来实现我上面描述的目标?

我的印象是你使用它是正确的。我希望受约束的模型能够找到与原始解决方案类似的有效解决方案,原因是原始解决方案尊重约束。我不知道为什么结果看起来是错误的,但以下似乎可以通过测试用例解决这个问题。

从原始距离矩阵开始,我使用

manifold.MDS()
对其进行反转,它会找到尽可能尊重原始距离的空间点配置。这是它找到的解决方案之一(我规定了
n_components=2
或 2D):

enter image description here

从视觉上看,这种反演展现了原始距离矩阵的一些显着特征:类 0/1 和 2/3 被推开,而类 4 距离任何类都不太远。 MDS 显然在这个距离矩阵上遇到了困难,得分为 0.71(超过 0.2 被认为很差),而且当使用更多组件时得分没有提高。这些因素表明原始距离矩阵的结构存在问题。

原始距离矩阵和 MDS 矩阵:

enter image description here

array([[0.  , 1.  , 0.98, 0.18, 0.5 ],
       [1.  , 0.  , 0.18, 0.98, 0.5 ],
       [0.98, 0.18, 0.  , 1.  , 0.5 ],
       [0.18, 0.98, 1.  , 0.  , 0.5 ],
       [0.5 , 0.5 , 0.5 , 0.5 , 0.  ]])

MDS 表示与原始表示有“一些”相似之处。区别在于 0 类和 2 类被认为几乎与 0/1 类和 2/3 类一样远。 它呈现

[0, 1, 1, 0, 0]

的有效聚类,其中类 (0, 2, 3) 在一个聚类中,而 (1, 4) 定义一个单独的聚类。

AgglomerativeClustering(
  n_clusters=2,
  linkage='average',
  connectivity=connectivity_matrix
).fit_predict(mds_coords) 

或者等效地,使用 MDS 结果中的距离矩阵:

from sklearn.metrics import pairwise_distances mds_distance_matrix = pairwise_distances(mds_coords) AgglomerativeClustering( n_clusters=2, linkage='average', connectivity=connectivity_matrix, metric='precomputed', ).fit_predict(mds_distance_matrix)

© www.soinside.com 2019 - 2024. All rights reserved.