本文目录导读:

我来介绍如何使用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进行网络嵌入的完整流程,你可以根据具体需求选择不同的嵌入方法,并应用于节点分类、链接预测、可视化等任务中。