P-sLSTM(AAAI 2025)学习笔记
论文标题:Unlocking the Power of LSTM for Long Term Time Series Forecasting
发表平台:AAAI 2025(CCF A)
发表时间:2025.2
模型结构图如下:
P-sLSTM 模型流程图及维度变化
下面是一个详细的流程图,展示 P-sLSTM 模型中数据的流动和维度变化。
模型数据流程图
输入 x: [B, L, C]
↓
维度重排: [B, C, L]
↓
展平批次和通道: [(B*C), L]
↓
创建补丁: [(B*C), Num_patches, Patch_size]
↓
嵌入层: [(B*C), Num_patches, Embedding_dim]
↓
xLSTM 堆栈: [(B*C), Num_patches, Embedding_dim]
↓
展平特征: [(B*C), Num_patches * Embedding_dim]
↓
投影层: [(B*C), Pred_len]
↓
重塑维度: [B, C, Pred_len]
↓
最终输出: [B, L_pred, C]
详细维度变化说明
输入 :
- 形状:
[B, L, C]
- 含义: 批次大小 B, 输入序列长度 L, 通道数 C
- 形状:
维度重排 :
- 形状:
[B, C, L]
- 操作:
rearrange(x, 'b l c -> b c l')
- 目的: 将通道维度移到中间位置
- 形状:
展平批次和通道 :
- 形状:
[(B*C), L]
- 操作:
rearrange(x, 'b c l -> (b c) l')
- 目的: 将批次和通道维度合并处理
- 形状:
创建补丁 :
- 形状:
[(B*C), Num_patches, Patch_size]
- 操作:
x.unfold(dimension=-1, size=patch_size, step=stride)
- 参数:
- Num_patches = (L - patch_size) // stride + 1
- Patch_size = configs.patch_size
- stride = configs.stride
- 形状:
嵌入层 :
- 形状:
[(B*C), Num_patches, Embedding_dim]
- 操作:
self.embedding(x)
- 参数: Embedding_dim = configs.embedding_dim
- 形状:
xLSTM 堆栈 :
- 形状:
[(B*C), Num_patches, Embedding_dim]
- 操作:
self.xlstm_stack(x)
- 内部: 多个 sLSTM 块处理,但维度保持不变
- 形状:
展平特征 :
- 形状:
[(B*C), Num_patches * Embedding_dim]
- 操作:
x.flatten(1)
- 目的: 将所有特征展平为一维向量
- 形状:
投影层 :
- 形状:
[(B*C), Pred_len]
- 操作:
self.projection(x)
- 参数: Pred_len = configs.pred_len
- 形状:
重塑维度 :
- 形状: [B, C, Pred_len]
- 操作:
rearrange(x, '(b c) l -> b c l', b=B, c=C)
- 目的: 恢复批次和通道维度
最终输出 :
- 形状:
[B, Pred_len, C]
- 操作:
rearrange(x, 'b c l -> b l c')
- 目的: 调整为最终输出格式,预测长度在中间维度
这个流程图清晰地展示了数据如何在模型中流动,以及每一步的维度变化,有助于理解模型的工作原理和数据处理流程。
- 形状:
xLSTM 内部流程图及维度变化
展开 xLSTM 的内部流程,详细说明 self.xlstm_stack(x)
这一步中数据的处理过程和维度变化。
xLSTM 内部流程图
输入 x: [(B*C), Num_patches, Embedding_dim]
↓
+------------------------+
| xLSTM Block Stack |
| |
| +------------------+ |
| | sLSTM Block 1 | |
| | +-------------+ | |
| | | sLSTM Layer | | |
| | +-------------+ | |
| | ↓ | |
| | +-------------+ | |
| | | 前馈网络层 | | |
| | +-------------+ | |
| +------------------+ |
| ↓ |
| +------------------+ |
| | sLSTM Block 2 | |
| | ... | |
| +------------------+ |
| ↓ |
| +------------------+ |
| | sLSTM Block n | |
| | ... | |
| +------------------+ |
+------------------------+
↓
输出: [(B*C), Num_patches, Embedding_dim]
详细维度变化说明
输入到 xLSTM 堆栈
- 形状:
[(B*C), Num_patches, Embedding_dim]
在每个 sLSTM 块内部:
sLSTM 层处理 :
- 输入形状:
[(B*C), Num_patches, Embedding_dim]
- 处理步骤:
- 多头注意力计算 :
- 将输入分割为
num_heads
个头 - 每个头的维度:
[(B*C), Num_patches, Embedding_dim/num_heads]
- 应用注意力机制
- 将输入分割为
- 卷积操作 :
- 使用
conv1d_kernel_size
大小的卷积核 - 捕获局部上下文信息
- 使用
- 状态空间处理 :
- 应用状态空间模型进行序列建模
- 多头注意力计算 :
- 输出形状:
[(B*C), Num_patches, Embedding_dim]
- 输入形状:
前馈网络层 :
- 输入形状:
[(B*C), Num_patches, Embedding_dim]
- 处理步骤:
- 第一线性变换 :
- 扩展维度:
[(B*C), Num_patches, Embedding_dim * proj_factor]
- 其中
proj_factor = 1.3
- 扩展维度:
- GELU 激活函数 :
- 应用非线性变换
- 第二线性变换 :
- 恢复原始维度:
[(B*C), Num_patches, Embedding_dim]
- 恢复原始维度:
- 第一线性变换 :
- 输出形状:
[(B*C), Num_patches, Embedding_dim]
- 输入形状:
残差连接 :
- 每个子块内部都有残差连接
- 确保梯度能够有效传播
多个块的堆叠:
- 第一个块输出:
[(B*C), Num_patches, Embedding_dim]
- 第二个块输入:
[(B*C), Num_patches, Embedding_dim]
- …
- 第 n 个块输出:
[(B*C), Num_patches, Embedding_dim]
其中n = configs.num_blocks
xLSTM 堆栈输出
- 形状:
[(B*C), Num_patches, Embedding_dim]
- 注意: 虽然经过了多个处理块,但输入和输出的维度保持不变
关键特性
- 维度保持 : 整个 xLSTM 堆栈处理过程中,输入和输出的维度保持一致
- 深度处理 : 通过多个 sLSTM 块的堆叠,逐步提取序列中的深层特征
- 并行处理 : 多头注意力机制允许模型并行地关注不同的特征模式
- 局部与全局结合 : 通过卷积操作捕获局部特征,通过状态空间模型捕获全局依赖
这种设计使 xLSTM 能够有效地处理时间序列数据,捕获不同尺度的时间依赖关系,同时保持计算效率
sLSTM Layer 详细解析
根据 xLSTM 堆栈的实现,我将为您展开 sLSTM Layer 的内部结构和工作流程。
sLSTM Layer 流程图
输入 x: [(B*C), Num_patches, Embedding_dim]
↓
+---------------------------+
| sLSTM Layer |
| |
| +---------------------+ |
| | 输入归一化 | |
| +---------------------+ |
| ↓ |
| +---------------------+ |
| | 多头注意力机制 | |
| | | |
| | +--------------+ | |
| | | Q, K, V 投影 | | |
| | +--------------+ | |
| | ↓ | |
| | +--------------+ | |
| | | 头分割处理 | | |
| | +--------------+ | |
| | ↓ | |
| | +--------------+ | |
| | | 状态空间处理 | | |
| | +--------------+ | |
| | ↓ | |
| | +--------------+ | |
| | | 头合并 | | |
| | +--------------+ | |
| | ↓ | |
| | +--------------+ | |
| | | 输出投影 | | |
| | +--------------+ | |
| +---------------------+ |
| ↓ |
| +---------------------+ |
| | 残差连接 | |
| +---------------------+ |
+---------------------------+
↓
输出: [(B*C), Num_patches, Embedding_dim]
sLSTM Layer 详细维度变化
1. 输入处理
- 输入形状:
[(B*C), Num_patches, Embedding_dim]
- 输入归一化: 应用 LayerNorm 进行归一化处理
2. 多头注意力机制 Q, K, V 投影:
- 输入形状:
[(B*C), Num_patches, Embedding_dim]
- 线性变换生成 Q, K, V:
- Q:
[(B*C), Num_patches, Embedding_dim]
- K:
[(B*C), Num_patches, Embedding_dim]
- V:
[(B*C), Num_patches, Embedding_dim]
头分割:
- Q:
- 将 Q, K, V 分割为多个头:
- Q:
[(B*C), Num_patches, num_heads, Embedding_dim/num_heads]
- K:
[(B*C), Num_patches, num_heads, Embedding_dim/num_heads]
- V:
[(B*C), Num_patches, num_heads, Embedding_dim/num_heads]
- Q:
- 重排为:
[(B*C), num_heads, Num_patches, Embedding_dim/num_heads]
3. 状态空间处理 卷积操作:
- 使用
conv1d_kernel_size
大小的卷积核 - 应用于每个头:
[(B*C), num_heads, Num_patches, Embedding_dim/num_heads]
- 捕获局部上下文信息 状态空间模型:
- 对每个头应用状态空间变换
- 使用 “
powerlaw_blockdependent
” 偏置初始化 - 处理序列中的长期依赖关系
4. 头合并与输出处理 头合并:
- 将多个头的输出合并:
[(B*C), Num_patches, Embedding_dim]
输出投影: - 线性变换:
[(B*C), Num_patches, Embedding_dim]
- 应用 dropout (如果配置)
5. 残差连接
- 将原始输入与处理后的输出相加
- 输出形状:
[(B*C), Num_patches, Embedding_dim]
sLSTM 的关键特性
状态空间模型 :
- 使用状态空间表示法处理序列
- 能够高效捕获长序列依赖关系
- 比传统 RNN 更高效地处理长序列
多头注意力 :
- 允许模型关注不同的特征模式
- 每个头可以专注于不同的信息
卷积操作 :
- 使用一维卷积捕获局部上下文
- 增强模型对局部模式的感知能力
偏置初始化 :
- 使用 “
powerlaw_blockdependent
” 初始化方法 - 根据块的深度调整偏置初始化策略
- 使用 “
残差连接 :
- 帮助梯度流动和深层网络训练
- 保留原始信息,防止信息丢失
sLSTM Layer 结合了状态空间模型和多头注意力机制的优势,能够有效处理时间序列数据中的长期依赖关系,同时保持计算效率。
实验复现
参数设置:
class Config:
def __init__(self):
self.seq_len = 10
self.pred_len = 1
self.channel = 5
self.embedding_dim = 64
self.patch_size = 5
self.stride = 1
self.conv1d_kernel_size = 3
self.num_heads = 4
self.num_blocks = 2
股票数据维度
trade_date,open,high,low,close,vol,amount,pct_chg,change,pre_close
沪深300
比亚迪(002594.sz)可能哪里出了点问题?
宁德时代(300750.sz)
腾讯(00700.hk)
有问题欢迎指正!❤️