Scikit-learn凝聚聚类连通矩阵

Mic*_*son 8 python hierarchical-clustering scikit-learn

我试图使用sklearn的凝聚聚类命令执行约束聚类.为了使算法受约束,它请求"连接矩阵".这被描述为:

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

我有一个观察对列表,我希望算法将强制保留在同一个集群中.我可以将其转换为稀疏scipy矩阵(coo或者csr),但是生成的集群无法强制约束.

一些数据:

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]])
Run Code Online (Sandbox Code Playgroud)

将对转换为"连接矩阵":

# 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
Run Code Online (Sandbox Code Playgroud)

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

m = AgglomerativeClustering(n_clusters=6, connectivity=sm)
out = m.fit_predict(X=data)
Run Code Online (Sandbox Code Playgroud)

警告我收到:

UserWarning:连接矩阵的连接组件数为7> 1.完成它以避免提前停止树.连接,n_components = _fix_connectivity(X,连接)

除了不祥的警告,我希望它们属于同一个集群的对,不会.

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

yhe*_*non 9

通过连接矩阵时sklearn.cluster.AgglomerativeClustering,必须连接矩阵中的所有点.凝聚聚类创建一个层次结构,其中所有点都迭代地组合在一起,因此隔离的聚类不可能存在.连接矩阵是"关闭"的连接点可能在附近的欧氏空间,但远离另一个指标有用(请参阅用户手册中的胶卷例子显示在这里).

想到这一点的另一种方法是你的点必须形成一个不相交的图形,你所能做的就是关闭节点之间的边缘.

这个警告:

UserWarning:连接矩阵的连接组件数为7> 1.完成它以避免提前停止树.连接,n_components = _fix_connectivity(X,连接)

告诉你,你有7个不相交的簇,超过了允许的1个.因此sklearn"完成"它(基本上填充它没有不相交的簇),这就是为什么你的约束根本不受尊重.

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