Transformers 中 Informer 模型详解:ProbSparse 稀疏自注意力与长序列时间序列预测实战
Informer 是面向长序列时间序列预测(LSTF,Long Sequence Time-Series Forecasting)的稀疏 Transformer 架构。本文以 模型文档 为主线,结合当前仓库中 配置实现、模型实现 与 测试代码,逐层拆解其三大核心机制(ProbSparse 自注意力、自注意力蒸馏、生成式解码器),完整讲解 InformerConfig 全部参数,并给出基于 InformerModel / InformerForPrediction 的加载、训练与采样预测实战代码。
读完本文,你将掌握:Informer 相对标准 Transformer 解决了什么本质问题、稀疏注意力在源码层面如何实现与采样、如何配置预测长度/上下文长度/滞后序列/静态特征等参数,以及如何用开源预训练 checkpoint 完成一次端到端的概率时间序列预测。
Informer 的动机:标准 Transformer 为何难以直接用于 LSTF
Informer 模型由 Haoyi Zhou、Shanghang Zhang、Jieqi Peng、Shuai Zhang、Jianxin Li、Hui Xiong、Wancai Zhang 在论文 Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting 中提出。按 模型文档 的记录,该论文于 2020-12-14 发布在 HF Papers,模型于 2023-03-08 由贡献者 elisim 与 kashif 合入 Transformers。
许多真实应用(如电力消费规划)需要预测很长的时序。这类 LSTF 任务要求模型具备高"预测容量",即高效捕获输出与输入之间精确的长程依赖耦合。论文指出,直接套用标准 Transformer 会遇到三类严重障碍:
- 二次方时间复杂度:vanilla self-attention 的复杂度随序列长度平方增长,长上下文下不可负担;
- 高内存占用:完整的注意力分数矩阵在长序列下会耗尽显存;
- 编码器-解码器架构的固有限制:传统的 step-by-step 自回归解码推断速度慢,不适合超长输出的场景。
Informer 围绕这些问题给出三个标志性设计,模型文档对它们的概括是:
- ProbSparse self-attention:选"活跃(active)"query 而非"懒惰(lazy)"query,实现
O(L logL)的时间与内存复杂度,同时保持序列依赖对齐的相当性能; - self-attention distilling(自注意力蒸馏):通过逐层减半层输入来突出占主导的注意力,从而高效处理超长输入序列;
- 生成式风格解码器(generative style decoder):概念上简单,却能在一次前向中预测整段长序列,而非逐时间步滚动,大幅提升长序列预测的推理速度。
仓库中的模型文档明确说明该模型为"稀疏 Transformer",用来缓解标准注意力在计算与内存上的二次开销;这也是理解其全部设计细节的总纲。
源码脉络:modular 文件驱动的一体化实现
在继续深入原理前,先梳理当前仓库中 Informer 的代码布局(位于 src/transformers/models/informer/):
| 文件 | 职责 |
|---|---|
| configuration_informer.py | InformerConfig,全部超参定义、默认值推导与架构校验 |
| modeling_informer.py | InformerModel、InformerForPrediction 以及注意力度量、标定器、嵌入与编码器/解码器全栈实现(约 1773 行) |
| modular_informer.py | Informer 的 modular 源文件,modeling_informer.py 由其自动生成,文件头标注"Do NOT edit this file manually",任何改动都应落在 modular 文件上 |
| init.py | 模块导出入口 |
模型顶层类与标准 Transformer 时序家族(Time Series Transformer 等)的输入输出约定保持一致。对应的集成测试位于 tests/models/informer/test_modeling_informer.py,其中 InformerModelTester 定义了统一的测试超参(如 batch_size=13、prediction_length=7、context_length=14),InformerModelTest 继承 ModelTesterMixin 校验前向、隐藏状态形状、注意力张量形状与缓存行为。
推理链路顶层结构
从 modeling_informer.py 的顶层类定义可以看出完整推理管线被拆成了清晰的模块:
InformerModel(第 994 行起):时序专用 encoder-decoder,承担输入特征构建、标定与变换;InformerForPrediction(第 1357 行起):在InformerModel之上叠加概率分布输出头与 NLL 损失,并提供generate采样预测入口;InformerEncoder/InformerDecoder:标准的 Transformer encoder/decoder 栈,但 encoder 内嵌 distilling 卷积层;- 分布式工具类:
StudentTOutput、NormalOutput、NegativeBinomialOutput等分布头定义在 src/transformers/time_series_utils.py(InformerForPrediction的__init__按config.distribution_output从这里选取分布)。
InformerConfig:核心配置参数全解读
InformerConfig(见 configuration_informer.py)继承 PreTrainedConfig,声明 model_type = "informer"。它把上游标准名称映射到 Informer 命名:
attribute_map = {
"hidden_size": "d_model",
"num_attention_heads": "encoder_attention_heads",
"num_hidden_layers": "encoder_layers",
"initializer_range": "init_std",
}
这意味着当你从其它 Transformer checkpoint 转换配置、或使用通用工具时,Transformers 会自动完成字段映射。下面按配置文件的 docstring 与源码逐一解释全部参数。
时序任务核心参数
| 参数 | 类型 / 默认值 | 含义与建议 |
|---|---|---|
prediction_length |
int,必填 |
解码器的预测长度,即模型的预测时域(horizon)。通常由数据集决定,建议按任务设置合适值 |
context_length |
int,默认等于 prediction_length |
编码器看到的上下文长度。若为 None,在 __post_init__ 中被自动赋为 prediction_length |
input_size |
int,默认 1 |
目标变量尺寸。单变量目标为 1,多变量目标 > 1 |
lags_sequence |
list[int],默认 [1, 2, 3, 4, 5, 6, 7] |
输入序列的滞后阶数,常由数据频率决定(默认覆盖一周的日滞后)。建议按数据集特性调整 |
scaling |
str / bool,默认 "mean" |
输入目标的标定方式:"mean"(均值标定)、"std"(标准差标定)、None/False(不标定);若传 True 等价于 "mean" |
协变量 / 特征维度参数
| 参数 | 类型 / 默认值 | 含义 |
|---|---|---|
num_dynamic_real_features |
int,默认 0 |
动态实数特征数量(随时间变化且在预测期必须已知) |
num_static_real_features |
int,默认 0 |
静态实数特征数量(随时间保持不变) |
num_static_categorical_features |
int,默认 0 |
静态类别特征数量(模型会为它学习 embedding) |
num_time_features |
int,默认 0 |
时间特征数量(如"月""日"等编码向量) |
cardinality |
list[int] |
每个静态类别特征的取值个数,长度须等于 num_static_categorical_features;若后者为 0 则可省略 |
embedding_dimension |
list[int] |
每个静态类别特征对应的 embedding 维度,长度同样须匹配类别数 |
__post_init__ 中的默认值推导逻辑值得注意(configuration_informer.py):
context_length缺省时取prediction_length;lags_sequence缺省时为[1, 2, 3, 4, 5, 6, 7];- 若
num_static_categorical_features == 0,cardinality被设为[0]; - 若
num_static_categorical_features > 0但未提供embedding_dimension,则按min(50, (cat + 1) // 2)自动生成; - 关键的
feature_size由input_size * len(lags_sequence) + _number_of_features计算得出。
其中 _number_of_features 属性(configuration_informer.py)汇总了 sum(embedding_dimension)、动态/时间/静态实数特征数,外加 input_size * 2——这两个来自标定器产生的 log1p(abs(loc)) 与 log(scale) 特征。它决定了 InformerValueEmbedding 的输入通道数,也解释了为何输入构建阶段会自动把 loc/scale 作为静态特征喂入网络。
模型容量与训练参数
| 参数 | 默认值 | 含义 |
|---|---|---|
d_model |
64 |
模型隐层维度(原版 "hidden_size") |
encoder_ffn_dim / decoder_ffn_dim |
32 / 32 |
编码器/解码器前馈网络维度 |
encoder_attention_heads / decoder_attention_heads |
2 / 2 |
注意力头数 |
encoder_layers / decoder_layers |
2 / 2 |
层数 |
is_encoder_decoder |
True |
固定为 encoder-decoder 架构 |
activation_function |
"gelu" |
FFN 激活函数 |
dropout / attention_dropout / activation_dropout |
0.05 / 0.1 / 0.1 |
整体 / 注意力 / FFN 两层之间的 dropout |
encoder_layerdrop / decoder_layerdrop |
0.1 / 0.1 |
训练期随机跳过层的概率(LayerDrop) |
init_std |
0.02 |
权重初始化标准差 |
use_cache |
True |
是否使用自回归缓存(Cache) |
Informer 特有机制参数
| 参数 | 默认值 | 含义 |
|---|---|---|
attention_type |
"prob" |
编码器使用的注意力类型:"prob" 为 Informer 的 ProbSparse 注意力,"full" 为普通自注意力 |
sampling_factor |
5 |
ProbSparse 采样因子,仅在 attention_type="prob" 时生效,控制缩减后的 query 矩阵 Q_reduce 长度 |
distil |
True |
编码器是否启用蒸馏(distilling) |
num_parallel_samples |
100 |
推理时每个时间步并行生成的样本数(用于概率预测) |
loss 参数默认 "nll"(负对数似然),目前是参数化分布唯一支持的损失;distribution_output 默认 "student_t",可选 "normal"、"negative_binomial"。
从配置初始化一个模型
配置 docstring 给出了最小可运行示例:
>>> from transformers import InformerConfig, InformerModel
>>> # 用 12 个时间步作为预测长度初始化配置
>>> configuration = InformerConfig(prediction_length=12)
>>> # 用随机权重初始化模型
>>> model = InformerModel(configuration)
>>> # 访问模型配置
>>> configuration = model.config
若想直接使用社区预训练 checkpoint,也可以跳过 InformerConfig,用 from_pretrained 加载(参考本文后面示例中的 "huggingface/informer-tourism-monthly")。
ProbSparse 自注意力的源码实现
ProbSparse 注意力是 Informer 最具辨识度的创新,其核心类为 InformerProbSparseAttention(modeling_informer.py),docstring 与论文保持一致:"选择活跃 query 而非懒惰 query,提供稀疏 Transformer,缓解 vanilla attention 的二次计算与内存需求"。
关键计算步骤
在 forward 中(modeling_informer.py),Q/K/V 投影完成并 reshape 到多头后,算法依次执行:
-
有放回地采样一部分 key:设 key 时间长度为
L_K,query 时间长度为L_Q,先计算u_part = min(sampling_factor * L_Q * log1p(L_K), L_K),然后torch.randint在L_K内采样u_part个 index,得到缩减的k_sample。代码使用math.ceil(math.log1p(L))近似log L,这是论文中O(L log L)复杂度的直接体现。 -
用缩减 key 估计稀疏度并选 top-k query:对所有 query 计算与采样 key 的点积
Q_K_sampled,得到每个 query 的稀疏度量M = max(Q_K_sampled) - mean(Q_K_sampled)(modeling_informer.py),再对M取topk(u),u = min(sampling_factor * log1p(L_Q), L_Q),得到"最活跃"的 query 索引q_reduce。 -
仅对活跃 query 做完整注意力:用
q_reduce与全部 key 计算attn_weights与 softmax,dropout 后与 value 做bmm。 -
上下文补齐(context filling):非活跃位置的输出并不是丢弃,而是由 value 的统计量填充——解码器(
is_decoder=True)用 value 沿时间维的cumsum作为上下文(modeling_informer.py),编码器则用 value 沿时间维的均值广播(modeling_informer.py),随后把稀疏注意力的真实输出写回到 top-k 位置(modeling_informer.py)。这样既保持了输出张量的形状,又让梯度能沿着挑选出的活跃路径传播。
采样因子对稀疏度的控制
sampling_factor 直接决定上面 u_part 与 u 的规模:因子越大,参与稀疏度量与最终注意力的 query/key 越多,接近 full attention,开销上升;因子越小越稀疏、越省显存与算力。若 sampling_factor 或长度取极端值使 u == 0,代码会退化为使用全部 query(modeling_informer.py)。
full attention 的可切换性
编码器的注意力在 InformerEncoderLayer 中会根据 config.attention_type 选择 InformerAttention(普通实现)还是 InformerProbSparseAttention。这一点让 Informer 也可以作为普通 Transformer 时序模型运行,便于做稀疏/非稀疏的消融对比——正如配置 docstring 所说明的 attention_type="full" 表示"vanilla transformer 的标准自注意力"。
自注意力蒸馏(Distilling)与编码器结构
InformerEncoder(modeling_informer.py)负责把原始输入转成可计算的特征序列:
- 用
InformerValueEmbedding(modeling_informer.py)将feature_size维输入映射到d_model(内部使用 Conv1d + GELU,随后投影); - 叠加
InformerSinusoidalPositionalEmbedding(modeling_informer.py)生成的正弦位置向量,经过layernorm_embedding与 dropout; - 逐层执行编码器层,并在相邻层之间根据
config.distil插入InformerConvLayer。
蒸馏的关键在于 InformerConvLayer(modeling_informer.py):它用 kernel_size=3、stride 为 2 的 Conv1d + ELU + MaxPool1d 把序列的时间维减半。编码器构建 conv_layers 的代码显示(modeling_informer.py):当 distil=True 时,encoder_layers - 1 个层后各接一个卷积层、最后一层不接;当 distil=False 时则完全不使用卷积。这种"逐层减半"正是论文所说"突出主导注意力、高效处理超长输入"的实现——深层编码器的序列长度指数级收缩,显著降低后续层与交叉注意力的计算量。测试中的 @slow 用例 expected_shape = torch.Size((64, model.config.context_length // 8, model.config.d_model))(test_modeling_informer.py)恰好验证了 distilling 后长度除以 8 的效果。
输入特征体系:past、future 与协变量约定
时序 Transformer 与 BERT 这类模型的关键区别之一在于位置信息由外部时间特征提供而非内部学习。从 InformerModel.forward、InformerForPrediction.forward 的 docstring(modeling_informer.py)可以整理出完整输入契约:
past_values:形状(batch_size, sequence_length)或加input_size维。序列长度必须大于context_length,因为模型需要更长的历史来构造滞后特征;_past_length = context_length + max(lags_sequence)(modeling_informer.py),在默认lags_sequence下即context_length + 7。past_time_features:形状(batch_size, sequence_length, num_features),num_features = num_time_features + num_dynamic_real_features。它们是输入的时间特征(月份、日期、节假日,乃至随时间单调增长的 age 特征),承担"位置编码"的角色。动态实数协变量也可以拼接进来,前提是预测期可知。past_observed_mask:布尔张量,1 表示观测到、0 表示缺失(缺失值须先用 0 填充)。它同时参与标定器(scaler)的均值/方差统计。static_categorical_features/static_real_features:全时间步恒定。类别特征会经InformerFeatureEmbedder逐特征查 embedding 后拼接(modeling_informer.py),典型例子是时间序列 ID、促销信息等。注意 Informer 只对静态类别特征学习 embedding。future_values:形状(batch_size, prediction_length),训练时的标签,配合future_time_features一起送入解码器。future_time_features:预测窗口的时间特征,推理阶段由调用方提供,模型据此生成未来输入。
标定流程在 create_network_inputs 中体现(modeling_informer.py):取最近 context_length 的观测上下文喂给 scaler,得到 loc 与 scale,再对 past 与 future 拼接后的整段序列做 (x - loc) / scale 归一化。InformerModel.__init__(modeling_informer.py)根据 config.scaling 选择 InformerMeanScaler / InformerStdScaler / InformerNOPScaler 三种标定器(定义于 modeling_informer.py),标准差标定还带 minimum_scale=1e-5 的数值保护。loc、scale 与静态特征会作为模型的额外输入(log1p(abs(loc))、log(scale))参与特征拼装,并在输出中一并返回以便反归一化。
InformerModel:编码器-解码器组合使用
InformerModel 内部维护 self.encoder、self.decoder 与 scaler/embedder。它的 forward 流程(modeling_informer.py)是:
- 调用
create_network_inputs生成规整后的transformer_inputs; - 把前
context_length段送入 encoder; - 把
context_length之后(含 future)的段送入 decoder,做 encoder-decoder 交叉注意力; - 返回
Seq2SeqTSModelOutput(含 decoder 输出、encoder 隐状态、loc、scale、static_features)。
当只给 past 不给 future 时,它也能运行——解码器输入会回退到零张量占位,为生成式预测预留接口。
模型 docstring 的官方示例展示了训练形态的调用(下载一个批量数据文件后直接前向):
>>> from huggingface_hub import hf_hub_download
>>> import torch
>>> from transformers import InformerModel
>>> file = hf_hub_download(
... repo_id="hf-internal-testing/tourism-monthly-batch", filename="train-batch.pt", repo_type="dataset"
... )
>>> batch = torch.load(file)
>>> model = InformerModel.from_pretrained("huggingface/informer-tourism-monthly")
>>> # 训练时同时提供 past 与 future 值及可能的附加特征
>>> outputs = model(
... past_values=batch["past_values"],
... past_time_features=batch["past_time_features"],
... past_observed_mask=batch["past_observed_mask"],
... static_categorical_features=batch["static_categorical_features"],
... static_real_features=batch["static_real_features"],
... future_values=batch["future_values"],
... future_time_features=batch["future_time_features"],
... )
>>> last_hidden_state = outputs.last_hidden_state
InformerForPrediction:概率输出头、训练损失与采样预测
InformerForPrediction(modeling_informer.py)在 InformerModel 之上做了三件事:
- 依据
config.distribution_output实例化StudentTOutput/NormalOutput/NegativeBinomialOutput(定义于 src/transformers/time_series_utils.py),并用get_parameter_projection(d_model)把 decoder 输出投影为分布参数; - 依据
config.loss选择nll作为损失; - 对缺失标签用
weighted_average掩码平均(modeling_informer.py),避免nan * 0污染梯度。
官方 docstring 的训练 + 推理示例是"复制即用"的模板:
>>> from huggingface_hub import hf_hub_download
>>> import torch
>>> from transformers import InformerForPrediction
>>> file = hf_hub_download(
... repo_id="hf-internal-testing/tourism-monthly-batch", filename="train-batch.pt", repo_type="dataset"
... )
>>> batch = torch.load(file)
>>> model = InformerForPrediction.from_pretrained("huggingface/informer-tourism-monthly")
>>> # 训练:同时提供 past 与 future 值
>>> outputs = model(
... past_values=batch["past_values"],
... past_time_features=batch["past_time_features"],
... past_observed_mask=batch["past_observed_mask"],
... static_categorical_features=batch["static_categorical_features"],
... static_real_features=batch["static_real_features"],
... future_values=batch["future_values"],
... future_time_features=batch["future_time_features"],
... )
>>> loss = outputs.loss
>>> loss.backward()
>>> # 推理:只提供 past 值,模型自动生成未来样本
>>> outputs = model.generate(
... past_values=batch["past_values"],
... past_time_features=batch["past_time_features"],
... past_observed_mask=batch["past_observed_mask"],
... static_categorical_features=batch["static_categorical_features"],
... static_real_features=batch["static_real_features"],
... future_time_features=batch["future_time_features"],
... )
>>> mean_prediction = outputs.sequences.mean(dim=1)
generate 的并行采样语义
InformerForPrediction.generate(modeling_informer.py)是"生成式解码器"的落地:在 forward 中传入 future_values=None,编码器处理历史、交叉注意力缓存被复用(use_cache=True);随后按 num_parallel_samples(默认 100)把 loc/scale 做 repeat_interleave,对分布进行并行采样来获得多个轨迹。返回的 SampleTSPredictionOutput.sequences 形状为 (batch_size, num_parallel_samples, prediction_length)(多变量时为 (batch_size, num_parallel_samples, prediction_length, input_size)),因此上面的 mean_prediction = outputs.sequences.mean(dim=1) 就是对 100 条样本取平均得到的点预测。
值得注意的源码细节:forward 中只要提供了 future_values 就会强制 use_cache=False(modeling_informer.py),因为训练形态下 decoder 一次性看到整段 future,不需要自回归缓存。
测试与可验证的行为约定
测试文件 一方面作为 CI 保护,另一方面也精确记录了模型的行为规格:
InformerModelTester的默认超参组合(test_modeling_informer.py)给出了一个可直接照抄的小配置:batch_size=13、prediction_length=7、context_length=14,并显式传递lags_sequence、scaling、num_time_features等字段——从中可以看到静态类别特征被编码成长度为cardinality[0]的 id、静态实数特征为单列、past_time_features的第三维等于config.num_time_features等张量约定;InformerModelTest断言 encoder/decoder 的注意力形状分别为(heads, context_length, context_length)与(heads, prediction_length, context_length)量级(test_modeling_informer.py),并覆盖 cache、padding、generate输出形状((batch, num_parallel_samples, prediction_length))等(test_modeling_informer.py)。
也就是说,本文前面提到的所有关键约定(_past_length、encoder 输入长度为 context_length、decoder 输出长度为 prediction_length、generate 采样维度)都能在测试断言中找到对应证据。
小结
Informer 在 Transformers 中的实现可以归纳为三个"机制—代码"对照:
| 论文机制 | 源码落点 | 关键配置 |
|---|---|---|
| ProbSparse 自注意力 | InformerProbSparseAttention |
attention_type="prob"、sampling_factor |
| 自注意力蒸馏 | InformerConvLayer + InformerEncoder.conv_layers |
distil=True、encoder_layers |
| 生成式解码器 | InformerForPrediction.generate(并行采样) |
prediction_length、num_parallel_samples |
同时它继承了 Transformers 时序家族统一的输入协议(past/future 值、时间特征、观测掩码、静态类别/实数特征、标定器),并通过 distribution_output 支持 Student-T / Normal / Negative-Binomial 概率输出,从而既能做点预测,也能输出带不确定性的样本轨迹。
进一步探索可以从三个入口继续:完整的端到端训练/微调流程见 examples 与官方模型卡片配套脚本;想对比 ProbSparse 与普通注意力的行为差异,可阅读 InformerAttention 与 InformerProbSparseAttention 两段实现并切换 attention_type;若要给 InformerConfig 增加字段或调整默认逻辑,请遵循 modular 工作流修改 modular_informer.py,再由其重新生成 modeling_informer.py。模型文档原文见 docs/source/en/model_doc/informer.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00