动态图神经网络
如何对GAT的权重($W$)和注意力参数($a$)进行增量更新(邻居偶尔变化)
1. 核心思想
- 局部更新:邻居变化的节点及其直接邻域的权重和注意力参数需要调整,其他部分冻结。
- 梯度隔离:反向传播时,仅计算受影响节点的梯度,避免全局参数震荡。
2. 数学实现步骤
(1) 识别受影响的节点
设邻居变化后的新邻接矩阵为 $\tilde{A}$,原邻接矩阵为 $A$,受影响节点集合 $\mathcal{V}_{\text{affected}}$ 包括:
- 新增或删除边的两端节点(直接受影响)。
- 这些节点的1-hop邻居(间接受影响,根据GAT层数决定)。
(2) 损失函数局部化
仅对 $\mathcal{V}_{\text{affected}}$ 中的节点计算损失:
$$ \mathcal{L}_{\text{incremental}} = \sum_{i \in \mathcal{V}_{\text{affected}}} \ell(y_i, \hat{y}_i) $$ 其中 $\ell$ 为交叉熵损失,$y_i$ 为标签,$\hat{y}_i$ 为模型输出。(3) 梯度计算与参数更新
-
梯度掩码:
反向传播时,非受影响节点的梯度强制置零:
$$ \nabla_{W,a} \mathcal{L}{\text{incremental}} = \left{ \begin{array}{ll} \nabla{W,a} \ell(y_i, \hat{y}i) & \text{if } i \in \mathcal{V}{\text{affected}} \ 0 & \text{otherwise} \end{array} \right. $$ -
参数更新:
使用优化器(如Adam)仅更新有梯度的参数:
$$ W \leftarrow W - \eta \nabla_W \mathcal{L}{\text{incremental}}, \quad a \leftarrow a - \eta \nabla_a \mathcal{L}{\text{incremental}} $$ 其中 $\eta$ 为较小的学习率(防止过拟合)。
(4) 注意力权重的动态适应
GAT的注意力机制会自动适应新邻居:
$$ \alpha_{ij} = \text{softmax}\left(\text{LeakyReLU}\left(a^T [W h_i \| W h_j]\right)\right) $$ 由于 $W$ 和 $a$ 已局部更新,新邻居 $j \in \tilde{\mathcal{N}}(i)$ 的权重 $\alpha_{ij}$ 会重新计算。3. 适用场景
- 低频变化:如社交网络每天新增少量边、论文引用网络月度更新。
- 局部变化:每次变化仅影响图中少量节点(<10%)。
若邻居高频变化(如秒级更新),需改用动态GNN(如TGAT)或时间序列建模。
EvolveGCN
EvolveGCN-H
1. EvolveGCN-H核心思想
EvolveGCN-H 通过 GRU(门控循环单元) 动态更新 GCN 每一层的权重矩阵 $W_t^{(l)}$,将权重矩阵视为 GRU 的 隐藏状态,并利用当前时间步的 节点嵌入(特征) 作为输入来驱动演化。
关键特点:
- 输入依赖:利用节点嵌入 $H_t^{(l)}$ 指导权重更新。
- 时序建模:通过 GRU 隐式捕捉参数演化的长期依赖。
2. 动态更新流程(以第 $l$ 层为例)
输入:
- 当前节点嵌入矩阵 $H_t^{(l)} \in \mathbb{R}^{n \times d}$:
- 上一时间步的权重矩阵 $W_{t-1}^{(l)} \in \mathbb{R}^{d \times d'}$:
- 邻接矩阵 $A_t \in \mathbb{R}^{n \times n}$:
输出:
- 更新后的权重矩阵 $W_t^{(l)} \in \mathbb{R}^{d \times d'}$。
- 下一层节点嵌入 $H_t^{(l+1)} \in \mathbb{R}^{n \times d'}$。
3. 动态更新示意图
Time Step t-1 Time Step t
+-------------------+ +-------------------+
| Weight Matrix | | Weight Matrix |
| W_{t-1}^{(l)} | --(GRU更新)--> | W_t^{(l)} |
+-------------------+ +-------------------+
^ ^
| |
+-------------------+ +-------------------+
| Node Embeddings | | Node Embeddings |
| H_t^{(l)} | --(GCN计算)--> | H_t^{(l+1)} |
+-------------------+ +-------------------+
^ ^
| |
+-------------------+ +-------------------+
| 邻接矩阵 A_t | | 邻接矩阵 A_{t+1} |
| (显式输入) | | (下一时间步输入) |
+-------------------+ +-------------------+
$$
\begin{align*}
W_t^{(l)} &<= H_t^{(l)} + W_{t-1}^{(l)} \\
H_t^{(l+1)} &<= A_t + H_t^{(l)} + W_t^{(l)}
\end{align*}
$$
4. 具体步骤分解
步骤 1:节点嵌入聚合(Summarize)
由于 GRU 的输入需与隐藏状态 $W_{t-1}^{(l)}$ 的列维度匹配(即 $d'$),需将 $H_t^{(l)}$ 从 $n \times d$ 压缩为 $d' \times d$ :
$$ Z_t = \text{Summarize}(H_t^{(l)}, d') $$将会舍弃部分节点
实现方式(论文方案):
-
计算得分:
$$ y_t = H_t^{(l)} p / |p| \quad (p \in \mathbb{R}^d \text{为可学习参数}) $$ 学一个“打分器”参数 $p$,$H_t^{(l)} p$相当于对每个节点的嵌入向量和 $p$做点积,得到一个分数。比如在社交网络中,$p$ 可能代表“活跃度”,得分高的用户更活跃。 -
选取 Top-$d'$ 个节点(按 $y_t$ 排序),加权求和:
$$ Z_t = [H_t^{(l)} \circ \tanh(y_t)]_{\text{top-}d'} \quad (\circ \text{为逐元素乘}) $$- 输出 $Z_t \in \mathbb{R}^{d' \times d}$。
举个例子
假设:
-
有3个节点($n=3$),嵌入维度 $d=2$,选Top-2个节点($d'=2$)。
-
节点嵌入:
$$ H_t^{(l)} = \begin{bmatrix} 1 & 0.5 \ 0.3 & 2 \ -1 & 1 \end{bmatrix}, \quad p = [1, 0] $$($p$ 只关注嵌入的第一维,比如“用户发帖数量”)
-
计算分数:
$$ y_t = H_t^{(l)} p = [1 \cdot 1 + 0.5 \cdot 0, \ 0.3 \cdot 1 + 2 \cdot 0, \ -1 \cdot 1 + 1 \cdot 0] = [1, 0.3, -1] $$Top-2节点是第1、第2个节点(分数1和0.3)。
-
加权聚合:
$$ Z_t = \begin{bmatrix} [1, 0.5] \circ \tanh(1) \ [0.3, 2] \circ \tanh(0.3) \end{bmatrix} = \begin{bmatrix} 0.76 & 0.38 \ 0.09 & 0.58 \end{bmatrix} $$ (假设 $\tanh(1) \approx 0.76$, $\tanh(0.3) \approx 0.29$) -
输出:$Z_t$ 是 $2 \times 2$ 矩阵,可以直接喂给GRU。
$$ W_t^{(l)} = \text{GRU}(Z_t^T, W_{t-1}^{(l)}) $$ 步骤 2:GRU 更新权重矩阵
标准GRU的输入、隐藏、输出都是向量,但这里都是矩阵!
当前时间步的输入:$Z_t^T$
上一时间步的隐藏状态:$W_{t-1}^{(l)}$
更新隐藏状态: $W_t^{(l)}$
标准GRU | 论文中的矩阵GRU | 作用 |
---|---|---|
$W_{xz}$ (输入→更新门) | $W_Z$ | 将当前输入 $Z_t^T$ 映射到更新门。 |
$W_{hz}$ (隐藏→更新门) | $U_Z$ | 将上一隐藏状态 $W_{t-1}^{(l)}$ 映射到更新门。 |
$b_z$ (更新门偏置) | $B_Z$ | 更新门的偏置项。 |
$W_{xh}$ (输入→候选状态) | $W_H$ | 将当前输入 $Z_t^T$ 映射到候选状态。 |
$W_{hh}$ (隐藏→候选状态) | $U_H$ | 将调制后的隐藏状态 $(R_t \circ W_{t-1}^{(l)})$ 映射到候选状态。 |
$b_h$ (候选状态偏置) | $B_H$ | 候选状态的偏置项。 |
GRU 的矩阵形式计算:
-
重置门 $R_t$:控制历史信息的遗忘程度
$$ R_t = \sigma(Z_t^T W_Z + W_{t-1}^{(l)} U_Z + B_Z) $$ -
更新门 $Z_t$:控制新旧状态混合比例
$$ U_t = \sigma(Z_t^T W_U + W_{t-1}^{(l)} U_U + B_U) $$ -
候选状态 $\widetilde{W}_t$:
$$ \widetilde{W}t = \tanh(Z_t^T W_H + (R_t \circ W{t-1}^{(l)}) U_H + B_H) $$ -
最终权重更新:
$$ W_t^{(l)} = (1 - U_t) \circ W_{t-1}^{(l)} + U_t \circ \widetilde{W}_t $$- 输出 $W_t^{(l)} \in \mathbb{R}^{d \times d'}$。
步骤 3:GCN 生成下一层嵌入
使用更新的 $W_t^{(l)}$ 执行标准 GCN 操作:
$$ H_t^{(l+1)} = \sigma\left(\widehat{A}_t H_t^{(l)} W_t^{(l)}\right) $$- $\widehat{A}_t$ 为归一化邻接矩阵(含自环)。
5. 关键设计细节
- 权重共享:
- 所有时间步共享同一 GRU 的参数($W_, U_, B_*$),确保模型尺寸不随时间增长。
- 层独立性:
- 每一层 GCN 的权重矩阵独立演化(不同层有各自的 GRU)。
- 特征与结构的协同:
- 节点嵌入 $H_t^{(l)}$ 既包含特征信息,也隐含历史结构信息(通过多层 GCN 传播),因此 GRU 能间接感知结构变化。
6. 所需提前训练的权重
参数类型 | 符号 | 维度 | 作用 |
---|---|---|---|
GCN 初始权重 | $W_0^{(l)}$ | $\mathbb{R}^{d \times d'}$ | 初始时刻各层 GCN 的初始参数 |
GRU 输入变换矩阵 | $W_Z, W_R, W_H$ | $\mathbb{R}^{d \times d'}$ | 将输入 $Z_t^T$ 映射到门控 |
GRU 隐藏变换矩阵 | $U_Z, U_R, U_H$ | $\mathbb{R}^{d' \times d'}$ | 将 $W_{t-1}^{(l)}$ 映射到门控 |
GRU 偏置项 | $B_Z, B_R, B_H$ | $\mathbb{R}^{d'}$ | 门控和候选状态的偏置 |
Summarize 参数 | $p$ | $\mathbb{R}^d$ | 对特征进行打分,不同层$p$不一样 |
任务相关参数 | 例如 MLP 权重 | 任务相关 | 链接预测、节点分类等输出层 |
EvolveGCN-O
1. 核心思想
EvolveGCN-O 通过 LSTM 直接演化 GCN 的权重矩阵 $W_t^{(l)}$,将权重矩阵视为 LSTM的输出(下一时间步的输入),不依赖节点嵌入。
关键特点:
- 结构驱动:仅通过历史权重 $W_{t-1}^{(l)}$ 预测当前权重,完全基于图结构的动态变化。
- 轻量化:无需处理节点嵌入,计算效率更高。
2. 动态更新流程(第$l$层)
输入:
- 上一时间步权重 $W_{t-1}^{(l)} \in \mathbb{R}^{d \times d'}$
- 邻接矩阵 $A_t \in \mathbb{R}^{n \times n}$(仅用于GCN计算)
输出:
- 更新后权重 $W_t^{(l)} \in \mathbb{R}^{d \times d'}$
- 下一层节点嵌入 $H_t^{(l+1)} \in \mathbb{R}^{n \times d'}$
3.具体步骤分解
步骤1:LSTM更新权重矩阵
矩阵版LSTM计算:
- 遗忘门:
$F_t = \sigma(W_F W_{t-1}^{(l)} + U_F C_{t-1} + B_F)$ - 输入门:
$I_t = \sigma(W_I W_{t-1}^{(l)} + U_I C_{t-1} + B_I)$ - 候选状态:
$\widetilde{C}t = \tanh(W_C W{t-1}^{(l)} + U_C C_{t-1} + B_C)$ - 细胞状态更新:
$C_t = F_t \circ C_{t-1} + I_t \circ \widetilde{C}_t$ - 输出门:
$O_t = \sigma(W_O W_{t-1}^{(l)} + U_O C_{t-1} + B_O)$ - 最终权重输出:
$W_t^{(l)} = O_t \circ \tanh(C_t)$
步骤2:GCN生成下一层嵌入
$H_t^{(l+1)} = \sigma(\widehat{A}_t H_t^{(l)} W_t^{(l)})$
4. 与EvolveGCN-H对比
特性 | EvolveGCN-H | EvolveGCN-O |
---|---|---|
RNN类型 | GRU | LSTM |
演化依据 | 节点嵌入+历史权重 | 仅历史权重 |
计算复杂度 | 高(需Summarize) | 低 |
适用场景 | 特征动态性强(如社交网络) | 结构变化主导(如路由器拓扑) |
TGAT
Bochner定理
Bochner定理为TGAT的连续时间编码提供了理论基础,使其能够将任意时间差映射为可学习的向量表示,从而在动态图中有效捕捉时序依赖。这一方法超越了传统离散编码的局限性,是TGAT的核心创新之一。
时间编码的构造
(1)Bochner 定理的数学形式
根据Bochner定理,任意正定时间核函数 $ f(\Delta t) $ 可表示为:
$$ f(\Delta t) = \mathbb{E}_{\omega \sim \mu} \left[ e^{i \omega \Delta t} \right], $$ 其中 $e^{i \omega \Delta t} = \cos(\omega \Delta t) + i \sin(\omega \Delta t)$ 是复指数函数。(2)蒙特卡洛近似 & 实值化
由于直接计算期望复杂,TGAT 用蒙特卡洛采样近似:
-
从分布 $\mu$ 中采样 $d$ 个频率 $\omega_1, \omega_2, \ldots, \omega_k$。
-
用这些频率构造实值编码(取复指数的实部和虚部,即 $\cos$ 和 $\sin$):
$$ \Phi_d(\Delta t) = \frac{1}{\sqrt d}\bigl[\cos(\omega_1 \Delta t),\sin(\omega_1 \Delta t),\dots,\cos(\omega_d \Delta t),\sin(\omega_d \Delta t)\bigr] $$ 这样就把时间差转成了一个长度为 $2d$ 的实值向量。
例子
取 $d=1$(此时时间编码向量就是二维的),有
$$ \Phi_1(\Delta t)\;=\;\frac{1}{\sqrt1}\bigl[\cos(\omega_1\Delta t),\;\sin(\omega_1\Delta t)\bigr] =\bigl[\cos(\omega_1\Delta t),\;\sin(\omega_1\Delta t)\bigr]. $$例如,若我们令 $\omega_1=1$ 且 $\Delta t = \pi/3$,那么
$$ \Phi_1\bigl(\pi/3\bigr) =\bigl[\cos(\pi/3),\;\sin(\pi/3)\bigr] =\bigl[0.5,\;0.866\!\dots\bigr]. $$所以在这个例子里,二维时间编码就是 $\bigl[0.5,;0.866]$。
为什么这样设计?
- 普通的图神经网络即使有时间戳,也只能把它当作一个离散特征,很难推广到模型没见过的时刻。TGAT通过把相对时间差 $\Delta t$ 映射成一组连续、周期性的函数值 $(\cos(\omega_1 \Delta t),\sin(\omega_1 \Delta t))$,让模型天然具备处理任意实数时间差的能力。
- 用一堆正余弦函数来编码时间,使得时间特征是平滑连续的
- 节点对邻居信息的关注度不仅由节点特征决定,也由时间编码决定。模型可以自动学出“距离现在越近的交互越重要”“一周前的活动强度要比一个月前的活动强度高”之类的规律。
- 可学习性:频率参数
{ωᵢ}
可以通过训练优化(例如让模型自动学习“短期交互”和“长期交互”的不同时间尺度)。
需要维护的数据:
-
全量事件日志(事件流)
整个动态图被表示成一条“事件流”──每一条事件是一个三元组
$$ (u, v, t) $$ 表示节点 $u$ 和节点 $v$ 在时刻 $t$ 上发生了一次交互。训练/推断时,TGAT 会遍历这条有时间戳的边列表,按时间顺序对每个目标节点做消息聚合。 -
每个节点的历史邻居列表
为了快速地找到“截止当前时刻 $t$,某节点 $v$ 最近接触过哪些节点”,TGAT 通常会为每个节点维护一个按时间排序的邻居列表:
$$ \mathit{Nbrs}(v) ;=; [(u_1,t_1),,(u_2,t_2),,\dots] $$ 其中每个 $(u_i, t_i)$ 表示节点 $u_i$ 在时间 $t_i$ 与 $v$ 交互过。这样,给定当前时间 $t$,就可以高效地检索出所有满足 $t_i < t$ 的历史交互。 -
每层的节点隐藏状态
TGAT 是一个多层(multi-layer)注意力网络,在第 $l$ 层它会产生每个节点在各个时间点的隐藏表示
$$ \tilde h_v^{(l)}(t),. $$ 为了在更高层次继续聚合,这些中间表示需要被缓存下来,至少要保存上一次(前一层)计算出的向量,才能和后续的时间编码一起拼接、送入下一层注意力。 -
时间编码的频率参数
TGAT 中的 ${\omega_k}_{k=1}^d$(映射 $\Delta t\mapsto [\cos(\omega_k\Delta t),\sin(\omega_k\Delta t)]$ 用的频率向量)是模型的可学习参数,也需要存储。
工作原理
1.检索时间邻居
从事件流中取出所有在 $t$ 之前与 $v_0$ 有过交互的节点集合以及交互的时间 $t_i$。
$$ \mathcal{N}(v_0; t) = \{ v_i \mid \exists (v_0, v_i, t_i) \in \mathcal{E}, t_i < t \} $$ 实际实现中,TGAT通过以下两种策略避免邻居集合无限膨胀:(1)时间窗口截断
-
仅保留目标时间 $t$ 的最近 $\Delta T$ 时间内的交互节点(例如过去7天的邻居)。
-
数学表达:
$$ \mathcal{N}(v_0; t) = { v_i \mid (v_0, v_i, t_i) \in \mathcal{E}, t - \Delta T \leq t_i < t } $$
(2)邻居采样(Neighborhood Sampling)
- 即使在一个时间窗口内,如果邻居数量过多(例如社交网络中的活跃用户),TGAT会随机采样固定数量的邻居(如最多20个)。
2.准备输入特征+时间编码
在 TGAT 模型中,每一层都需要计算隐藏表示:
在第 $l$ 层里,既要计算目标节点 $v_0$ 在当前时刻 $t$ 的隐藏表示 $\tilde{h}_0^{(l-1)}(t)$,也要计算它的每个邻居 $v_i$ 在各自交互时刻 $t_i$ 的隐藏表示 $\tilde{h}_i^{(l-1)}(t_i)$。
- 若 $l=1$,则将原始静态特征 $x_i$ 作为第 0 层隐藏表示 $\tilde h_i^{(0)}(t_i)$;
- 若 $l>1$,则使用第 $(l-1)$ 层计算出的隐藏表示 $\tilde h_i^{(l-1)}(t_i)$。
对每个邻居 $v_i$ 计算相对时间差 $\Delta t_i = t - t_i$,再通过
得到长度为 $2d$ 的时间编码向量。对目标节点自身,使用 $\Delta t=0$ 的时间编码。
$$ Z(t) = \begin{bmatrix} \tilde h_0^{(l-1)}(t)\,\|\,\Phi_d(0)\\ \tilde h_1^{(l-1)}(t_1)\,\|\,\Phi_d(\Delta t_1)\\ \;\;\vdots\\ \tilde h_N^{(l-1)}(t_N)\,\|\,\Phi_d(\Delta t_N) \end{bmatrix} $$ 3.拼接构建"实体—时间"矩阵
其中 $\Delta t_i=t-t_i$ ,这里 $v_0$ 一共有 $N$ 个节点。可能存在同一时间有多个交互的节点。
4. 线性映射到 Query/Key/Value
分别用三组可学习的线性变换把 $Z(t)$ 投影出
$$ Q = Z(t)W^Q,\quad K = Z(t)W^K,\quad V = Z(t)W^V $$ 其中 $Q$ 取第一行(目标节点),$K,V$ 取其余行。5.计算注意力权重
对每个邻居 $i$ 计算
$$ \alpha_i \;=\;\frac{\exp\bigl(Q^\top K_i\bigr)}{\sum_j\exp\bigl(Q^\top K_j\bigr)}\,, $$ 这样就能在同一时刻、同一节点间对「谁更重要」自动打分。$$ h^{(l)}(t)\;=\;\sum_{i\in N(v_0;t)}\alpha_i\,V_i\quad\in\mathbb{R}^{d_h}. $$ 6.加权求和生成聚合向量
7.与目标节点静态特征融合并通过 FFN
把聚合向量 $h^{(l)}(t)$ 和目标节点的原始特征 $x_0$ 拼接,送入两层前馈网络:
$$ \tilde h_0^{(l)}(t) = \mathrm{FFN}\bigl(h^{(l)}(t)\,\|\,x_0\bigr) = \mathrm{ReLU}\Bigl(\bigl[h^{(l)}(t)\parallel x_0\bigr] W_0^{(l)} + b_0^{(l)}\Bigr) W_1^{(l)} + b_1^{(l)} $$ 这样就得到了第 $l$ 层节点 $v_0$ 在时刻 $t$ 的最终输出表示。FFN 并不是只在最后一层使用,而是在每一层注意力聚合后都要执行,以产生该层的节点时刻表示。
8.多头与多层堆叠
- 如果使用多头注意力,则在步骤 4–6 中并行做 $k$ 组不同投影,得出 ${h^{(l,i)}(t)}_{i=1}^k$,再将它们拼接后送入 FFN;
- 堆叠 $L$ 层上述流程,就能把多跳($L$ 跳)邻居信息聚合进来。
总结:每个节点,动态融合节点自身及其邻居在不同时间点的嵌入,其中这些嵌入都显式编码了时间信息。
不同层之间的嵌入维度可以不同,但同一层内所有时间步的嵌入维度必须保持一致。
举例
假设目标节点 $v_0$ 在时间 $t=10$ 需要聚合历史邻居,其中:
$t=10$时$v_0$的特征:$\tilde{h}_0(t=10)=[0.1, 0.2, 0.3, 0.4, 0.5]$
-
在时间 $t_1=8$,$v_0$ 与邻居 ${v_{1}, v_{2}}$ 交互。
-
$v_1$ 的特征:$\tilde{h}_1(t=8) = [0.6, 0.7, 0.8, 0.9, 1.0]$
-
$v_2$ 的特征:$\tilde{h}_2(t=8) = [0.2, 0.3, 0.4, 0.5, 0.6]$
-
-
在时间 $t_2=5$,$v_0$ 与邻居 ${v_{3}}$ 交互。
- $v_3$ 的特征:$\tilde{h}_3(t=5) = [1.1, 1.2, 1.3, 1.4, 1.5]$
时间编码($d_T=2$, $\omega_1=1$):
- $\Phi_{d_T}(10-8=2) = [\cos(2), \sin(2)] \approx [-0.42, 0.91]$
- $\Phi_{d_T}(10-5=5) = [\cos(5), \sin(5)] \approx [0.28, -0.96]$
- $\Phi_{d_T}(0) = [1, 0]$
将每个邻居的特征与对应时间编码拼接:
$$ Z(10) = \begin{bmatrix} \tilde{h}_0(10) \| \Phi_{d_T}(0) \\ \tilde{h}_1(8) \| \Phi_{d_T}(2) \\ \tilde{h}_2(8) \| \Phi_{d_T}(2) \\ \tilde{h}_3(5) \| \Phi_{d_T}(5) \end{bmatrix} = \begin{bmatrix} 0.1, 0.2, 0.3, 0.4, 0.5, 1, 0 \\ 0.6, 0.7, 0.8, 0.9, 1.0, -0.42, 0.91 \\ 0.2, 0.3, 0.4, 0.5, 0.6, -0.42, 0.91 \\ 1.1, 1.2, 1.3, 1.4, 1.5, 0.28, -0.96 \end{bmatrix}_{4 \times 7} $$注意力权重计算:
1.投影矩阵参数(简化示例,设 $d_h = 3$,真实情况由训-练得来):
$$ W_Q = W_K = \begin{bmatrix} 0.1 & 0.2 & 0.3 \\ 0.4 & 0.5 & 0.6 \\ 0.7 & 0.8 & 0.9 \\ 1.0 & 1.1 & 1.2 \\ 1.3 & 1.4 & 1.5 \\ 0.2 & 0.3 & 0.4 \\ 0.5 & 0.6 & 0.7 \end{bmatrix}_{7 \times 3}, \quad W_V = \begin{bmatrix} 0.3 & 0.4 & 0.5 \\ 0.6 & 0.7 & 0.8 \\ 0.9 & 1.0 & 1.1 \\ 1.2 & 1.3 & 1.4 \\ 1.5 & 1.6 & 1.7 \\ 0.1 & 0.2 & 0.3 \\ 0.4 & 0.5 & 0.6 \end{bmatrix}_{7 \times 3} $$ **2.计算 Query/Key/Value**:- Query(目标节点 $v_0$):
-
Keys(邻居节点): $$ K(10) = [Z(10)]_{1:3} W_K = \begin{bmatrix} 0.6 & 0.7 & 0.8 & 0.9 & 1.0 & -0.42 & 0.91 \ 0.2 & 0.3 & 0.4 & 0.5 & 0.6 & -0.42 & 0.91 \ 1.1 & 1.2 & 1.3 & 1.4 & 1.5 & 0.28 & -0.96 \end{bmatrix} \cdot W_K = \begin{bmatrix} 3.22 & 3.68 & 4.14 \ 1.82 & 2.18 & 2.54 \ 4.18 & 4.64 & 5.10 \end{bmatrix} $$
-
Values(邻居节点): $$ V(10) = [Z(10)]_{1:3} W_V = \begin{bmatrix} 3.52 & 3.92 & 4.32 \ 2.12 & 2.42 & 2.72 \ 4.48 & 4.88 & 5.28 \end{bmatrix} $$
3.计算注意力权重
- 计算未归一化分数(缩放因子 $\sqrt{d_h} = \sqrt{3} \approx 1.732$):
- Softmax 归一化: $$ \alpha = \text{softmax}([18.46, 10.56, 21.40]) = [2.4 \times 10^{-2}, 1.6 \times 10^{-5}, 0.976] $$
4.加权求和生成聚合向量
$$ h(10) = \sum_{i=1}^3 \alpha_i V_i = 0.024 \cdot \begin{bmatrix}3.52 \\ 3.92 \\ 4.32\end{bmatrix} + 1.6 \times 10^{-5} \cdot \begin{bmatrix}2.12 \\ 2.42 \\ 2.72\end{bmatrix} + 0.976 \cdot \begin{bmatrix}4.48 \\ 4.88 \\ 5.28\end{bmatrix}\approx [4.48, 4.88, 5.28] $$ **5.节点嵌入更新**1.拼接操作
$$ z=[h(10) \| x_0] = [4.48, 4.88, 5.28, 0.1, 0.2, 0.3, 0.4, 0.5] $$ **2. FFN参数设置**FFN 包含两层:
$$ \tilde{h}_0^{(l)}(10)=\text{FFN}(z) = \text{ReLU}(z W_0 + b_0) W_1 + b_1 $$需提前训练的参数
参数名称 | 符号 | 维度 | 来源层 | 作用 |
---|---|---|---|---|
时间编码频率参数 | $\omega_1,\dots,\omega_{d_T}$ | $d_T\times1$ | 全模型 | 控制功能性时间编码基频率,用于生成 $\Phi_{d_T}(\Delta t)$ |
Query 投影矩阵 | $W_Q^{(l)}$ | $(d_h + d_T)\times d_h$ | 第 $l$ 层 | 将拼接后的"隐藏表示+时间编码"映射为 Query 向量 |
Key 投影矩阵 | $W_K^{(l)}$ | $(d_h + d_T)\times d_h$ | 第 $l$ 层 | 将拼接后的"隐藏表示+时间编码"映射为 Key 向量 |
Value 投影矩阵 | $W_V^{(l)}$ | $(d_h + d_T)\times d_h$ | 第 $l$ 层 | 将拼接后的"隐藏表示+时间编码"映射为 Value 向量 |
FFN 第一层权重 | $W_0^{(l)}$ | $(d_h + d_0)\times d_f$ | 第 $l$ 层 FFN | 拼接向量 $[,h^{(l)}(t),|,x_0,]$ 的第一层线性变换 |
FFN 第一层偏置 | $b_0^{(l)}$ | $d_f$ | 第 $l$ 层 FFN | 第一层线性偏置 |
FFN 第二层权重 | $W_1^{(l)}$ | $d_f\times d$ | 第 $l$ 层 FFN | 第二层线性变换,生成本层最终节点表示 |
FFN 第二层偏置 | $b_1^{(l)}$ | $d$ | 第 $l$ 层 FFN | 第二层线性偏置 |
每个节点运行的模型是一样的QKV这些参数都是一样的。
运行过程中这些训练好的参数不会变化,模型的动态性体现在:
- 维护全局事件流;当新的边 $(u, v, t)$ 加入或旧的边变得不再被采样时,下一次你对某个节点做推理时,检索到的邻居集合就不一样;
- 时间编码会根据新的 $\Delta t$ 动态计算;
- 注意力权重 $\alpha_i$ 会重新分配,FFN 也会基于新的聚合结果给出新的输出。
节点是否需要交互(是否需要全局信息)
-
如果节点仅关注自己的特征更新以及任务,仅需维护:
从事件流中取出所有在 $t$ 之前与 $v_0$ 有过交互的节点集合以及交互的时间 $t_i$。 $$ \mathcal{N}(v_0; t) = { v_i \mid \exists (v_0, v_i, t_i) \in \mathcal{E}, t_i < t } $$
-
如果节点还关注其他节点的特征更新及任务,需要知道全局事件流 (若干时刻邻接矩阵转化而来)