Scikit-learn 凝聚聚类连接矩阵

Posted

技术标签:

【中文标题】Scikit-learn 凝聚聚类连接矩阵【英文标题】:Scikit-learn Agglomerative Clustering Connectivity Matrix 【发布时间】:2017-08-06 21:24:40 【问题描述】:

我正在尝试使用 sklearn 的凝聚聚类命令执行约束聚类。为了使算法受到约束,它需要一个“连接矩阵”。这被描述为:

连接性约束是通过连接性矩阵施加的:一个 scipy 稀疏矩阵,其元素仅位于行和列的交叉点,其中包含应连接的数据集的索引。这个矩阵可以从先验信息构建:例如,您可能希望通过仅合并具有从一个指向另一个指向的链接的页面来对网页进行聚类。

我有一个观察对列表,我希望算法强制它们保持在同一个集群中。我可以将其转换为稀疏的scipy 矩阵(coocsr),但生成的集群无法强制约束。

一些数据:

import numpy as np
import scipy as sp
import pandas as pd
import scipy.sparse as ss
from sklearn.cluster import AgglomerativeClustering


# unique ids 
ids = np.arange(10)

# Pairs that should belong to the same cluster
mustLink = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])

# Features for training the model
data = pd.DataFrame([
[.0873,-1.619,-1.343],
[0.697456, 0.410943, 0.804333],
[-1.295829, -0.709441, -0.376771],
[-0.404985, -0.107366, 0.875791],
[-0.404985, -0.107366,  0.875791],
[-0.515996, 0.731980, -1.569586],
[1.024580,  0.409148, 0.149408],
[-0.074604, 1.269414, 0.115744],
[-0.006706, 2.097276, 0.681819],
[-0.432196, 1.249149,-1.159271]])

将这些对转换为“连接矩阵”:

# Blank coo matrix to csr
sm = ss.coo_matrix((len(ids), len(ids)), np.int32).tocsr()
# Insert 1 for connected pairs and diagonals
for i in np.arange(len(mustLink)): # add links to both sides of the matrix
    sm[mustLink.loc[i, 'A'], mustLink.loc[i, 'B']] = 1
    sm[mustLink.loc[i, 'B'], mustLink.loc[i, 'A']] = 1
for i in np.arange(sm.tocsr()[1].shape[1]): # add diagonals
    sm[i,i] = 1
sm = sm.tocoo() # convert back to coo format

训练和拟合凝聚聚类模型:

m = AgglomerativeClustering(n_clusters=6, connectivity=sm)
out = m.fit_predict(X=data)

我收到的警告:

UserWarning:连通矩阵的连通分量数为 7 > 1。完成它以避免过早停止树。 连通性,n_components = _fix_connectivity(X, 连通性)

除了不祥的警告之外,我希望的对属于同一个集群,但事实并非如此。

这是因为 sklearn 算法不是为处理 mustlink 约束而设计的,而是只能使用distance 矩阵(区分here)?

【问题讨论】:

你的代码不是这样运行的 :) 也许值得在新的 python 会话中自己测试一下。 更新了!感谢您的提醒 您的连接矩阵无效。所有点必须连接在一起,因为凝聚聚类将层次结构中的所有点聚集在一起。 (您可以将其视为必须形成一个不能不相交的图形的所有点。可以关闭节点之间的边)。这就是您收到警告的原因。没有很好的方法来做你正在尝试用凝聚集群做的事情。 谢谢,@y300。如果您想将该评论放大为完整的回复,我将奖励您赏金。这就是我一直在寻找的。​​span> 【参考方案1】:

将连接矩阵传递给sklearn.cluster.AgglomerativeClustering 时,必须连接矩阵中的所有点。凝聚聚类创建了一个层次结构,其中所有点迭代地组合在一起,因此孤立的聚类不能存在。连接矩阵对于“关闭”欧几里得空间中可能在附近但远离另一个度量的点的连接很有用(请参阅用户指南here 中显示的果冻卷示例)。

另一种思考方式是,您的点必须形成一个不相交的图,您所能做的就是关闭节点之间的边。

此警告:

UserWarning:连通矩阵的连通分量数为 7 > 1。完成它以避免过早停止树。连通性,n_components = _fix_connectivity(X, 连通性)

告诉您您有 7 个不相交的集群,这比允许的 1 个多。因此 sklearn “完成”了它(基本上将其填充为不具有不相交的集群),这就是为什么您的约束根本不被尊重的原因。

这里没有简单的解决方法。您可以尝试在聚类后重新分配中心以尊重您的约束,或者您需要使用不同的算法。

【讨论】:

以上是关于Scikit-learn 凝聚聚类连接矩阵的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python Scikit-learn 中获得凝聚聚类“质心”

如何在 Scikit-learn 凝聚聚类中使用 Pearson 相关性作为距离度量

分层凝聚聚类:如何更新距离矩阵?

使用 DTW 距离矩阵的凝聚聚类

sklearn 具有距离链接准则的凝聚聚类

使用 scikit 选择层次凝聚聚类中的聚类数