网络数据上的无监督机器学习
在处理图数据时,机器学习(ML)并不是必需的,但它可以带来很大的帮助。而且,什么是ML、什么不是ML之间的界限也比较模糊。比如,社区检测就可以被视为无监督ML,因为这些算法能够自动识别网络中存在的社区。
网络科学方法
我们其实已经掌握了一些方法,这些方法可以避免使用那些被宣传为图ML的技术。以下是一些例子:
-
社区识别
:可以使用Louvain算法来识别社区,甚至只需要查看连通分量。
-
枢纽节点识别
:使用PageRank算法来识别枢纽节点,而不需要使用嵌入技术。
-
孤立节点识别
:使用
k_corona(0)
来识别孤立节点,根本不需要ML。
-
训练数据创建
:可以将多个图特征组合成训练数据。
不建议在需要模型可解释性的场景中使用Karate Club创建嵌入。嵌入虽然是一个不错的捷径,但使用这些嵌入的模型会变成一个不可解释的黑箱。建议在可能的情况下,优先使用NetworkX中的网络科学方法,但也要了解Karate Club,因为它在某些情况下是有用的。
无监督ML在网络数据上的应用
无监督ML在网络数据上的应用主要分为两类:社区识别和创建嵌入。无监督ML不仅可以为节点创建嵌入,还可以为边或整个图创建嵌入。
社区检测
社区检测的目标是识别网络中存在的节点社区。可以将社区看作是相互以某种方式交互的节点簇。社区检测不仅在涉及人的社交网络分析中有用,在其他领域也有应用,比如网站之间的交互、国家和城市之间的交互等。
社区检测的一个例子是《悲惨世界》中的社区,这个社区的成员之间联系紧密,每个成员都与其他成员相连。当然,其他社区的连接可能更稀疏。
图嵌入
图嵌入可以看作是将复杂网络转换为数学模型更易于使用的数据格式。例如,如果直接将图的边列表或NetworkX图(G)用于随机森林模型,模型将无法使用这些输入数据。为了利用这些模型,需要将图解构为更可用的格式。
在之前的监督机器学习章节中,我们将图转换为了如下格式的训练数据:
- 节点的度
- 聚类系数
- 三角形数量
- 介数和紧密中心性
- PageRank分数
使用嵌入时,图中的所有信息都被解构为一系列嵌入。虽然阅读模型背后的文章可以了解这个过程,但嵌入创建完成后,其可解释性并不强。
这些嵌入可以直接输入到监督ML模型中进行预测,即使模型和数据的可解释性不强,预测结果也可能非常有用。嵌入的下游应用主要有两个:
-
聚类
:目标是识别看起来或行为相似的事物的簇。手工制作的训练数据和Karate Club生成的嵌入都可以用于聚类。但使用任何模型都有其局限性,例如使用K-means时,需要指定预期的簇数量,而这通常是未知的。如果只是想识别簇,也可以使用社区检测算法、
k_corona
、查看连通分量或按PageRank对节点进行排序。
-
分类
:目标是预测某些事情。在社交网络中,可以预测谁最终会成为朋友、谁可能想成为朋友、谁可能会点击广告或购买产品等。分类在ML中通常受到最多关注,使用得当可以让世界变得更美好、更安全。使用手工制作的训练数据训练的模型可以帮助我们了解哪些特征对识别某些行为最有用,而使用嵌入训练的模型可能只能告诉我们某个嵌入编号有用,但这并没有实际意义。
代码实践
在进行后续操作之前,需要先构建一个图。这里使用NetworkX中的《悲惨世界》图:
import networkx as nx
import pandas as pd
# 创建图并移除不需要的字段
G = nx.les_miserables_graph()
df = nx.to_pandas_edgelist(G)[['source', 'target']] # 移除 'weight'
G = nx.from_pandas_edgelist(df)
# 复制图并将节点标签转换为整数
G_named = G.copy()
G = nx.convert_node_labels_to_integers(G, first_label=0, ordering='default', label_attribute=None)
nodes = G_named,
同时,还需要一些带标签的训练数据:
train_data = 'data/clf_df.csv'
clf_df = pd.read_csv(train_data).set_index('index')
社区检测实践
这里将使用Karate Club中的两种算法进行社区检测:SCD和EgoNetSplitter。
SCD
SCD算法声称比最准确的最先进社区检测解决方案快得多,同时保留甚至超越它们的质量,还能处理具有数十亿条边的图。以下是使用SCD算法的步骤:
1. 安装Karate Club:
pip install karateclub
- 导入所需的库:
from karateclub.community_detection.non_overlapping.scd import SCD
import numpy as np
- 使用模型:
model = SCD()
model.fit(G)
clusters = model.get_memberships()
- 将簇信息转换为numpy数组:
clusters = np.array(list(clusters.values()))
- 创建簇的DataFrame:
cluster_df = pd.DataFrame({'node': nodes, 'cluster': clusters})
- 找出节点数量最多的社区:
title = 'Clusters by Node Count (SCD)'
cluster_df['cluster'].value_counts()[0:10].plot.barh(title=title).invert_yaxis()
- 查看特定社区:
check_cluster = 1
community_nodes = cluster_df[cluster_df['cluster'] == check_cluster]['node'].to_list()
G_comm = G_named.subgraph(community_nodes)
draw_graph(G_comm, show_names=True, node_size=5)
SCD算法在《悲惨世界》网络上训练速度极快,而且设置比其他方法更简单,代码量少,并且声称可以扩展到具有数十亿条边的网络。
EgoNetSplitter
EgoNetSplitter算法先创建节点的自我网络,然后使用Louvain方法进行聚类,最后将重叠的簇成员信息存储为字典。以下是使用步骤:
1. 导入模型:
from karateclub.community_detection.overlapping.ego_splitter import EgoNetSplitter
model = EgoNetSplitter()
model.fit(G)
clusters = model.get_memberships()
clusters = np.array(list(clusters.values()))
clusters = [i[0] for i in clusters]
- 创建簇的DataFrame:
cluster_df = pd.DataFrame({'node': nodes, 'cluster': clusters})
- 检查社区成员数量:
title = 'Clusters by Node Count (EgoNetSplitter)'
cluster_df['cluster'].value_counts()[0:10].plot.barh(title=title).invert_yaxis()
- 查看特定社区:
check_cluster = 7
community_nodes = cluster_df[cluster_df['cluster'] == check_cluster]['node'].to_list()
G_comm = G_named.subgraph(community_nodes)
draw_graph(G_comm, show_names=True, node_size=5)
个人更喜欢SCD算法的输出,但也有人认为将那些通过一条连接与社区相连的额外节点包含在社区中比将它们排除更好。由于SCD算法的可扩展性和社区划分的清晰性,在社区检测方面更倾向于使用SCD算法。
下面是一个简单的mermaid流程图,展示无监督ML在网络数据上的应用流程:
graph LR
A[网络数据] --> B{无监督ML应用}
B --> C[社区检测]
B --> D[图嵌入]
C --> E[识别社区]
D --> F[创建嵌入]
F --> G[聚类]
F --> H[分类]
总的来说,无监督ML在网络数据处理中有多种应用,不同的算法和方法各有优缺点,需要根据具体需求选择合适的方法。在后续内容中,我们将继续探讨使用无监督ML创建图嵌入的相关内容。
网络数据上的无监督机器学习
图嵌入的实现与应用
在前面我们了解了图嵌入的概念和潜在用途,接下来将详细介绍如何使用 Karate Club 进行图嵌入的创建,并展示其在聚类和分类任务中的应用。
创建图嵌入
这里我们使用 Karate Club 中的 DeepWalk 算法来创建图嵌入。DeepWalk 是一种基于随机游走的图嵌入方法,它通过在图上进行随机游走生成节点序列,然后使用 Word2Vec 模型将这些节点序列转换为低维向量表示。
以下是使用 DeepWalk 算法创建图嵌入的代码:
from karateclub import DeepWalk
# 创建 DeepWalk 模型
model = DeepWalk()
# 拟合图数据
model.fit(G)
# 获取节点嵌入
embeddings = model.get_embedding()
在上述代码中,我们首先导入了 DeepWalk 类,然后创建了一个 DeepWalk 模型实例。接着,我们使用
fit
方法将图数据
G
拟合到模型中,最后使用
get_embedding
方法获取节点的嵌入表示。
聚类应用
我们可以使用 K-means 算法对生成的嵌入进行聚类,以识别相似的节点。以下是具体的代码实现:
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 设置聚类的数量
n_clusters = 5
# 创建 K-means 模型
kmeans = KMeans(n_clusters=n_clusters)
# 对嵌入进行聚类
cluster_labels = kmeans.fit_predict(embeddings)
# 可视化聚类结果
plt.scatter(embeddings[:, 0], embeddings[:, 1], c=cluster_labels, cmap='viridis')
plt.title('K-means Clustering of Node Embeddings')
plt.xlabel('Embedding Dimension 1')
plt.ylabel('Embedding Dimension 2')
plt.show()
在这段代码中,我们首先导入了 K-means 类和
matplotlib.pyplot
库。然后,我们设置了聚类的数量为 5,并创建了一个 K-means 模型实例。接着,我们使用
fit_predict
方法对嵌入进行聚类,并将聚类结果存储在
cluster_labels
中。最后,我们使用
matplotlib
库将聚类结果可视化。
操作步骤总结如下:
1. 导入所需的库。
2. 设置聚类的数量。
3. 创建 K-means 模型。
4. 对嵌入进行聚类。
5. 可视化聚类结果。
分类应用
我们可以使用逻辑回归模型对生成的嵌入进行分类。以下是具体的代码实现:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 准备训练数据和标签
X = embeddings
y = clf_df['label'].values
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建逻辑回归模型
model = LogisticRegression()
# 拟合训练数据
model.fit(X_train, y_train)
# 进行预测
y_pred = model.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
在上述代码中,我们首先导入了逻辑回归类、
train_test_split
函数和
accuracy_score
函数。然后,我们准备了训练数据
X
和标签
y
,并使用
train_test_split
函数将数据划分为训练集和测试集。接着,我们创建了一个逻辑回归模型实例,并使用
fit
方法将训练数据拟合到模型中。最后,我们使用
predict
方法进行预测,并使用
accuracy_score
函数计算预测的准确率。
操作步骤总结如下:
1. 导入所需的库。
2. 准备训练数据和标签。
3. 划分训练集和测试集。
4. 创建逻辑回归模型。
5. 拟合训练数据。
6. 进行预测。
7. 计算准确率。
不同方法的对比与总结
为了更直观地对比不同方法在社区检测和图嵌入任务中的表现,我们可以将前面介绍的方法进行总结,如下表所示:
| 任务 | 方法 | 优点 | 缺点 |
| ---- | ---- | ---- | ---- |
| 社区检测 | SCD | 速度快,可处理大规模图,社区划分清晰 | |
| 社区检测 | EgoNetSplitter | 考虑了节点的自我网络和重叠社区 | 可能会包含一些不合理的节点 |
| 图嵌入 | DeepWalk | 基于随机游走,能捕捉图的局部和全局结构 | 可解释性较差 |
下面是一个 mermaid 流程图,展示了整个无监督 ML 在网络数据处理中的流程:
graph LR
A[网络数据] --> B{无监督 ML 处理}
B --> C[社区检测]
B --> D[图嵌入]
C --> E{SCD 算法}
C --> F{EgoNetSplitter 算法}
D --> G{DeepWalk 算法}
G --> H[获取嵌入]
H --> I[聚类]
H --> J[分类]
通过以上的分析和实践,我们可以看到无监督 ML 在网络数据处理中具有重要的作用。不同的算法和方法在不同的任务中表现各异,我们需要根据具体的需求和场景选择合适的方法。在实际应用中,我们还需要考虑算法的可扩展性、可解释性以及计算效率等因素。同时,我们也应该意识到,虽然图嵌入在某些任务中能取得较好的效果,但由于其可解释性较差,在一些对模型解释性要求较高的场景中可能并不适用。因此,在使用无监督 ML 处理网络数据时,我们需要综合考虑各种因素,以达到最佳的处理效果。
超级会员免费看

被折叠的 条评论
为什么被折叠?



