Python案例如何用Networkx做网络聚类

wen python案例 1

本文目录导读:

Python案例如何用Networkx做网络聚类

  1. 基础环境准备
  2. 基于社区检测的聚类
  3. 基于谱聚类的网络聚类
  4. 基于标签传播的聚类
  5. 模块度优化聚类
  6. 复杂网络聚类综合案例
  7. 实用工具函数

我来给你几个使用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()
  1. Louvain算法:速度快,适合大规模网络,是推荐的首选方法
  2. Girvan-Newman算法:基于边介数,但计算量大
  3. 谱聚类:适合知道社区数量时使用
  4. 标签传播:简单快速,但结果不稳定
  5. 模块度优化:适合追求高模块度的场景

选择聚类算法时,需要考虑网络规模、社区结构特点、计算资源等因素。

抱歉,评论功能暂时关闭!