我想使用谱聚类在python中聚类图。
光谱聚类是一种更通用的技术,不仅可以应用于图形,还可以应用于图像或任何类型的数据,但是,它被认为是一种特殊的图形聚类技术。遗憾的是,我无法在线查找python谱图的示例。
Scikit Learn记录了两种光谱聚类方法:SpectralClustering和spectral_clustering,它们似乎不是别名。
这两种方法都提到它们可以在图表上使用,但不提供具体说明。 Neither does the user guide。我asked for such an example from the developers,但他们过度劳累并没有得到它。
用于记录此内容的良好网络是Karate Club Network。它包括as a method in networkx。
我喜欢如何解决这个问题。如果有人可以帮我搞清楚,我可以将文档添加到scikit learn。
答案 0 :(得分:17)
没有太多的光谱聚类经验,只是通过文档(跳到最后的结果!):
import numpy as np
import networkx as nx
from sklearn.cluster import SpectralClustering
from sklearn import metrics
np.random.seed(1)
# Get your mentioned graph
G = nx.karate_club_graph()
# Get ground-truth: club-labels -> transform to 0/1 np-array
# (possible overcomplicated networkx usage here)
gt_dict = nx.get_node_attributes(G, 'club')
gt = [gt_dict[i] for i in G.nodes()]
gt = np.array([0 if i == 'Mr. Hi' else 1 for i in gt])
# Get adjacency-matrix as numpy-array
adj_mat = nx.to_numpy_matrix(G)
print('ground truth')
print(gt)
# Cluster
sc = SpectralClustering(2, affinity='precomputed', n_init=100)
sc.fit(adj_mat)
# Compare ground-truth and clustering-results
print('spectral clustering')
print(sc.labels_)
print('just for better-visualization: invert clusters (permutation)')
print(np.abs(sc.labels_ - 1))
# Calculate some clustering metrics
print(metrics.adjusted_rand_score(gt, sc.labels_))
print(metrics.adjusted_mutual_info_score(gt, sc.labels_))
ground truth
[0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1]
spectral clustering
[1 1 0 1 1 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
just for better-visualization: invert clusters (permutation)
[0 0 1 0 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
0.204094758281
0.271689477828
来自here的数据和任务简介:
图中的节点代表了大学空手道俱乐部的34名成员。 (Zachary是一名社会学家,他是其中一名成员。)两个节点之间的边缘表明这两个成员在正常的俱乐部会议之外一起度过了大量时间。数据集很有意思,因为当Zachary收集他的数据时,空手道俱乐部发生争执,并分成两派:一派由“先生”领导。嗨“,一个由”约翰A“领导。事实证明,只使用连接信息(边缘),就可以恢复两个派系。
使用sklearn&谱聚类解决这个问题:
如果亲和力是图的邻接矩阵,则此方法可用于查找规范化图切割。
This将规范化的图切割描述为:
找到图的顶点V的两个不相交的分区A和B. A∪B= V且A∩B=∅
给定两个顶点之间的相似性度量w(i,j)(例如,同一性) 当它们连接时)切割值(及其标准化版本)定义为: cut(A,B)= A中的SUM u,B中的v:w(u,v)
...
我们寻求最小化解体 A组和B组之间以及关联的最大化 在每个小组内
听起来不错。因此,我们创建邻接矩阵(nx.to_numpy_matrix(G)
)并将参数affinity
设置为预先计算(因为我们的adjancency-matrix是我们预先计算的相似性度量)。
或者,使用预先计算的,可以使用用户提供的亲和力矩阵。
修改:虽然不熟悉这一点,但我找了参数来调整并找到assign_labels:
用于在嵌入空间中指定标签的策略。在拉普拉斯嵌入之后,有两种方法可以分配标签。 k-means可以应用,是一个受欢迎的选择。但它也可能对初始化很敏感。离散化是另一种对随机初始化不太敏感的方法。
所以尝试不太敏感的方法:
sc = SpectralClustering(2, affinity='precomputed', n_init=100, assign_labels='discretize')
输出:
ground truth
[0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1]
spectral clustering
[0 0 1 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1]
just for better-visualization: invert clusters (permutation)
[1 1 0 1 1 1 1 1 0 0 1 1 1 1 0 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
0.771725032425
0.722546051351
这完全符合事实真相!
答案 1 :(得分:1)
这是一个虚拟的例子,只是为了看看它对简单相似矩阵的作用-受sascha的回答启发。
代码
import numpy as np
from sklearn.cluster import SpectralClustering
from sklearn import metrics
np.random.seed(0)
adj_mat = [[3,2,2,0,0,0,0,0,0],
[2,3,2,0,0,0,0,0,0],
[2,2,3,1,0,0,0,0,0],
[0,0,1,3,3,3,0,0,0],
[0,0,0,3,3,3,0,0,0],
[0,0,0,3,3,3,1,0,0],
[0,0,0,0,0,1,3,1,1],
[0,0,0,0,0,0,1,3,1],
[0,0,0,0,0,0,1,1,3]]
adj_mat = np.array(adj_mat)
sc = SpectralClustering(3, affinity='precomputed', n_init=100)
sc.fit(adj_mat)
print('spectral clustering')
print(sc.labels_)
输出
spectral clustering
[0 0 0 1 1 1 2 2 2]