循环神经网络与图神经网络的联系:从序列到图的学习

循环神经网络与图神经网络的联系:从序列到图的学习

循环神经网络(RNN)和图神经网络(GNN)虽然在处理的数据类型上有所不同,但在核心思想和数学原理上有着深刻的联系[4]。理解这种联系不仅有助于我们更好地掌握图神经网络,还能为设计新的网络架构提供启发。

循环神经网络基础

RNN的基本概念

循环神经网络被称为”循环”,因为它们对序列的每个元素执行相同的任务,输出取决于先前的计算。RNN有一个”记忆”,可以捕获到目前为止计算的信息。

RNN结构图

符号定义

  • $X_t$:$t$时刻输入层的输入
  • $S_t$:$t$时刻的隐藏层输出($S_0$通常初始化为全0)
  • $O_t$:$t$时刻输出层的输出
  • $W_{in}$:输入权重
  • $W_s$:隐藏层权重
  • $W_{out}$:输出权重

RNN的数学定义

隐藏层输出: \(S_t = f(W_{in} \cdot X_t + W_s \cdot S_{t-1} + b_{hidden})\)

输出层输出: \(O_t = g(W_{out} \cdot S_t + b_{out})\)

RNN的不同模式

RNN模式图

RNN存在多种输入输出模式:

  • One-to-One:一对一映射
  • One-to-Many:一对多映射(如图像描述生成)
  • Many-to-One:多对一映射(如情感分析)
  • Many-to-Many:多对多映射(如机器翻译)
graph LR
    X0["X₀"] --> S0["隐藏状态 S₀"] --> O0["O₀"]
    X1["X₁"] --> S1["S₁"] --> O1["O₁"]
    X2["X₂"] --> S2["S₂"] --> O2["O₂"]
    S0 -.->|"Wₛ"| S1 -.->|"Wₛ"| S2

RNN的核心问题:梯度消失与梯度爆炸

问题分析

RNN在处理长序列时面临严重的梯度消失和梯度爆炸问题。让我们从数学角度分析这个问题:

假设RNN的损失函数为 $L = \sum_{t=1}^T L_t$,其中$t$为模型的时间步。对模型求偏导:

输出层权重: \(\frac{\partial L_3}{\partial W_{out}} = \frac{\partial L_3}{\partial O_3}\frac{\partial O_3}{\partial W_{out}}\)

输入层权重: \(\frac{\partial L_3}{\partial W_{in}} = \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial W_{in}} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial W_{in}} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial S_1} \frac{\partial S_1}{\partial W_{in}}\)

隐藏层权重: \(\frac{\partial L_3}{\partial W_{s}} = \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial W_s} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial W_s} + \frac{\partial L_3}{\partial O_3} \frac{\partial O_3}{\partial S_3} \frac{\partial S_3}{\partial S_2} \frac{\partial S_2}{\partial S_1} \frac{\partial S_1}{\partial W_s}\)

梯度消失的数学分析

对于任意时刻的$W_{in}$和$W_s$,偏导公式为:

\[\frac{\partial L_t}{\partial W_{[in/s]}} = \sum_{k=0}^t \frac{\partial L_t}{\partial O_t} \frac{\partial O_t}{\partial S_t}\left(\prod_{j=k+1}^t \frac{\partial S_j}{\partial S_{j-1}}\right) \frac{\partial S_k}{\partial W_{[in/s]}}\]

如果加上激活函数 $S_j = \tanh(W_x W_j + W_s S_{j-1} + b_1)$,得到:

\[\prod_{j=k+1}^t \frac{\partial S_j}{\partial S_{j-1}} = \prod_{j=k+1}^t \tanh' W_s\]

由于 $\tanh’ \leq 1$,当$W_s < 1$时,连乘结果趋于0(梯度消失);当$W_s > 1$时,连乘结果趋于无穷(梯度爆炸)。[1]

从RNN到GNN的演进

消息传递的统一框架

RNN和GNN都可以用消息传递的框架来理解:

RNN的消息传递

  • 每个时间步,当前状态接收来自前一个时间步的信息
  • 信息传递是线性的(时间序列)
  • 状态更新:$S_t = f(X_t, S_{t-1})$

GNN的消息传递

  • 每个节点,当前节点接收来自邻居节点的信息
  • 信息传递是图结构的(空间关系)
  • 状态更新:$h_v^{(l+1)} = f(h_v^{(l)}, {h_u^{(l)} : u \in \mathcal{N}(v)})$[5]

图结构作为序列的推广

我们可以将图结构看作是序列的推广:

  1. 序列:每个元素只与前一个元素相连
  2. 树结构:每个节点有多个子节点
  3. 图结构:每个节点可以与多个邻居节点相连

这种推广使得GNN能够处理更复杂的结构化数据。

graph LR
    subgraph SEQ["序列 RNN"]
        A["A"] --> B["B"] --> C["C"] --> D["D"]
    end
    SEQ -->|"推广"| TREE["树结构<br/>Root→A→C,D<br/>Root→B"]
    TREE -->|"推广"| GRAPH["图 GNN<br/>任意节点连接"]

图神经网络中的梯度问题

过平滑问题

GNN面临类似RNN梯度消失的问题,称为”过平滑”(Over-smoothing):

现象:随着层数增加,所有节点的表示趋于相同 原因:消息传递过程中,节点信息被过度平均化 数学表达:$\lim_{l \to \infty} h_v^{(l)} = c$,其中$c$是常数[2]

解决方案

残差连接

\(h_v^{(l+1)} = h_v^{(l)} + \text{GNN}(h_v^{(l)}, \{h_u^{(l)} : u \in \mathcal{N}(v)\})\)

跳跃连接

\(h_v^{(l+1)} = \text{Concat}(h_v^{(0)}, h_v^{(1)}, \ldots, h_v^{(l)})\)

注意力机制

为不同的邻居节点分配不同的权重,避免信息被过度平均[3]

实际应用中的联系

序列到图的转换

许多实际问题可以同时用序列和图来建模:

文本处理

  • 序列视角:字符序列 → RNN/LSTM
  • 图视角:句法依存树 → GNN

时间序列

  • 序列视角:时间点序列 → RNN
  • 图视角:时间点间的因果关系图 → GNN

混合架构

现代深度学习模型经常结合RNN和GNN:

图序列网络

  • 用RNN处理时间维度
  • 用GNN处理空间维度
  • 适用于动态图数据

注意力机制的统一

  • RNN中的自注意力机制
  • GNN中的图注意力机制
  • 都基于查询-键-值框架

代码实现对比

RNN实现示例

import torch
import torch.nn as nn

class SimpleRNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleRNN, self).__init__()
        self.hidden_size = hidden_size
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
    
    def forward(self, x):
        # x shape: (batch_size, seq_len, input_size)
        output, _ = self.rnn(x)
        # 取最后一个时间步的输出
        output = self.fc(output[:, -1, :])
        return output

GNN实现示例

import torch
import torch.nn as nn
from torch_geometric.nn import GCNConv

class SimpleGNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleGNN, self).__init__()
        self.conv1 = GCNConv(input_size, hidden_size)
        self.conv2 = GCNConv(hidden_size, output_size)
        self.dropout = nn.Dropout(0.5)
    
    def forward(self, x, edge_index):
        # x shape: (num_nodes, input_size)
        # edge_index shape: (2, num_edges)
        x = torch.relu(self.conv1(x, edge_index))
        x = self.dropout(x)
        x = self.conv2(x, edge_index)
        return x

总结

RNN和GNN虽然在处理的数据类型上不同,但在核心思想上有着深刻的联系:

  1. 消息传递:都基于信息在结构中的传播
  2. 状态更新:都通过聚合信息来更新状态
  3. 梯度问题:都面临信息传播中的衰减问题
  4. 解决方案:都可以通过残差连接、注意力机制等方法解决

理解这种联系有助于我们:

  • 更好地掌握图神经网络的核心思想
  • 设计新的网络架构
  • 解决实际应用中的问题
  • 理解深度学习模型的统一性

在下一篇文章中,我们将深入探讨图卷积网络(GCN)的具体实现,包括数学原理和PyTorch代码实现。


参考文献

  1. Hochreiter, S., & Schmidhuber, J. Long Short-Term Memory. Neural Computation, 1997. DOI:10.1162/neco.1997.9.8.1735
  2. Kipf, T. N., & Welling, M. Semi-Supervised Classification with Graph Convolutional Networks. ICLR, 2017. arXiv:1609.02907
  3. Veličković, P., Cucurull, G., Casanova, A., Romero, A., Liò, P., & Bengio, Y. Graph Attention Networks. ICLR, 2018. arXiv:1710.10903
  4. Wu, Z., Pan, S., Chen, F., Long, G., Zhang, C., & Yu, P. S. A Comprehensive Survey on Graph Neural Networks. IEEE Transactions on Neural Networks and Learning Systems, 2020. arXiv:1901.00596
  5. Gilmer, J., Schoenholz, S. S., Riley, P. F., Vinyals, O., & Dahl, G. E. Neural Message Passing for Quantum Chemistry. ICML, 2017. arXiv:1704.01212
文章目录