Commit on 2025/05/05 周一 10:12:08.30

This commit is contained in:
zhangsan 2025-05-05 10:12:08 +08:00
parent cfc666641a
commit 7b566c5e8e
7 changed files with 568 additions and 116 deletions

View File

@ -0,0 +1,308 @@
# 动态图神经网络
## 如何对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$ 层为例)**
**输入**
1. 当前节点嵌入矩阵 $H_t^{(l)} \in \mathbb{R}^{n \times d}$
2. 上一时间步的权重矩阵 $W_{t-1}^{(l)} \in \mathbb{R}^{d \times d'}$
3. 邻接矩阵 $A_t \in \mathbb{R}^{n \times n}$
**输出**
1. 更新后的权重矩阵 $W_t^{(l)} \in \mathbb{R}^{d \times d'}$。
2. 下一层节点嵌入 $H_t^{(l+1)} \in \mathbb{R}^{n \times d'}$。
---
#### **3. 动态更新示意图**
```plaintext
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')
$$
**实现方式**(论文方案):
1. 计算得分:
$$
y_t = H_t^{(l)} p / \|p\| \quad (p \in \mathbb{R}^d \text{为可学习参数})
$$
学一个“打分器”参数 $p$$H_t^{(l)} p$相当于对每个节点的嵌入向量和 $p$做点积,得到一个分数。比如在社交网络中,$p$ 可能代表“活跃度”,得分高的用户更活跃。
2. 选取 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$ 只关注嵌入的第一维,比如“用户发帖数量”)
1. **计算分数**
$$ 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)。
2. **加权聚合**
$$ 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$
3. **输出**$Z_t$ 是 $2 \times 2$ 矩阵可以直接喂给GRU。
##### **步骤 2GRU 更新权重矩阵**
$$
W_t^{(l)} = \text{GRU}(Z_t^T, W_{t-1}^{(l)})
$$
标准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 的矩阵形式计算**
1. **重置门** $R_t$:控制历史信息的遗忘程度
$$
R_t = \sigma(Z_t^T W_Z + W_{t-1}^{(l)} U_Z + B_Z)
$$
2. **更新门** $Z_t$:控制新旧状态混合比例
$$
U_t = \sigma(Z_t^T W_U + W_{t-1}^{(l)} U_U + B_U)
$$
3. **候选状态** $\widetilde{W}_t$
$$
\widetilde{W}_t = \tanh(Z_t^T W_H + (R_t \circ W_{t-1}^{(l)}) U_H + B_H)
$$
4. **最终权重更新**
$$
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'}$。
##### **步骤 3GCN 生成下一层嵌入**
使用更新的 $W_t^{(l)}$ 执行标准 GCN 操作:
$$
H_t^{(l+1)} = \sigma\left(\widehat{A}_t H_t^{(l)} W_t^{(l)}\right)
$$
- $\widehat{A}_t$ 为归一化邻接矩阵(含自环)。
---
#### **5. 关键设计细节**
1. **权重共享**
- 所有时间步共享同一 GRU 的参数($W_*, U_*, B_*$),确保模型尺寸不随时间增长。
2. **层独立性**
- 每一层 GCN 的权重矩阵独立演化(不同层有各自的 GRU
3. **特征与结构的协同**
- 节点嵌入 $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$ | 动态选择重要节点 |
| 任务相关参数 | 例如 MLP 权重 | 任务相关 | 链接预测、节点分类等输出层 |
### **EvolveGCN-O**
#### **1. 核心思想**
EvolveGCN-O 通过 **LSTM** 直接演化 GCN 的权重矩阵 $W_t^{(l)}$,将权重矩阵视为 **LSTM的输出**(下一时间步的输入),**不依赖节点嵌入**。
**关键特点**
- **结构驱动**:仅通过历史权重 $W_{t-1}^{(l)}$ 预测当前权重,完全基于图结构的动态变化。
- **轻量化**:无需处理节点嵌入,计算效率更高。
---
#### **2. 动态更新流程(第$l$层)**
**输入**
1. 上一时间步权重 $W_{t-1}^{(l)} \in \mathbb{R}^{d \times d'}$
2. 邻接矩阵 $A_t \in \mathbb{R}^{n \times n}$仅用于GCN计算
**输出**
1. 更新后权重 $W_t^{(l)} \in \mathbb{R}^{d \times d'}$
2. 下一层节点嵌入 $H_t^{(l+1)} \in \mathbb{R}^{n \times d'}$
#### 3.具体步骤分解
##### **步骤1LSTM更新权重矩阵**
**矩阵版LSTM计算**
1. 遗忘门:
$F_t = \sigma(W_F W_{t-1}^{(l)} + U_F C_{t-1} + B_F)$
2. 输入门:
$I_t = \sigma(W_I W_{t-1}^{(l)} + U_I C_{t-1} + B_I)$
3. 候选状态:
$\widetilde{C}_t = \tanh(W_C W_{t-1}^{(l)} + U_C C_{t-1} + B_C)$
4. 细胞状态更新:
$C_t = F_t \circ C_{t-1} + I_t \circ \widetilde{C}_t$
5. 输出门:
$O_t = \sigma(W_O W_{t-1}^{(l)} + U_O C_{t-1} + B_O)$
6. 最终权重输出:
$W_t^{(l)} = O_t \circ \tanh(C_t)$
##### **步骤2GCN生成下一层嵌入**
$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

View File

@ -1,5 +1,3 @@
李振河 陈茂森
# 图神经网络
图表示学习的本质是把节点映射成低维连续稠密的向量。这些向量通常被称为 **嵌入Embedding**,它们能够捕捉节点在图中的结构信息和属性信息,从而用于下游任务(如节点分类、链接预测、图分类等)。
@ -152,6 +150,8 @@
### **矩阵运算**
符号波浪号用于表示**经过自环增强的矩阵**。
$\tilde D^{-1}\,\tilde A\,\tilde D^{-1}H$
$H'=\tilde D^{-1}\,\tilde A\,H$
@ -516,12 +516,7 @@ $$
| 特性 | 直推式Transductive | 归纳式Inductive |
| ---------------- | ---------------------- | ------------------------------- |
| 训练时是否读全图 | 是 | 否(局部采样) |
| 参数 W 依赖 | 固定图的全局结构 | 只依赖“中心节点 + 邻居”局部结构 |
| 推理时能否换图 | 不能 | 能(只要给出邻居列表和特征) |
| 典型算法 | Kipf&Welling GCN | GraphSAGE, GAT, SGC (简化版) 等 |
总结直推式要求图的邻接矩阵不能变化归纳式要求现有的邻接关系尽量不变化支持少量节点新加入直接复用已有W和a聚合特征。

View File

@ -152,10 +152,9 @@ GRU 通过两个门gate来控制信息的流动
- $x_t$ 是当前时间步的输入;
- $h_{t-1}$ 是上一时刻的隐藏状态;
- $W_z$ 和 $U_z$ 是权重矩阵;
- $b_z$ 是偏置向量;
- $\sigma(\cdot)$ 是 sigmoid 函数,用于将输出限制在 $[0, 1]$ 区间。
2. **重置门 $r_t$**
$$
r_t = \sigma(W_{xr} x_t + W_{hr} h_{t-1} + b_r)

View File

@ -1,78 +1,58 @@
### **LSTM+GAT训练过程说明RWP网络节点移动预测**
#### **1. 数据构造**
**输入数据**
- **节点轨迹数据**
- 每个节点在1000个时间单位内的二维坐标 $(x, y)$,形状为 $[N, 1000, 2]$$N$个节点1000个时间步2维特征
- **动态邻接矩阵序列**
- 每个时间步的节点连接关系基于距离阈值或其他规则生成得到1000个邻接矩阵 $[A_1, A_2, \dots, A_{1000}]$,每个 $A_t$ 的形状为 $[2, \text{num\_edges}_t]$(稀疏表示)。
**滑动窗口处理**
- **窗口大小**12用前12个时间步预测第13个时间步
- **滑动步长**1每次滑动1个时间步生成更多训练样本
- **生成样本数量**
- 总时间步1000窗口大小12 → 可生成 $1000 - 12 = 988$ 个样本。
**样本格式**
- **输入序列** $X^{(i)}$:形状 $[N, 12, 2]$$N$个节点12个时间步2维坐标
- **目标输出** $Y^{(i)}$:形状 $[N, 2]$第13个时间步所有节点的坐标
- **动态邻接矩阵**每个样本对应12个邻接矩阵 $[A^{(i)}_1, A^{(i)}_2, \dots, A^{(i)}_{12}]$(每个 $A^{(i)}_t$ 形状 $[2, \text{num\_edges}_t]$)。
### **Bochner定理Bochner's Theorem简介**
Bochner定理是**调和分析Harmonic Analysis**中的一个重要定理由数学家Salomon Bochner提出。它描述了**连续正定函数positive definite functions**与**非负有限测度non-negative finite measures**之间的对偶关系,在信号处理、概率论和机器学习(如核方法、时间编码)中有广泛应用。
---
#### **2. 训练过程**
**模型结构**
1. **LSTM层**
- 输入:$[N, 12, 2]$$N$个节点的12步历史轨迹
- 输出:每个节点的时序特征 $[N, 12, H]$$H$为LSTM隐藏层维度
- **关键点**LSTM独立处理每个节点的时序节点间无交互。
### **1. 数学定义与公式**
Bochner定理的核心内容是
> **一个连续函数 $ f: \mathbb{R}^d \to \mathbb{C} $ 是正定的positive definite当且仅当它是某个非负有限测度 $ \mu $ 的傅里叶变换。**
2. **GAT层**
- 输入取LSTM最后一个时间步的输出 $[N, H]$(即每个节点的最终时序特征)。
- 动态图输入使用第12个时间步的邻接矩阵 $A^{(i)}_{12}$(形状 $[2, \text{num\_edges}]$)。
- 输出:通过图注意力聚合邻居信息,得到空间增强的特征 $[N, H']$$H'$为GAT输出维度
数学表达式为:
$$
f(\mathbf{t}) = \int_{\mathbb{R}^d} e^{i \boldsymbol{\omega}^\top \mathbf{t}} \, \mathrm{d}\mu(\boldsymbol{\omega}),
$$
其中:
- $ \mathbf{t} \in \mathbb{R}^d $ 是输入向量(如时间差、空间坐标等)。
- $ \boldsymbol{\omega} $ 是频率域变量,$ \mu(\boldsymbol{\omega}) $ 是频域上的非负测度(可理解为能量分布)。
- $ e^{i \boldsymbol{\omega}^\top \mathbf{t}} $ 是复指数函数(傅里叶基)。
3. **预测层**
- 全连接层将 $[N, H']$ 映射到 $[N, 2]$,预测下一时刻的坐标。
**训练步骤**
1. **前向传播**
- 输入 $[N, 12, 2]$ → LSTM → $[N, 12, H]$ → 取最后时间步 $[N, H]$ → GAT → $[N, H']$ → 预测 $[N, 2]$。
2. **损失计算**
- 均方误差MSE损失比较预测坐标 $[N, 2]$ 和真实坐标 $[N, 2]$。
3. **反向传播**
- 梯度从预测层回传到GAT和LSTM更新所有参数。
#### **关键点**
- **正定函数**:满足对任意 $ n $ 个点 $ \mathbf{t}_1, \ldots, \mathbf{t}_n $,矩阵 $ [f(\mathbf{t}_i - \mathbf{t}_j)]_{i,j} $ 是半正定positive semi-definite的。
- **测度 $ \mu $**:代表频域的权重分布,可通过采样或优化学习得到。
---
#### **3. 数据维度变化总结**
| **步骤** | **数据形状** | **说明** |
| --------------------- | -------------- | -------------------------------------- |
| 原始输入 | $[N, 1000, 2]$ | $N$个节点1000个时间步的$(x,y)$坐标。 |
| 滑动窗口样本 | $[N, 12, 2]$ | 每个样本包含12个历史时间步。 |
| LSTM输入 | $[N, 12, 2]$ | 输入LSTM的节点独立时序数据。 |
| LSTM输出 | $[N, 12, H]$ | $H$为LSTM隐藏层维度。 |
| GAT输入最后时间步 | $[N, H]$ | 提取每个节点的最终时序特征。 |
| GAT输出 | $[N, H']$ | $H'$为GAT输出维度含邻居聚合信息。 |
| 预测输出 | $[N, 2]$ | 下一时刻的$(x,y)$坐标预测。 |
### **2. 在TGAT论文中的应用**
TGAT论文利用Bochner定理设计**功能性时间编码Functional Time Encoding**,将时间差 $ \Delta t $ 映射为向量表示。具体步骤:
#### **1时间编码的构造**
根据Bochner定理任意正定时间核函数 $ f(\Delta t) $ 可表示为:
$$
f(\Delta t) = \mathbb{E}_{\omega \sim \mu} \left[ e^{i \omega \Delta t} \right],
$$
其中 $ \mu $ 是频率 $ \omega $ 的分布。通过蒙特卡洛采样近似:
$$
f(\Delta t) \approx \frac{1}{k} \sum_{j=1}^k e^{i \omega_j \Delta t}, \quad \omega_j \sim \mu.
$$
#### **2实值化处理**
由于神经网络需实数输入,取实部并拆分为正弦和余弦函数:
$$
\phi(\Delta t) = \sqrt{\frac{1}{k}} \left[ \cos(\omega_1 \Delta t), \sin(\omega_1 \Delta t), \ldots, \cos(\omega_k \Delta t), \sin(\omega_k \Delta t) \right].
$$
这构成了TGAT中时间差 $ \Delta t $ 的编码向量。
#### **优势**
- **理论保障**Bochner定理确保时间编码的数学合理性正定性保持拓扑结构
- **灵活性**:通过调整 $ \mu $ 可适应不同时间尺度模式。
---
#### **4. 关键注意事项**
1. **动态图的处理**
- 每个滑动窗口样本需匹配对应时间步的邻接矩阵(如第 $i$ 到 $i+11$ 步的 $[A^{(i)}_1, \dots, A^{(i)}_{12}]$但GAT仅使用最后一步 $A^{(i)}_{12}$。
- 若图结构变化缓慢,可简化为所有窗口共享 $A^{(i)}_{12}$。
2. **数据划分**
- 按时间划分训练/验证集如前800个窗口训练后188个验证避免未来信息泄露。
3. **模型改进方向**
- **多步预测**:输出 $[N, K, 2]$(预测未来$K$步),需调整损失函数。
- **时空耦合**改用ST-LSTM或先GAT后LSTM更早引入交互。
### **3. 与其他方法的对比**
- **传统位置编码如Transformer的PE**:仅适用于离散序列,无法泛化到任意时间差。
- **Bochner编码**:适用于连续时间域,且能通过学习 $ \mu $ 优化时间敏感性。
---
### **总结**
- **数据流**:滑动窗口切割时序 → LSTM独立编码节点轨迹 → GAT聚合空间信息 → 预测坐标。
- **节点交互时机**仅在GAT阶段通过注意力机制融合邻居信息LSTM阶段节点独立。
- **适用性**适合RWP等移动模型预测兼顾时序动态和空间依赖。
### **总结**
Bochner定理为TGAT的**连续时间编码**提供了理论基础使其能够将任意时间差映射为可学习的向量表示从而在动态图中有效捕捉时序依赖。这一方法超越了传统离散编码的局限性是TGAT的核心创新之一。

View File

@ -116,6 +116,81 @@ $$
## 网络重构分析
### 滤波误差
- **原始全矩阵**
$$
A = X \Lambda X^T = X_r \Lambda_r X_{r}^T + \underbrace{X_{-r} \Lambda_{-r} X_{-r}^T}_{\text{被截掉的尾部}}
$$
- **截断重构(真实)**
$$
A_k = X_r \Lambda_r X_{r}^T
$$
- **滤波后重构**
$$
\hat{A}_r = X_r (\Lambda_r + \Delta \Lambda_r) X_{r}^T
$$
- **卡尔曼滤波误差矩阵**(定义为两者之差):
$$
E_{KF} = \hat{A}_r - A_r = X_r \Delta \Lambda_r X_{r}^T.
$$
---
要量化这个误差,常用矩阵的 Frobenius 范数:
$$
e_{KF} = \| E_{KF} \|_F = \| X_r \Delta \Lambda_r X_r^T \|_F.
$$
由于 $X_K$ 是正交子矩阵(假设特征向量正交归一),有
$$
e_{KF} = \|\Delta \Lambda_K\|_F = \sqrt{\sum_{i=1}^r (\delta \lambda_i)^2}.
$$
---
### **全局误差度量**
对估计矩阵 $\hat{A}_k$ 的所有元素 $\{\hat{a}_{ij}\}$ 进行 $K$-means 聚类,得到中心 $\{c_k\}_{k=1}^K$。
- **簇内平均偏差**
$$
\text{mean}_k = \frac{1}{|\mathcal{S}_k|} \sum_{(i,j)\in\mathcal{S}_k} |\hat{a}_{ij} - c_k|
$$
- **全局允许误差**
$$
\delta_{\max} = \frac{1}{K} \sum_{k=1}^K \text{mean}_k
$$
**最终约束条件**
-
$$
\boxed{
\underbrace{e_{KF}}_{\text{滤波误差}}
\;+\;
\underbrace{\epsilon}_{\text{重构算法误差}}
\;\le\;
\underbrace{\delta_{\max}}_{\text{聚类量化容限}}
}
$$
$$
{\epsilon}\;\le\;
{\delta_{\max}} -e_{KF}
$$
## 网络结构优化
@ -522,3 +597,13 @@ TCN的卷积核仅在**单个通道内滑动**,计算时仅依赖该节点自
2. **数据划分**
- 按时间划分训练/验证集如前800个窗口训练后188个验证避免未来信息泄露。
颜佳佳论文问题:
卡尔曼滤波预测了流量矩阵但是又要TCN-GAT预测了流量矩阵是否可以将TCN-GAT预测流量矩阵作为卡尔曼滤波的观测值。

View File

@ -234,6 +234,10 @@ $$
## 网络重构分析
### **0/1矩阵**
这里以n个特征值特征向量重构为例
假设网络中有 $n$ 个节点,则矩阵 $A(G)$ 的维度为 $n \times n$,预测得到特征值和特征向量后,可以根据矩阵谱分解理论进行逆向重构网络邻接矩阵,表示如下:
$$
@ -284,6 +288,82 @@ $$
### **非0/1矩阵**
- 原始(真)加权邻接矩阵:
$$
A = \sum_{m=1}^n \lambda_m\,x_m x_m^T,
\quad \lambda_1\ge\lambda_2\ge\cdots\ge\lambda_n,\;
x_m^T x_k=\delta_{mk}.
$$
- 估计得到的矩阵及谱分解:
$$
\widetilde A = \sum_{m=1}^n \widetilde\lambda_m\,\widetilde x_m\widetilde x_m^T,
\quad \widetilde\lambda_1\ge\cdots\ge\widetilde\lambda_n,\;
\widetilde x_m^T\widetilde x_k=\delta_{mk}.
$$
- 最终只取前 $r$ 项重构
$$
A_r \;=\;\sum_{m=1}^r \widetilde\lambda_m\,\widetilde x_m\widetilde x_m^T,
$$
#### **全局误差度量**
对估计矩阵 $\widetilde{A}$ 的所有元素 $\{\tilde{a}_{ij}\}$ 进行 $K$-means 聚类,得到中心 $\{c_k\}_{k=1}^K$。
- **簇内平均偏差**
$$
\text{mean}_k = \frac{1}{|\mathcal{S}_k|} \sum_{(i,j)\in\mathcal{S}_k} |\tilde{a}_{ij} - c_k|
$$
- **全局允许误差**
$$
\delta_{\max} = \frac{1}{K} \sum_{k=1}^K \text{mean}_k
$$
#### 带权重构需控制两类误差:
1. **谱分解截断误差**$\epsilon$
$$
\epsilon
= \bigl\|\widetilde A - A_r\bigr\|_F
= \Bigl\|\sum_{m=r+1}^n \widetilde\lambda_m\,\widetilde x_m \widetilde x_m^T\Bigr\|_F.
$$
---
2. **滤波误差**$\eta$
**来源**:滤波器在谱域对真实特征值/向量的估计偏差,包括
- 特征值偏差 $\Delta\lambda_m=\lambda_m-\widetilde\lambda_m$
- 特征向量:矩阵扰动得来,不知道该不该算
$$
A - \widetilde A=\sum_{m=1}^n \Delta \lambda_m \hat{x}_m \hat{x}_m^T.
$$
$$
\eta \approx \Bigl\|\sum_{m=1}^n \Delta\lambda_m\,\widetilde x_m\widetilde x_m^T\Bigr\|_F
$$
#### **最终约束条件**
$$
\boxed{
\underbrace{\eta}_{\text{滤波误差}}
\;+\;
\underbrace{\epsilon}_{\text{谱分解截断误差}}
\;\le\;
\underbrace{\delta_{\max}}_{\text{聚类量化容限}}
}
$$
## 基于时空特征的节点位置预测
在本模型中,整个预测流程分为两大模块:

View File

@ -186,58 +186,63 @@ String sortedStr = new String(charArray);
- `substring(int beginIndex, int endIndex)` 方法返回从 `beginIndex``endIndex - 1` 的子字符串。
- 返回的是 `String` 类型,即使子字符串只有一个字符。
去除开头结尾空字符:
- `trim()`
### StringBuffer
分割字符串:
`StringBuffer` 是 Java 中用于操作可变字符串的类
**`split()`** 方法,可以用来分割字符串,并返回一个字符串数组。参数是正则表达式。
```java
public class StringBufferExample {
public static void main(String[] args) {
// 创建初始字符串 "Hello"
StringBuffer sb = new StringBuffer("Hello");
System.out.println("Initial: " + sb.toString()); // 输出 "Hello"
// 1. append在末尾追加 " World"
sb.append(" World");
System.out.println("After append: " + sb.toString()); // 输出 "Hello World"
// 2. insert在索引 5 位置("Hello"后)插入 ", Java"
sb.insert(5, ", Java");
System.out.println("After insert: " + sb.toString()); // 输出 "Hello, Java World"
// 3. delete删除从索引 5 到索引 11不包含的子字符串即删除刚才插入的 ", Java"
sb.delete(5, 11);
//sb.delete(5, sb.length()); 删除到末尾
System.out.println("After delete: " + sb.toString()); // 输出 "Hello World"
// 4. deleteCharAt删除索引 5 处的字符(删除空格)
sb.deleteCharAt(5);
System.out.println("After deleteCharAt: " + sb.toString()); // 输出 "HelloWorld"
// 5. reverse反转整个字符串
sb.reverse();
System.out.println("After reverse: " + sb.toString()); // 输出 "dlroWolleH"
}
}
String str = "apple, banana, orange grape";
String[] fruits = str.split(",\\s*"); // 按逗号后可能存在的空格分割
// apple banana orange grape
```
`StringBuffer`有库函数可以翻转String未提供
```java
StringBuilder sb = new StringBuilder(s);
String reversed = sb.reverse().toString();
```
StringBuffer清空内容
### StringBuilder
**StringBuffer** 是线程安全的,它的方法是同步的 (synchronized),这意味着在多线程环境下使用 `StringBuffer` 是安全的。
**StringBuilder** 不是线程安全的,它的方法没有同步机制,因此在单线程环境中,`StringBuilder` 的性能通常要比 `StringBuffer` 更好。
它们都是 Java 中用于操作可变字符串的类,拥有相同的方法!
1.**`append(String str)`**
向字符串末尾追加内容。
2.**`insert(int offset, String str)`**
在指定位置插入字符串。
3.**`delete(int start, int end)`**
删除从 `start``end` 索引之间的字符。
4.**`deleteCharAt(int index)`**
删除指定位置的字符。
5.**`replace(int start, int end, String str)`**
替换指定范围内的字符。
6.**`reverse()`**
将字符串反转。String未提供
7.**`toString()`**
返回当前字符串缓冲区的内容,转换为 `String` 对象。
8.**`charAt(int index)`**
返回指定位置的字符。
9.**`length()`**
返回当前字符串的长度。
10.**`setLength(int newLength)`**
设置字符串的长度。 //sb.setLength(0); 用作清空字符串
```java
StringBuffer sb = new StringBuffer("Hello, world!");
System.out.println("Before clearing: " + sb);
// 清空 StringBuffer
sb.setLength(0);
```
`StringBuffer``append()` 方法不仅支持添加普通的字符串,也可以直接将另一个 `StringBuffer` 对象添加到当前的 `StringBuffer`