本文目录导读:

我来给你几个使用NetworkX进行网络聚类的完整案例。
基础环境准备
import networkx as nx import matplotlib.pyplot as plt import numpy as np from networkx.algorithms import community from sklearn.cluster import SpectralClustering from sklearn.metrics import normalized_mutual_info_score # 设置中文显示 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False
基于社区检测的聚类
1 Louvain算法(推荐)
# 创建示例网络
def create_demo_network():
G = nx.Graph()
# 添加三个社区
# 社区1
community1 = range(0, 10)
G.add_edges_from([(i, j) for i in community1 for j in community1 if i < j])
# 社区2
community2 = range(10, 20)
G.add_edges_from([(i, j) for i in community2 for j in community2 if i < j])
# 社区3
community3 = range(20, 30)
G.add_edges_from([(i, j) for i in community3 for j in community3 if i < j])
# 添加跨社区连接
G.add_edges_from([(0, 10), (5, 15), (10, 20), (15, 25)])
return G
# 使用Louvain算法进行社区检测
def louvain_clustering():
G = create_demo_network()
# 执行Louvain社区检测
communities = community.louvain_communities(G)
print("Louvain社区检测结果:")
for idx, comm in enumerate(communities):
print(f"社区 {idx+1}: {sorted(comm)}")
# 可视化
pos = nx.spring_layout(G, seed=42)
colors = ['red', 'blue', 'green', 'yellow', 'purple']
plt.figure(figsize=(10, 8))
for idx, comm in enumerate(communities):
nx.draw_networkx_nodes(G, pos,
nodelist=list(comm),
node_color=colors[idx],
node_size=100,
label=f"社区 {idx+1}")
nx.draw_networkx_edges(G, pos, alpha=0.5)
nx.draw_networkx_labels(G, pos, font_size=8)
plt.title("Louvain社区检测结果")
plt.legend()
plt.axis('off')
plt.show()
return communities
# 运行Louvain聚类
louvain_communities = louvain_clustering()
2 Girvan-Newman算法
def girvan_newman_clustering():
G = create_demo_network()
# 执行Girvan-Newman社区检测
communities_generator = community.girvan_newman(G)
top_level_communities = next(communities_generator)
# 转换为列表
communities = sorted(map(sorted, top_level_communities))
print("Girvan-Newman社区检测结果:")
for idx, comm in enumerate(communities):
print(f"社区 {idx+1}: {comm}")
# 计算模块度
modularity_score = community.modularity(G, communities)
print(f"模块度: {modularity_score:.3f}")
# 可视化
pos = nx.spring_layout(G, seed=42)
colors = ['red', 'blue', 'green', 'yellow']
plt.figure(figsize=(10, 8))
for idx, comm in enumerate(communities):
nx.draw_networkx_nodes(G, pos,
nodelist=comm,
node_color=colors[idx],
node_size=100,
label=f"社区 {idx+1}")
nx.draw_networkx_edges(G, pos, alpha=0.5)
nx.draw_networkx_labels(G, pos, font_size=8)
plt.title("Girvan-Newman社区检测结果\n模块度: {:.3f}".format(modularity_score))
plt.legend()
plt.axis('off')
plt.show()
return communities
# 运行
gn_communities = girvan_newman_clustering()
基于谱聚类的网络聚类
def spectral_clustering_network():
# 创建随机块模型网络
G = nx.stochastic_block_model(sizes=[15, 15, 15],
p=[[0.8, 0.1, 0.1],
[0.1, 0.8, 0.1],
[0.1, 0.1, 0.8]],
seed=42)
# 获取邻接矩阵
adj_matrix = nx.to_numpy_array(G)
# 执行谱聚类
n_clusters = 3
clustering = SpectralClustering(n_clusters=n_clusters,
affinity='precomputed',
random_state=42)
labels = clustering.fit_predict(adj_matrix)
# 可视化结果
pos = nx.spring_layout(G, seed=42)
colors = ['red', 'blue', 'green']
plt.figure(figsize=(10, 8))
for cluster_id in range(n_clusters):
node_indices = [i for i, label in enumerate(labels) if label == cluster_id]
nx.draw_networkx_nodes(G, pos,
nodelist=node_indices,
node_color=colors[cluster_id],
node_size=100,
label=f"谱聚类第{cluster_id+1}组")
nx.draw_networkx_edges(G, pos, alpha=0.3)
nx.draw_networkx_labels(G, pos, font_size=8)
plt.title("光谱聚类结果")
plt.legend()
plt.axis('off')
plt.show()
# 评估聚类效果
true_labels = [0]*15 + [1]*15 + [2]*15
nmi = normalized_mutual_info_score(true_labels, labels)
print(f"归一化互信息(NMI): {nmi:.3f}")
return labels, G
基于标签传播的聚类
def label_propagation_clustering():
# 创建网络
G = nx.karate_club_graph()
# 执行标签传播算法
communities = community.asyn_lpa_communities(G)
# 转换为字典格式
node_community = {}
for idx, comm in enumerate(communities):
for node in comm:
node_community[node] = idx
print("空手道俱乐部网络标签传播结果:")
for node, comm_id in sorted(node_community.items()):
print(f"节点 {node}: 社区 {comm_id}")
# 可视化
pos = nx.spring_layout(G, seed=42)
colors = ['red', 'blue', 'green', 'yellow']
plt.figure(figsize=(10, 8))
# 绘制每个社区
for comm_id in set(node_community.values()):
nodes_in_comm = [node for node, c_id in node_community.items()
if c_id == comm_id]
nx.draw_networkx_nodes(G, pos,
nodelist=nodes_in_comm,
node_color=colors[comm_id % len(colors)],
node_size=100,
label=f"社区 {comm_id+1}")
nx.draw_networkx_edges(G, pos, alpha=0.5)
nx.draw_networkx_labels(G, pos, font_size=8)
plt.title("标签传播算法聚类结果")
plt.legend()
plt.axis('off')
plt.show()
return node_community
模块度优化聚类
def modularity_optimization():
# 创建更大规模的网络
G = nx.karate_club_graph()
# 使用模块度最大化进行社区检测
communities = community.greedy_modularity_communities(G)
# 计算模块度
modularity_score = community.modularity(G, communities)
print("贪心模块度优化结果:")
for idx, comm in enumerate(sorted(communities, key=len, reverse=True)):
print(f"社区 {idx+1} (大小={len(comm)}): {sorted(comm)}")
print(f"模块度: {modularity_score:.3f}")
# 可视化
pos = nx.spring_layout(G, seed=42)
colors = plt.cm.Set3(np.linspace(0, 1, len(communities)))
plt.figure(figsize=(12, 8))
for idx, comm in enumerate(communities):
nx.draw_networkx_nodes(G, pos,
nodelist=list(comm),
node_color=[colors[idx]],
node_size=100,
label=f"社区 {idx+1}")
nx.draw_networkx_edges(G, pos, alpha=0.5)
nx.draw_networkx_labels(G, pos, font_size=8)
plt.title(f"贪心模块度优化聚类结果\n模块度: {modularity_score:.3f}")
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.axis('off')
plt.tight_layout()
plt.show()
return communities, modularity_score
复杂网络聚类综合案例
def advanced_network_clustering():
# 创建更复杂的网络拓扑
G = nx.powerlaw_cluster_graph(100, 3, 0.3, seed=42)
# 多种聚类算法比较
algorithms = {
'Louvain': community.louvain_communities,
'Label_Propagation': community.asyn_lpa_communities,
'Greedy_Modularity': community.greedy_modularity_communities
}
results = {}
# 执行所有算法
for name, algo in algorithms.items():
try:
communities = list(algo(G))
mod_score = community.modularity(G, communities)
results[name] = {
'communities': communities,
'modularity': mod_score,
'n_clusters': len(communities),
'cluster_sizes': [len(c) for c in communities]
}
print(f"{name}算法:")
print(f" 社区数量: {len(communities)}")
print(f" 模块度: {mod_score:.3f}")
print(f" 社区大小分布: {sorted(results[name]['cluster_sizes'], reverse=True)}")
print()
except Exception as e:
print(f"{name}算法失败: {e}")
# 可视化比较
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
pos = nx.spring_layout(G, seed=42)
colors = plt.cm.Set2(np.linspace(0, 1, 8))
for idx, (name, result) in enumerate(results.items()):
ax = axes[idx]
for cluster_idx, comm in enumerate(result['communities']):
nx.draw_networkx_nodes(G, pos,
nodelist=list(comm),
node_color=[colors[cluster_idx % len(colors)]],
node_size=30,
ax=ax)
nx.draw_networkx_edges(G, pos, alpha=0.1, ax=ax)
ax.set_title(f"{name}\n模块度: {result['modularity']:.3f}")
ax.axis('off')
plt.suptitle("网络聚类算法比较", fontsize=14)
plt.tight_layout()
plt.show()
return results, G
# 运行综合案例
if __name__ == "__main__":
print("======= 网络聚类案例分析 =======")
results, G = advanced_network_clustering()
实用工具函数
def evaluate_clustering(G, communities):
"""评估聚类效果"""
# 计算模块度
mod_score = community.modularity(G, communities)
# 计算覆盖率
covered_nodes = set()
for comm in communities:
covered_nodes.update(comm)
coverage = len(covered_nodes) / G.number_of_nodes()
# 计算平均社区大小
avg_size = np.mean([len(comm) for comm in communities])
return {
'modularity': mod_score,
'coverage': coverage,
'n_communities': len(communities),
'avg_cluster_size': avg_size
}
def plot_clustering_comparison(results_dict, G):
"""绘制多个聚类结果比较图"""
fig, axes = plt.subplots(2, 2, figsize=(12, 12))
axes = axes.ravel()
pos = nx.spring_layout(G, seed=42)
for idx, (name, communities) in enumerate(results_dict.items()):
if idx >= 4:
break
ax = axes[idx]
colors = plt.cm.Set3(np.linspace(0, 1, len(communities)))
for cluster_idx, comm in enumerate(communities):
nx.draw_networkx_nodes(G, pos,
nodelist=list(comm),
node_color=[colors[cluster_idx]],
node_size=50,
ax=ax)
nx.draw_networkx_edges(G, pos, alpha=0.2, ax=ax)
stats = evaluate_clustering(G, communities)
ax.set_title(f"{name}\n模块度: {stats['modularity']:.3f}, "
f"社区数: {stats['n_communities']}")
ax.axis('off')
plt.tight_layout()
plt.show()
- Louvain算法:速度快,适合大规模网络,是推荐的首选方法
- Girvan-Newman算法:基于边介数,但计算量大
- 谱聚类:适合知道社区数量时使用
- 标签传播:简单快速,但结果不稳定
- 模块度优化:适合追求高模块度的场景
选择聚类算法时,需要考虑网络规模、社区结构特点、计算资源等因素。