Python案例如何用Networkx做网络嵌入

wen python案例 1

本文目录导读:

Python案例如何用Networkx做网络嵌入

  1. 基础环境配置
  2. 创建示例图
  3. 基于邻接矩阵的嵌入方法
  4. Node2Vec嵌入方法
  5. 完整示例:网络嵌入可视化
  6. 高级应用:节点分类

我来介绍如何使用NetworkX进行网络嵌入(Network Embedding),NetworkX本身没有直接实现网络嵌入的算法,但可以结合其他库来实现。

基础环境配置

# 安装必要的库
# pip install networkx
# pip install node2vec
# pip install gensim
# pip install scikit-learn
# pip install matplotlib
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA

创建示例图

# 方式1:创建随机图
G = nx.karate_club_graph()  # 空手道俱乐部图
print(f"节点数: {G.number_of_nodes()}")
print(f"边数: {G.number_of_edges()}")
# 方式2:创建自定义图
def create_sample_graph():
    G = nx.Graph()
    edges = [
        (1, 2), (1, 3), (2, 3), (2, 4), (3, 4),
        (4, 5), (5, 6), (5, 7), (6, 7),
        (7, 8), (8, 9), (8, 10), (9, 10)
    ]
    G.add_edges_from(edges)
    return G
# 可视化图
def visualize_graph(G, title="Graph Visualization"):
    plt.figure(figsize=(8, 6))
    pos = nx.spring_layout(G, seed=42)
    nx.draw(G, pos, with_labels=True, node_color='lightblue', 
            node_size=500, font_size=10, font_weight='bold')
    plt.title(title)
    plt.show()
G = create_sample_graph()
visualize_graph(G)

基于邻接矩阵的嵌入方法

def adjacency_embedding(G, dimensions=2):
    """
    基于邻接矩阵的嵌入
    """
    # 获取邻接矩阵
    adj_matrix = nx.adjacency_matrix(G).toarray()
    # 使用PCA降维
    pca = PCA(n_components=dimensions)
    embeddings = pca.fit_transform(adj_matrix)
    return embeddings
# 使用Laplacian特征映射
def laplacian_embedding(G, dimensions=2):
    """
    Laplacian特征映射
    """
    # 计算拉普拉斯矩阵
    L = nx.laplacian_matrix(G).toarray()
    # 计算特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eigh(L)
    # 选择最小的非零特征值对应的特征向量
    idx = np.argsort(eigenvalues)
    eigenvectors = eigenvectors[:, idx]
    # 返回嵌入向量(跳过第一个特征向量)
    embeddings = eigenvectors[:, 1:dimensions+1]
    return embeddings
# 应用嵌入
adj_emb = adjacency_embedding(G, 2)
lap_emb = laplacian_embedding(G, 2)
print("邻接矩阵嵌入形状:", adj_emb.shape)
print("拉普拉斯嵌入形状:", lap_emb.shape)

Node2Vec嵌入方法

# 方式1:使用node2vec库
from node2vec import Node2Vec
def node2vec_embedding(G, dimensions=128, walk_length=30, num_walks=200):
    """
    Node2Vec网络嵌入
    """
    # 初始化Node2Vec模型
    node2vec = Node2Vec(G, dimensions=dimensions, 
                       walk_length=walk_length, 
                       num_walks=num_walks,
                       workers=4)  # 并行工作线程数
    # 训练模型
    model = node2vec.fit(window=10, min_count=1, batch_words=4)
    return model
# 方式2:手动实现简单的随机游走嵌入
def random_walk_embedding(G, walk_length=20, num_walks=10, dimensions=128):
    """
    基于随机游走的简单嵌入
    """
    from gensim.models import Word2Vec
    walks = []
    nodes = list(G.nodes())
    for _ in range(num_walks):
        for node in nodes:
            walk = [node]
            current = node
            for _ in range(walk_length - 1):
                neighbors = list(G.neighbors(current))
                if neighbors:
                    current = np.random.choice(neighbors)
                    walk.append(current)
                else:
                    break
            walks.append([str(n) for n in walk])
    # 使用Word2Vec训练嵌入
    model = Word2Vec(walks, vector_size=dimensions, 
                    window=5, min_count=0, sg=1, workers=4)
    return model
# 应用Node2Vec
node2vec_model = node2vec_embedding(G, dimensions=64, walk_length=20, num_walks=100)
# 获取节点嵌入
def get_node_embeddings(model, nodes):
    embeddings = {}
    for node in nodes:
        embeddings[node] = model.wv[str(node)]
    return embeddings
embeddings = get_node_embeddings(node2vec_model, G.nodes())
print("节点嵌入维度:", len(embeddings[1]))
print("节点1的嵌入向量:\n", embeddings[1][:10], "...")

完整示例:网络嵌入可视化

class NetworkEmbeddingDemo:
    def __init__(self):
        self.G = None
        self.embeddings = None
    def load_graph(self, graph_type='karate'):
        """加载图数据"""
        if graph_type == 'karate':
            self.G = nx.karate_club_graph()
        elif graph_type == 'erdos':
            self.G = nx.erdos_renyi_graph(20, 0.15, seed=42)
        elif graph_type == 'watts':
            self.G = nx.watts_strogatz_graph(30, 3, 0.1, seed=42)
        return self.G
    def compute_node2vec_embedding(self, dimensions=64):
        """计算Node2Vec嵌入"""
        if self.G is None:
            raise ValueError("请先加载图数据")
        # 节点重命名为字符串
        G_str = nx.Graph()
        G_str.add_nodes_from([str(n) for n in self.G.nodes()])
        G_str.add_edges_from([(str(u), str(v)) for u, v in self.G.edges()])
        node2vec = Node2Vec(G_str, dimensions=dimensions,
                           walk_length=30, num_walks=200, workers=4)
        model = node2vec.fit(window=10, min_count=1)
        self.embeddings = model
        return model
    def visualize_embeddings(self, method='tsne'):
        """可视化嵌入结果"""
        if self.embeddings is None:
            raise ValueError("请先计算嵌入")
        # 获取所有节点嵌入
        nodes = list(self.G.nodes())
        vectors = np.array([self.embeddings.wv[str(n)] for n in nodes])
        # 降维到2D
        if method == 'tsne':
            reducer = TSNE(n_components=2, random_state=42)
        else:
            reducer = PCA(n_components=2)
        vectors_2d = reducer.fit_transform(vectors)
        # 可视化
        plt.figure(figsize=(12, 5))
        # 子图1:原始图
        plt.subplot(121)
        pos = nx.spring_layout(self.G, seed=42)
        nx.draw(self.G, pos, with_labels=True, node_color='lightblue',
                node_size=200, font_size=8)
        plt.title("原始图结构")
        # 子图2:嵌入空间
        plt.subplot(122)
        plt.scatter(vectors_2d[:, 0], vectors_2d[:, 1], c='blue', alpha=0.6)
        for i, node in enumerate(nodes):
            plt.annotate(str(node), (vectors_2d[i, 0], vectors_2d[i, 1]))
        plt.title(f"嵌入空间 ({method.upper()})")
        plt.xlabel("维度1")
        plt.ylabel("维度2")
        plt.tight_layout()
        plt.show()
    def find_similar_nodes(self, node_id, top_k=5):
        """找相似节点"""
        similar = self.embeddings.wv.most_similar(str(node_id), topn=top_k)
        return similar
# 使用示例
demo = NetworkEmbeddingDemo()
demo.load_graph('karate')
demo.compute_node2vec_embedding(dimensions=64)
demo.visualize_embeddings('tsne')
# 找相似节点
similar_nodes = demo.find_similar_nodes(1, top_k=5)
print("与节点1最相似的节点:")
for node, score in similar_nodes:
    print(f"  节点 {node}: 相似度 {score:.4f}")

高级应用:节点分类

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
def node_classification_example():
    """使用嵌入向量进行节点分类"""
    # 加载数据
    G = nx.karate_club_graph()
    # 计算嵌入
    G_str = nx.Graph()
    G_str.add_nodes_from([str(n) for n in G.nodes()])
    G_str.add_edges_from([(str(u), str(v)) for u, v in G.edges()])
    node2vec = Node2Vec(G_str, dimensions=64, walk_length=30, 
                       num_walks=200, workers=4)
    model = node2vec.fit(window=10, min_count=1)
    # 准备特征和标签
    nodes = list(G.nodes())
    X = np.array([model.wv[str(n)] for n in nodes])
    # 使用俱乐部分类作为标签
    y = np.array([G.nodes[n]['club'] for n in nodes])
    y = (y == 'Mr. Hi').astype(int)  # 二分类
    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(
        X, y, test_size=0.3, random_state=42
    )
    # 训练分类器
    clf = RandomForestClassifier(n_estimators=100, random_state=42)
    clf.fit(X_train, y_train)
    # 预测和评估
    y_pred = clf.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    print(f"节点分类准确率: {accuracy:.4f}")
    return accuracy
# 运行分类示例
acc = node_classification_example()

这些示例展示了如何使用NetworkX进行网络嵌入的完整流程,你可以根据具体需求选择不同的嵌入方法,并应用于节点分类、链接预测、可视化等任务中。

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