开发也能看懂的大模型:GNN

1. 什么是GNN?

图神经网络是一类专门用于处理图结构数据的神经网络。它能有效捕捉节点、边及其局部邻域结构的特征,并生成节点、边或整个图的嵌入表示。

  • 图的组成 :一个图由 节点(nodes/vertices)边(edges) 组成。

    • 节点表示:节点的属性(例如社交网络中的用户信息)。
    • 边表示:边的属性(例如好友关系、权重)。
  • 目标:通过聚合节点及其邻居的信息,实现任务(如节点分类、链路预测、图分类等)。


2. GNN的核心思想

GNN的核心是消息传递机制(Message Passing):

  • 每个节点通过聚合自己及其邻居节点的特征,更新自身特征表示。
  • 这一过程通常分为邻居聚合特征更新两步,循环执行多轮(图卷积层数)。

数学表示:

常见模型:

  • GCN(Graph Convolutional Network) :基于谱图理论的图卷积模型。
  • GAT(Graph Attention Network) :引入注意力机制,赋予邻居节点不同权重。
  • GraphSAGE(Sample and Aggregates) :随机采样部分邻居,提高效率。

3. 大规模GNN的挑战

在处理大规模图(例如含百万节点、十亿边)时,传统GNN面临如下挑战:

  1. 内存限制:存储全图数据及中间计算结果可能超出单机内存容量。
  2. 计算复杂度高:全图邻居特征聚合导致计算瓶颈,尤其是深层GNN。
  3. 邻居爆炸:节点的邻居数随网络规模指数增长,导致计算不可扩展。
  4. 数据存取延迟:访问远程存储或分布式环境下的节点特征可能拖慢训练。

4. 解决方案

分布式训练

将大规模图分片,分布到多台机器上,并行处理:

  • 节点分片:将图的节点划分为多个子集,各子集及其邻居特征分布存储。
  • 边分片:将边划分到多个计算节点,减少存储压力。

邻居采样

采样固定数量的邻居以减少计算量:

  • GraphSAGE采样:随机采样固定数量的邻居。
  • 跳跃采样(K-hop Sampling) :仅采样某些跳数范围内的邻居。
  • 重要性采样:根据边的权重或节点的重要性选择采样。

基于Mini-batch的训练

  • 将全图划分为多个子图,每次仅处理一个子图。
  • 通过子图采样算法(如METIS、GraphSAINT)生成训练用子图。

异步更新

  • 在分布式环境中,允许节点在部分邻居信息未完全更新的情况下继续训练,减少等待时间。

图存储与加速

  • 使用专用的图存储系统(如DGL、PyTorch Geometric、Deep Graph Library)。
  • 加速硬件(如GPU、TPU)结合高效算法优化计算。

5. 应用场景

  • 社交网络分析

    • 推荐系统:预测用户可能感兴趣的内容。
    • 用户分类:根据行为特征进行分群。
  • 知识图谱

    • 实体链接:预测图中缺失的关系或节点。
    • 图补全:填补知识图谱中的空白数据。
  • 生物信息学

    • 药物发现:分析化学分子的图结构。
    • 基因网络:预测基因功能或关联。
  • 金融领域

    • 风险评估:检测金融交易网络中的欺诈行为。
    • 关系挖掘:分析企业间的资金流动图。

大规模图神经网络(Graph Neural Network, GNN)是近年来在图结构数据分析领域中的重要技术,尤其适用于社交网络、知识图谱、生物网络等场景。以下是对大规模GNN的简要讲解:


6. 优缺点总结

优点

  • 能处理图结构数据,捕获节点间复杂关系。
  • 灵活适应多种任务(节点分类、链路预测、图分类等)。
  • 引入分布式和采样技术后,可扩展至大规模数据。

缺点

  • 深度GNN可能导致过平滑问题(节点特征趋于一致)。
  • 处理大规模图时仍需较高硬件要求。
  • 对稀疏图或动态图的处理仍有优化空间。

GCN(图卷积网络)

GCN(图卷积网络) 是 GNN 的一个具体模型。

GCN 是基于卷积操作设计的图神经网络模型,灵感来源于传统的卷积神经网络(CNN),但它适用于图结构数据。

GCN 的主要特点是:

  • 通过图的邻接矩阵聚合邻居节点的特征。
  • 引入了归一化邻接矩阵,避免直接使用原始邻接矩阵可能导致的特征爆炸问题。
  • 使用了简单的线性变换和非线性激活函数。

GCN 的核心公式为:

GCN 常用于节点分类和图嵌入任务。

GCN 和 GNN 的异同

特性 GNN GCN
范围 广义框架,包含多种模型 GNN 的一种具体实现
核心机制 消息传递(Message Passing) 图卷积(基于归一化邻接矩阵的聚合)
应用场景 所有图任务:节点分类、链路预测等 常用于节点分类和嵌入学习
算法多样性 可以设计不同的消息传递和聚合方式 固定使用卷积和归一化邻接矩阵

案例分析:Karate Club 数据集 节点分类

Karate Club 数据集是图网络研究中最常用的一个小型数据集,用于测试图算法的效果。它由美国社会学家 Wayne W. Zachary 在 1977 年研究的空手道俱乐部成员的社交关系网络构成,因其结构简单且数据明确,常被用作图神经网络(GNN)入门案例.

数据集简介

  • 节点(Nodes)

    • 图中有 34 个节点,每个节点代表俱乐部的一名成员。
  • 边(Edges)

    • 图中有 78 条边,每条边表示两名成员之间的友谊关系。
  • 分组(Community Memberships)

    • 俱乐部因领导层意见分歧分裂为两个派别:

      1. 支持俱乐部管理员("Mr. Hi")的成员。
      2. 支持教练("Officer")的成员。
    • 数据集中每个节点带有其派别标签,二分类问题是典型任务。

  • 任务

    • 根据成员之间的关系预测每个节点的派别(即社区分类)。

数据结构

  • 网络结构

    • 节点和边构成无向图。
    • 没有权重的边(即边的权值均为 1)。
  • 标签

    • 每个节点有一个标签(0 或 1),表示其社区归属。

实现步骤

1. 安装必要库

只需要轻量级的 NetworkXNumPy

bash 复制代码
pip install networkx numpy

2. 加载图数据

使用 NetworkX 创建 Karate Club 图:

python 复制代码
import networkx as nx
import numpy as np

# 加载 Karate Club 图
G = nx.karate_club_graph()

# 获取节点数和边数
print("节点数:", G.number_of_nodes())
print("边数:", G.number_of_edges())

# 获取标签 (分类目标)
labels = np.array([G.nodes[i]['club'] == 'Mr. Hi' for i in range(G.number_of_nodes())], dtype=int)

3. 初始化图特征

为每个节点初始化特征向量(可以简单使用单位矩阵):

python 复制代码
# 使用单位矩阵作为初始节点特征,每个节点的特征向量独立
features = np.eye(G.number_of_nodes())

4. 实现 GCN 层

GCN 的核心是消息传递和特征聚合,这里使用邻接矩阵的归一化方式:

python 复制代码
def normalize_adjacency_matrix(A):
    """归一化邻接矩阵"""
    D = np.diag(np.sum(A, axis=1))  # 度矩阵
    D_inv_sqrt = np.linalg.inv(np.sqrt(D))  # D^(-1/2)
    return D_inv_sqrt @ A @ D_inv_sqrt  # A_hat = D^(-1/2) * A * D^(-1/2)

def gcn_layer(A, X, W):
    """GCN 层"""
    A_hat = normalize_adjacency_matrix(A)  # 归一化邻接矩阵
    return np.relu(A_hat @ X @ W)  # A_hat * X * W

5. 两层 GCN 的前向传播

实现两层 GCN 模型:

python 复制代码
# 构造邻接矩阵
A = nx.adjacency_matrix(G).toarray()

# 初始化权重矩阵
np.random.seed(42)  # 固定随机种子
W1 = np.random.rand(G.number_of_nodes(), 4)  # 第一层权重,输出 4 维特征
W2 = np.random.rand(4, 2)  # 第二层权重,分类为 2 类

# 前向传播
hidden = gcn_layer(A, features, W1)  # 第一层
output = gcn_layer(A, hidden, W2)  # 第二层

print("输出特征矩阵维度:", output.shape)  # (34, 2)

6. 分类和评价

使用简单的 softmax 函数分类并评估准确率:

python 复制代码
def softmax(X):
    """Softmax 函数"""
    exp_X = np.exp(X - np.max(X, axis=1, keepdims=True))  # 防止溢出
    return exp_X / np.sum(exp_X, axis=1, keepdims=True)

# 预测
predictions = np.argmax(softmax(output), axis=1)

# 计算准确率
accuracy = np.mean(predictions == labels)
print("分类准确率:", accuracy)

结果

附录:完整代码:

python 复制代码
import networkx as nx
import numpy as np

# 创建 Karate Club 图
G = nx.karate_club_graph()

# 获取标签
labels = np.array([G.nodes[i]['club'] == 'Mr. Hi' for i in range(G.number_of_nodes())], dtype=int)

# 初始化特征
features = np.eye(G.number_of_nodes())

# 构造邻接矩阵
A = nx.adjacency_matrix(G).toarray()

# 手动实现 ReLU 激活函数
def relu(X):
    return np.maximum(0, X)

# 归一化邻接矩阵
def normalize_adjacency_matrix(A):
    D = np.diag(np.sum(A, axis=1))  # 度矩阵
    D_inv_sqrt = np.linalg.inv(np.sqrt(D))  # D^(-1/2)
    return D_inv_sqrt @ A @ D_inv_sqrt  # A_hat = D^(-1/2) * A * D^(-1/2)

# GCN 层
def gcn_layer(A, X, W):
    A_hat = normalize_adjacency_matrix(A)
    return relu(A_hat @ X @ W)

# 初始化权重
np.random.seed(42)
W1 = np.random.rand(G.number_of_nodes(), 4)  # 第一层权重
W2 = np.random.rand(4, 2)  # 第二层权重

# 两层 GCN 前向传播
hidden = gcn_layer(A, features, W1)
output = gcn_layer(A, hidden, W2)

# 分类预测
def softmax(X):
    exp_X = np.exp(X - np.max(X, axis=1, keepdims=True))
    return exp_X / np.sum(exp_X, axis=1, keepdims=True)

# 预测结果
predictions = np.argmax(softmax(output), axis=1)

# 计算准确率
accuracy = np.mean(predictions == labels)
print("分类准确率:", accuracy)
相关推荐
九圣残炎3 分钟前
【从零开始的LeetCode-算法】3227. 字符串元音游戏
java·算法·leetcode
凡人的AI工具箱22 分钟前
40分钟学 Go 语言高并发:RPC服务开发实战
开发语言·后端·性能优化·rpc·golang
梁小憨憨29 分钟前
变分推断(Variational Inference)
人工智能·算法·机器学习
Mercury_@2230 分钟前
项目集成篇:springboot集成redistemple实现自定义缓存,并且可以设置过期时间
后端·缓存
就爱学编程36 分钟前
重生之我在异世界学编程之C语言:选择结构与循环结构篇
c语言·数据结构·算法
一只大侠42 分钟前
输入一串字符,以“?”结束。统计其中字母个数,数字个数,其它符号个数。:JAVA
java·开发语言·算法
以后不吃煲仔饭43 分钟前
面试小札:线程池
java·后端·面试
winstongit1 小时前
捷联惯导原理和算法预备知识
算法·机器人
爱上语文1 小时前
请求响应:常见参数接收及封装(数组集合参数及日期参数)
java·开发语言·spring boot·后端
程序猿进阶1 小时前
Tomcat 都有哪些核心组件
java·开发语言·后端·面试·性能优化·tomcat·firefox