web-dev-qa-db-ja.com

pythonでのグラフのスペクトルクラスタリング

スペクトルクラスタリングを使用して、pythonでグラフをクラスタリングしたいと思います。

スペクトルクラスタリングは、グラフだけでなく画像やあらゆる種類のデータにも適用できる、より一般的な手法ですが、例外的なgraphクラスタリング手法。悲しいことに、スペクトルクラスタリンググラフの例はpython online。

私はこれをどのように進めるかについて何らかの方向性が欲しいです。誰かが私がそれを理解するのを手伝うことができるなら、私はscikit learnにドキュメントを追加できます。

ノート:

16
Alex Lenail

スペクトルクラスタリングの経験があまりなく、ドキュメントの説明を読むだけです(結果を確認するには最後までスキップしてください)。

コード:

_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人のメンバーを表しています。 (ザカリーは社会学者であり、彼はメンバーの1人でした。)2つのノード間のエッジは、2人のメンバーが通常のクラブ会議以外でかなりの時間を費やしたことを示します。 Zacharyがデータを収集している間に空手クラブで論争があり、それが2つの派splitに分かれていたため、データセットは興味深いものです。こんにちは」と「ジョンA」が率いるもの。接続情報(エッジ)のみを使用して、2つの派factを回復できることがわかりました。

これに取り組むためにsklearnとスペクトルクラスタリングを使用する:

アフィニティがグラフの隣接行列である場合、このメソッドを使用して、正規化されたグラフカットを見つけることができます。

これ は、正規化されたグラフカットを次のように説明します。

A∪B = VおよびA dis B = thatとなるように、グラフの頂点Vの2つの互いに素なパーティションAおよびBを見つける

2つの頂点間の類似性測度w(i、j)が与えられた場合(たとえば、それらが接続されている場合の同一性)、カット値(およびその正規化バージョン)は次のように定義されます:cut(A、B)= SUM u in A、v in B: w(u、v)

...

グループAとBの間の関連付けの最小化と、各グループ内の関連付けの最大化を求めます

大丈夫ですね。したがって、隣接行列(nx.to_numpy_matrix(G))を作成し、param affinityprecomputedに設定します(adjancency-matrixは事前に計算された類似性であるため、測定)。

または、事前計算されたユーザー提供のアフィニティマトリックスを使用できます。

編集:これに慣れていない間、私はチューニングするパラメータと見つかった assign_labels

埋め込みスペースにラベルを割り当てるために使用する戦略。ラプラシアンの埋め込み後にラベルを割り当てるには、2つの方法があります。 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
_

それは、地上の真実にほぼ完璧にフィットしています!

20
sascha

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]
5
sinapan