繁体   English   中英

在python中对图形进行光谱聚类

[英]Spectral Clustering a graph in python

我想使用谱聚类在 python 中聚类一个图。

光谱聚类是一种更通用的技术,不仅可以应用于图形,还可以应用于图像或任何类型的数据,但是,它被认为是一种特殊的图形聚类技术。 遗憾的是,我在网上找不到 Python 中的谱聚类图示例。

我很想知道如何解决这个问题。 如果有人能帮我弄清楚,我可以将文档添加到 scikit learn 中。

笔记:

没有太多的Spectral-clustering经验,只是通过文档(跳到最后的结果!):

码:

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

总体思路:

这里介绍数据和任务:

图中的节点代表了大学空手道俱乐部的34名成员。 (Zachary是一名社会学家,他是其中一名成员。)两个节点之间的边缘表明这两个成员在正常的俱乐部会议之外一起度过了大量时间。 数据集很有意思,因为当Zachary收集他的数据时,空手道俱乐部发生争执,并分成两派:一派由“先生”领导。 嗨“,一个由”约翰A“领导。 事实证明,仅使用连接信息(边缘),可以恢复两个派系。

使用sklearn和谱聚类来解决这个问题:

如果affinity是图的邻接矩阵,则此方法可用于查找规范化图切割。

将标准化图形切割描述为:

找到图的顶点V的两个不相交的分区A和B,这样A∪B= V和A∩B=∅

给定两个顶点之间的相似性度量w(i,j)(例如,当它们连接时的标识),剪切值(及其标准化版本)被定义为:cut(A,B)= A中的SUM u,B中的v: w(你,v)

...

我们寻求最小化A组和B组之间的分离以及每组内关联的最大化

听起来不错。 因此,我们创建邻接矩阵( nx.to_numpy_matrix(G) )并将param 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

这完全符合事实真相!

这是一个虚拟的例子,只是为了看看它对简单相似性矩阵的作用 - 受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]

如果我们希望对图形分割成2群,我们可以使用函数linalg.algebraicconnectivity.fiedler_vector()networkx太,以便计算的费德勒向量(对应于图的拉普拉斯矩阵的第二最小特征值的特征向量)的图,假设图是一个连通的无向图。

使用相同的示例数组,我们可以使用上述函数来获取 Fiedler 向量,然后对向量的值进行阈值处理以计算每个节点对应的集群索引。

import networkx as nx
import numpy as np
A = np.array([[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]])
G = nx.from_numpy_matrix(A)
ev = nx.linalg.algebraicconnectivity.fiedler_vector(G)
labels = [0 if v < 0 else 1 for v in ev] # using threshold 0
labels
# [0, 0, 0, 0, 0, 1, 1, 1, 1]

我们可以迭代/递归地使用该函数来进一步划分每个集群。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM