28、图嵌入实战

图嵌入实战

1. 图嵌入简介

图嵌入可以简单理解为将复杂网络解构为更适合机器学习任务的格式,也就是把复杂的数据结构转化为相对简单的数据结构。在后续内容中,我们会使用一些无监督机器学习模型创建图嵌入,观察具有相似嵌入的节点,再结合监督机器学习预测“是否为革命者”,就像之前的“找出革命者”游戏。

我们会快速介绍几种不同的模型,为节省时间,会提供文档链接和简单总结,仅做简单比较。需要注意的是,使用机器学习时绝不能盲目,要阅读文档和相关文章,了解模型工作原理。也可以尝试不同模型,观察其表现。

2. 可视化辅助函数

为了可视化后续的嵌入,我们需要以下辅助函数:

def draw_clustering(embeddings, nodes, title):
    import plotly.express as px
    from sklearn.decomposition import PCA
    embed_df = pd.DataFrame(embeddings)
    # dim reduction, two features; solely for visualization
    model = PCA(n_components=2)
    X_features = model.fit_transform(embed_df)
    embed_df = pd.DataFrame(X_features)
    embed_df.index = nodes
    embed_df.columns = ['x', 'y']
    fig = px.scatter(embed_df, x='x', y='y', text=embed_df.index)
    fig.update_traces(textposition='top center')
    fig.update_layout(height=800, title_text=title, font_size=11)
    return fig.show()

这里需要说明几点:
- draw_clustering 函数使用 plotly 创建交互式散点图,可缩放并交互查看节点。需要安装 plotly ,可使用 pip install plotly 进行安装。
- 使用主成分分析(PCA)将嵌入降为二维,仅用于可视化。PCA 是无监督学习,可用于降维。这样做是为了展示不同嵌入模型的表现,但不建议在创建嵌入后进行 PCA,这里仅用于可视化。

3. FEATHER 算法
  • 算法介绍 :FEATHER 算法可在 这里 了解详情。它是“FEATHER - N”的实现,该算法使用节点特征的特征函数和随机游走权重来描述节点邻域。它声称能创建高质量的图表示,有效进行迁移学习,并且能很好地扩展到大型网络,可创建节点嵌入。
  • 操作步骤
    1. 创建嵌入
from karateclub.node_embedding.attributed.feathernode import FeatherNode
model = FeatherNode()
model.fit(G, clf_df)
embeddings = model.get_embedding()

这里不仅传入了图 G ,还传入了手工创建的训练数据 clf_df ,这与其他模型不同,能让模型基于更多上下文数据学习网络信息。
2. 可视化嵌入

title = 'Les Miserables Character Similarity (FeatherNode)'
draw_clustering(embeddings, nodes, title)

通过可视化可以看到一些节点聚集在一起,例如放大左下角的聚类,能看到 Feuilly 和 Prouvaire 相邻。
3. 检查节点的自我网络

node = 'Feuilly'
G_ego = nx.ego_graph(G_named, node)
draw_graph(G_ego, show_names=True, node_size=3)

node = 'Prouvaire'
G_ego = nx.ego_graph(G_named, node)
draw_graph(G_ego, show_names=True, node_size=3)

观察发现,它们都在彼此的自我网络和社区中,节点连接紧密。
4. 查看其他节点 :检查 MotherInnocent 和 MmeMagloire 的自我网络,发现它们的自我网络较小,这些相似性被 FEATHER 捕捉并转化为嵌入。
5. 查看嵌入数据

eb_df = pd.DataFrame(embeddings, index=nodes)
eb_df['label'] = clf_df['label']
eb_df.head(10)

图被转换为 1750 个嵌入维度,这对于小型网络来说数据量较大。
6. 分类任务

from sklearn.model_selection import train_test_split
X_cols = [c for c in eb_df.columns if c != 'label']
X = eb_df[X_cols]
y = eb_df['label']
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1337, test_size=0.3)

from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(random_state=1337)
clf.fit(X_train, y_train)
train_acc = clf.score(X_train, y_train)
test_acc = clf.score(X_test, y_test)
print('train accuracy: {}\ntest accuracy: {}'.format(train_acc, test_acc))

使用 FEATHER 嵌入作为训练数据,模型在未见过的数据上能 100% 正确识别革命者,但对于 100% 的准确率要保持怀疑,可能存在数据泄露等问题。同时,使用这些嵌入会使模型失去可解释性。

4. NodeSketch 算法
  • 算法介绍 :NodeSketch 算法可在 这里 了解详情。它是“NodeSketch”的实现,通过对图的自环增强邻接矩阵进行草图绘制来输出低阶节点嵌入,然后递归生成 k 阶节点嵌入。
  • 操作步骤
    1. 创建嵌入并可视化
from karateclub.node_embedding.neighbourhood.nodesketch import NodeSketch
model = NodeSketch()
model.fit(G)
embeddings = model.get_embedding()
title = 'Les Miserables Character Similarity (NodeSketch)'
draw_clustering(embeddings, nodes, title)
2. **查看相似节点的自我网络**:
node = 'Eponine'
G_ego = nx.ego_graph(G_named, node)
draw_graph(G_ego, show_names=True, node_size=3)

node = 'Brujon'
G_ego = nx.ego_graph(G_named, node)
draw_graph(G_ego, show_names=True, node_size=3)

观察发现,虽然它们的自我网络看起来不同,但节点连接数相近,且属于同一个连接良好的社区。
3. 查看嵌入数据

eb_df = pd.DataFrame(embeddings, index=nodes)
eb_df['label'] = clf_df['label']
eb_df.head(10)

生成的嵌入有 32 个特征,比 FEATHER 生成的数据集简单,且嵌入值为整数。
4. 分类任务

X_cols = [c for c in eb_df.columns if c != 'label']
X = eb_df[X_cols]
y = eb_df['label']
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1337, test_size=0.3)
clf = RandomForestClassifier(random_state=1337)
clf.fit(X_train, y_train)
train_acc = clf.score(X_train, y_train)
test_acc = clf.score(X_test, y_test)
print('train accuracy: {}\ntest accuracy: {}'.format(train_acc, test_acc))

模型在训练数据上准确率为 98%,测试数据上为 100%,同样要对 100% 的准确率保持怀疑。使用这些嵌入也会使模型成为黑盒模型,失去可解释性。

5. 模型对比表格
算法 嵌入维度 训练准确率 测试准确率 可解释性
FEATHER 1750 0.9811320754716981 1.0
NodeSketch 32 0.9811320754716981 1.0
6. 流程图
graph LR
    A[开始] --> B[选择算法]
    B --> C{FEATHER}
    B --> D{NodeSketch}
    C --> E[创建嵌入]
    C --> F[可视化嵌入]
    C --> G[检查自我网络]
    C --> H[分类任务]
    D --> I[创建嵌入]
    D --> J[可视化嵌入]
    D --> K[检查自我网络]
    D --> L[分类任务]
    H --> M[结束]
    L --> M

图嵌入实战

7. RandNE 算法
  • 算法介绍 :RandNE 号称对“十亿级网络嵌入”有用,意味着它适用于拥有数十亿节点或边的网络,对大型现实世界网络有应用价值。可在 这里 查看文档。它是“RandNE”的实现,使用基于归一化邻接矩阵的平滑方法对正交化的随机正态生成的基础节点嵌入矩阵进行处理。
  • 操作步骤
    1. 生成嵌入并可视化
from karateclub.node_embedding.neighbourhood.randne import RandNE
model = RandNE()
model.fit(G)
embeddings = model.get_embedding()
title = 'Les Miserables Character Similarity (RandNE)'
draw_clustering(embeddings, nodes, title)

从输出的散点图可以看出,它与 FEATHER 和 NodeSketch 的结果差异很大。
2. 查看相似节点的自我网络

node = 'Marius'
G_ego = nx.ego_graph(G_named, node)
draw_graph(G_ego, show_names=True, node_size=3)

node = 'MotherPlutarch'
G_ego = nx.ego_graph(G_named, node)
draw_graph(G_ego, show_names=True, node_size=3)

Marius 是连接良好的节点,而 MotherPlutarch 只有一条边与其他节点相连,二者差异很大,但嵌入却显示它们相似。不过,这可能是散点图可视化时 PCA 步骤的影响,可进一步查看其他相似节点。
3. 查看嵌入数据

eb_df = pd.DataFrame(embeddings, index=nodes)
eb_df['label'] = clf_df['label']
eb_df.head(10)

生成的嵌入有 77 个特征,比 FEATHER 默认创建的嵌入简单,相比之下,NodeSketch 创建了 32 个特征。
4. 分类任务

X_cols = [c for c in eb_df.columns if c != 'label']
X = eb_df[X_cols]
y = eb_df['label']
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1337, test_size=0.3)
clf = RandomForestClassifier(random_state=1337)
clf.fit(X_train, y_train)
train_acc = clf.score(X_train, y_train)
test_acc = clf.score(X_test, y_test)
print('train accuracy: {}\ntest accuracy: {}'.format(train_acc, test_acc))

模型在训练集上准确率为 98.1%,测试集上为 91.7%,这比 FEATHER 和 NodeSketch 嵌入的效果差,但可能是偶然情况。同样,检查嵌入的特征重要性时,无法解释结果。

8. 三种算法总结表格
算法 嵌入维度 训练准确率 测试准确率 可解释性 适用场景
FEATHER 1750 0.9811320754716981 1.0 可结合额外训练数据,对数据信息挖掘有需求的场景
NodeSketch 32 0.9811320754716981 1.0 需要简单嵌入表示的场景
RandNE 77 0.9811320754716981 0.9166666666666666 大型网络嵌入场景
9. 完整流程图
graph LR
    A[开始] --> B[选择算法]
    B --> C{FEATHER}
    B --> D{NodeSketch}
    B --> E{RandNE}
    C --> F[创建嵌入]
    C --> G[可视化嵌入]
    C --> H[检查自我网络]
    C --> I[分类任务]
    D --> J[创建嵌入]
    D --> K[可视化嵌入]
    D --> L[检查自我网络]
    D --> M[分类任务]
    E --> N[创建嵌入]
    E --> O[可视化嵌入]
    E --> P[检查自我网络]
    E --> Q[分类任务]
    I --> R[结束]
    M --> R
    Q --> R
10. 注意事项与建议
  • 模型准确率 :在实际应用中,对于准确率达到 100% 的模型要保持高度怀疑,因为这可能隐藏着数据泄露等深层次问题。需要对模型进行充分验证,不能仅仅依据高准确率就盲目信任模型。
  • 可解释性 :使用图嵌入进行机器学习时,很多模型会变成黑盒模型,失去可解释性。如果对模型的可解释性有要求,需要谨慎选择算法或寻找其他方法来解释模型结果。
  • 实验探索 :建议对感兴趣的模型进行深入研究和实验,尝试不同的参数设置和数据处理方法,以找到最适合特定任务的模型和配置。

通过对 FEATHER、NodeSketch 和 RandNE 三种图嵌入算法的介绍和实验,我们了解了它们的特点、操作步骤以及在分类任务中的表现。在实际应用中,可以根据具体的需求和场景选择合适的算法,同时要注意模型的准确率和可解释性问题。希望这些内容能帮助大家更好地理解和应用图嵌入技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值