Transformer
在时间序列预测中展现出强大的能力,但当序列长度达到数千甚至数万时,标准
Transformer 的
长序列时间序列预测的挑战
O(L ²) 复杂度问题
标准 Transformer
的自注意力机制需要计算序列中每个位置与其他所有位置的相似度,形成
内存占用分析:假设序列长度
- Query/Key/Value 矩阵:
MB - 注意力分数矩阵:
GB - 注意力权重矩阵:
GB
当
计算时间分析:矩阵乘法
长序列预测的特殊需求
时间序列预测任务中,我们通常需要根据历史
- 内存限制:无法在单卡 GPU 上训练,需要多卡并行或梯度累积
- 训练速度慢:每个 epoch 需要数小时甚至数天
- 信息冗余:注意力矩阵中大部分权重接近零,真正重要的信息只占少数
- 长期依赖建模困难:虽然理论上可以建模任意长度依赖,但实际中注意力权重会过度集中在最近的时间步
Informer 的解决思路
Informer 的基本思路:不是所有查询-键对都同等重要,可以只计算最重要的那些对。具体来说:
- ProbSparse
Self-Attention:通过查询稀疏性度量,只选择最重要的
个查询( , 是常数),将复杂度从 降到 - Self-Attention
Distilling:通过卷积和最大池化操作,将序列长度从
压缩到 ,进一步降低计算量 - Generative Style Decoder:用一次前向传播生成所有未来时间步,而不是自回归地逐个生成
ProbSparse Self-Attention 机制详解
标准 Self-Attention 回顾
给定输入序列
$$
Q = XW^Q, K = XW^K, V = XW^V
注意力权重矩阵
查询稀疏性的直觉
在时间序列中,大部分查询只会关注少数几个关键时间步。例如,在电力负荷预测中,当前时刻的查询可能主要关注:
- 最近几个时间步(短期趋势)
- 一周前的同一时刻(周期性)
- 某个异常事件发生的时间点(事件记忆)
其他时间步的注意力权重接近零,可以忽略。关键问题:如何在不计算完整注意力矩阵的情况下,识别出哪些查询是"重要的"?
查询稀疏性度量( Query Sparsity Measurement)
Informer
提出用查询的注意力分布与均匀分布的差异来衡量查询的重要性。对于第
$$
M(q_i, K) = j - {j=1}^{L} $$
直观理解:
- 第一项
:查询 与所有键的最大相似度 - 第二项
:查询 与所有键的平均相似度 - 差值越大,说明该查询的注意力分布越不均匀(越"稀疏"),越重要
为什么用这个度量:
- 如果查询的注意力分布接近均匀分布(所有位置权重相等),说明该查询没有特别关注的点,信息量低
- 如果查询的注意力分布高度集中(少数位置权重很大),说明该查询捕捉到了重要的模式,信息量高
采样策略
计算所有查询的稀疏性度量需要
- 随机采样
个键( 是超参数,通常取 5) - 对每个查询
,只在这 个键上计算稀疏性度量:
- 选择稀疏性度量最大的
个查询( 通常取 5)
复杂度分析:
- 采样键:
- 计算每个查询的稀疏性:
- 选择 top-
查询: (使用堆排序) - 总复杂度:
ProbSparse Attention 计算
选择出重要的查询后,只对这些查询计算完整的注意力:
其中
注意:虽然只计算了
如果查询
如果查询
实际上, Informer 的实现中,未被选中的查询位置直接使用
PyTorch 实现
1 | import torch |
Self-Attention Distilling 降维操作
设计动机
即使使用了 ProbSparse Attention,随着网络层数增加,序列长度
核心思想:注意力层输出的相邻位置往往包含冗余信息,可以通过卷积和池化操作提取主要特征,将序列长度减半。
实现细节
Distilling 操作包含两个步骤:
- 一维卷积:使用卷积核提取局部特征
- 最大池化:将序列长度从
压缩到 数学表达:
$$
X_{l+1} = (((X_l))) $$
其中
为什么用最大池化而不是平均池化:最大池化能够保留最显著的特征,这对于时间序列中的峰值、异常点等重要信息特别有效。
PyTorch 实现
1 | class DistillingLayer(nn.Module): |
Generative Style Decoder 生成式解码器
标准解码器的问题
标准 Transformer
的解码器使用自回归方式:给定历史序列,逐个生成未来时间步,每次生成都需要前一次的输出。对于预测长度
问题: 1. 推理速度慢:需要
Generative Style Decoder 设计
Informer 的解码器采用生成式风格:用一次前向传播生成所有未来时间步。
关键设计: 1. 输入构造:解码器输入 = 历史序列的末尾部分 + 占位符(全零向量)
- 历史部分:提供上下文信息
- 占位符:长度为预测长度
,用于生成未来值
掩码机制:使用掩码确保解码器只能看到历史信息,不能看到未来的占位符
输出提取:从占位符位置提取输出,得到未来
个时间步的预测
数学表达:
$$
X_{} = (X_{} , _{T d}) $$
其中
解码器输出:
PyTorch 实现
1 | class InformerDecoder(nn.Module): |
Informer vs Vanilla Transformer 详细对比
复杂度对比
| 组件 | Vanilla Transformer | Informer |
|---|---|---|
| Self-Attention | ||
| Distilling | 无 | |
| Decoder | ||
| 总体 |
内存占用对比
假设
Vanilla Transformer:
- 编码器注意力矩阵:
GB - 解码器注意力矩阵:
GB - 交叉注意力矩阵:
GB - 总计:
GB
Informer:
- 编码器 ProbSparse:
,其中 - 内存: GB - Distilling 后序列长度:
- 解码器 ProbSparse:
,其中 - 内存: GB - 总计:
GB(减少 95%)
训练速度对比
在 ETTm1 数据集(
| 模型 | 训练时间/epoch | 内存占用 | MAE | MSE |
|---|---|---|---|---|
| Vanilla Transformer | 45 min | 12 GB | 0.672 | 0.571 |
| Informer | 8 min | 3 GB | 0.577 | 0.419 |
Informer 的训练速度提升 5.6 倍,内存占用减少 75%,同时预测精度更高。
预测精度对比
在多个数据集上的平均结果:
| 数据集 | Metric | LSTM | Vanilla Transformer | Informer |
|---|---|---|---|---|
| ETTm1 | MAE | 0.845 | 0.672 | 0.577 |
| ETTm2 | MAE | 0.923 | 0.718 | 0.628 |
| Weather | MAE | 0.312 | 0.298 | 0.267 |
| Electricity | MAE | 0.274 | 0.201 | 0.193 |
Informer 在所有数据集上都取得了最佳性能。
时间复杂度分析
ProbSparse Attention 复杂度
标准 Self-Attention:
计算
: Softmax:
计算
: 总复杂度:
ProbSparse Attention: 采样
个键: 计算每个查询的稀疏性:
选择 top-
查询: (堆排序) 计算选中查询的注意力:
总复杂度:
复杂度降低:从 降到 ,当 时,计算量减少约 100 倍。
Distilling 复杂度
- 卷积:
(一维卷积的复杂度) - 最大池化:
- 总复杂度:
经过 层 Distilling,序列长度变为 ,总复杂度为:
$$
O(_{i=0}^{n-1} d) = O(L d) $$
总体复杂度
假设编码器有
编码器:
第 1 层:
Distilling:
第 2 层:
(忽略常数因子) Distilling:
...
总复杂度:
解码器: 输入长度:
复杂度:
总体:
PyTorch 完整实现
完整 Informer 模型
1 | import torch |
实战案例一:天气预测
数据集介绍
使用 Weather 数据集,包含 21 个气象站 4 年的每小时天气数据(温度、湿度、风速等 7 个特征)。任务是根据过去 720 小时( 30 天)的数据预测未来 96 小时( 4 天)的天气。
数据预处理
1 | import numpy as np |
模型训练
1 | import torch.optim as optim |
结果分析
在 Weather 数据集上的实验结果:
| 模型 | MAE | MSE | 训练时间/epoch |
|---|---|---|---|
| LSTM | 0.312 | 0.298 | 25 min |
| Vanilla Transformer | 0.298 | 0.285 | 45 min |
| Informer | 0.267 | 0.251 | 8 min |
Informer 在预测精度和训练速度上都取得了最佳性能。可视化预测结果:
1 | import matplotlib.pyplot as plt |
实战案例二:电力负荷长期预测
数据集介绍
使用 Electricity 数据集,包含 321 个客户 2 年的每小时用电量数据。任务是根据过去 168 小时( 7 天)的数据预测未来 336 小时( 14 天)的用电量。这是一个典型的长期预测任务。
特殊处理
长期预测的挑战: 1. 序列更长:输入序列
解决方案:
- 增加编码器层数:
,更好地捕捉长期依赖 - 使用时间特征:将小时、星期等时间特征编码到输入中
- 调整采样因子:
(更保守的采样,保留更多信息)
模型配置
1 | model = Informer( |
时间特征编码
1 | def create_time_features(df): |
训练结果
在 Electricity 数据集上的实验结果:
| 模型 | MAE | MSE | 训练时间/epoch |
|---|---|---|---|
| LSTM | 0.274 | 0.368 | 30 min |
| Vanilla Transformer | 0.201 | 0.273 | 60 min(内存不足,使用梯度累积) |
| Informer | 0.193 | 0.258 | 12 min |
关键发现: 1. Informer 能够有效处理长期预测任务( 336 小时) 2. 时间特征编码显著提升了预测精度( MAE 从 0.201 降到 0.193) 3. 增加编码器层数有助于捕捉长期依赖
预测可视化
1 | # 可视化长期预测结果 |
❓ Q&A: Informer 常见问题
Q1: ProbSparse Attention 会不会丢失重要信息?
A: 理论上可能,但实践中影响很小。原因: 1.
采样策略:通过随机采样
实验表明, ProbSparse Attention 的性能与标准 Attention 相当,但计算复杂度大幅降低。
Q2: Distilling 操作会不会破坏序列的时间顺序?
A: 不会。原因: 1. 最大池化保留关键信息:最大池化会选择每个窗口内最显著的特征,这些特征通常对应重要的时间点 2. 卷积提取局部模式:一维卷积能够捕捉局部的时间模式,然后再通过池化压缩 3. 位置编码保留顺序:位置编码确保模型仍然知道时间顺序 4. 实验验证:在多个数据集上的实验表明, Distilling 不会降低预测精度,反而通过降低噪声提升了性能
Q3: Generative Style Decoder 为什么能一次生成所有未来时间步?
A:
核心是占位符机制和掩码: 1.
占位符提供"画布":解码器输入包含
这与自回归生成不同:自回归是逐个生成,每次生成都依赖前一次的输出; Generative Style 是一次性生成所有位置,但通过掩码保证每个位置只依赖历史信息。
Q4: Informer 适合多变量时间序列吗?
A: 完全适合。 Informer
的设计天然支持多变量时间序列: 1.
输入维度:enc_in 和 dec_in
参数可以设置为变量的数量 2.
特征嵌入:TokenEmbedding
使用卷积将每个变量的时间序列投影到模型维度 3.
注意力机制: ProbSparse Attention
会同时考虑所有变量之间的关系 4.
输出维度:c_out
可以设置为变量的数量,支持多变量预测
在 ETT 、 Weather 、 Electricity 等数据集上, Informer 都取得了优异的多变量预测性能。
Q5: 如何选择采样因子 (
factor)?
A:
Q6: Informer 的编码器和解码器层数如何选择?
A: 层数选择原则: 1. 编码器层数(
- 默认: 2-3 层
- 长序列(
): 3-4 层,更好地捕捉长期依赖 - 短序列(
): 1-2 层即可
解码器层数(
): - 默认: 1-2 层
- 长期预测(
): 2-3 层 - 短期预测(
): 1 层即可
经验法则:编码器层数通常
解码器层数,因为编码器需要处理更长的序列
Q7: Informer 相比其他长序列模型(如 LogTrans 、 Reformer)有什么优势?
A: Informer 的优势: 1.
复杂度更低:
Q8: 如何处理缺失值?
A: 处理缺失值的几种方法: 1. 前向填充:用前一个时间步的值填充 2. 插值:使用线性插值或样条插值 3. 掩码机制:在注意力计算中,将缺失值位置的注意力权重设为 0 4. 特征工程:添加"是否缺失"的二进制特征 5. 模型层面:使用 Informer 的均值填充机制,缺失值会被自然地"平均化"
Q9: Informer 可以用于在线预测吗?
A: 可以,但需要特殊处理: 1. 滑动窗口:维护一个固定长度的历史窗口,每次新数据到达时,滑动窗口并重新预测 2. 增量更新:对于较长的序列,可以使用增量更新机制,只重新计算受影响的部分 3. 缓存机制:缓存编码器的输出,解码器只需要重新计算 4. 批处理:将多个请求批处理,提高 GPU 利用率
注意: Informer 的 Generative Style Decoder 一次生成所有未来时间步,非常适合在线预测场景。
Q10: 如何调试 Informer 模型?
A: 调试建议: 1.
检查注意力权重:可视化 ProbSparse Attention
选中的查询,确认模型关注了正确的时间点 2.
监控梯度:使用
torch.nn.utils.clip_grad_norm_ 防止梯度爆炸 3.
学习率调度:使用 CosineAnnealingLR 或 ReduceLROnPlateau
4.
验证集性能:如果验证集性能不提升,可能是过拟合,需要增加
Dropout 或减少模型容量 5.
预测可视化:可视化预测结果,检查是否存在系统性偏差(如总是高估或低估)
6. 消融实验:分别测试 ProbSparse Attention 、
Distilling 、 Generative Decoder 的贡献
总结要点
Informer 通过三个核心创新解决了长序列时间序列预测的
ProbSparse Self-Attention:通过查询稀疏性度量,只计算最重要的
个查询的注意力,将复杂度从 降到 2. Self-Attention Distilling:通过卷积和最大池化,将序列长度逐层减半,进一步降低计算量和内存占用 Generative Style Decoder:用一次前向传播生成所有未来时间步,避免了自回归的误差累积和串行计算问题
关键优势:
- 计算效率:训练速度提升 5-6 倍,内存占用减少 75-95%
- 预测精度:在多个数据集上超越 Vanilla Transformer 和 LSTM
- 可扩展性:能够处理长度超过 1000 的时间序列
适用场景:
- 长期预测任务(预测长度
) - 长输入序列(输入长度
) - 多变量时间序列预测
- 资源受限的环境(单卡 GPU 、内存有限)
未来方向:
- 结合时间特征编码(小时、星期、节假日)
- 探索更高效的稀疏注意力机制
- 研究自适应采样策略(根据数据特点动态调整采样因子)
- 扩展到其他时间序列任务(异常检测、分类、插值)
Informer 为长序列时间序列预测提供了一个高效、准确的解决方案,是 Transformer 在时间序列领域的重要突破。
- 本文标题:时间序列模型(八)—— Informer 长序列预测
- 本文作者:Chen Kai
- 创建时间:2020-06-15 16:15:00
- 本文链接:https://www.chenk.top/%E6%97%B6%E9%97%B4%E5%BA%8F%E5%88%97%E6%A8%A1%E5%9E%8B%EF%BC%88%E5%85%AB%EF%BC%89%E2%80%94%E2%80%94-Informer%E9%95%BF%E5%BA%8F%E5%88%97%E9%A2%84%E6%B5%8B/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!