Appearance
TimesNet 总览
第一性
TimesNet 的核心不是 attention,而是:==时间序列的变化常由多个周期共同组成==。代码先用 FFT 找主要周期,再把一维时间轴按周期折成二维网格,最后用
Conv2d同时建模“周期内变化”和“周期间变化”。
1. 论文问题与动机
普通时序模型直接在一维时间轴上建模:
text
t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11这个视角能表达相邻时间点的连续变化,但不能直接表达“第几个周期块”和“周期内部第几个位置”的二维关系。
TimesNet 的论文直觉是:如果主周期是
text
原始 1D:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
按 period=4 折成 2D:
row0: [1, 2, 3, 4]
row1: [5, 6, 7, 8]
row2: [9, 10, 11, 12]
列方向 = 周期内部位置
行方向 = 周期块之间变化因此 TimesNet 的代码主线就是:
text
1D 时序
到 FFT 找主周期
到 period 网格化
到 Conv2d 建模二维变化
到 多周期加权融合
到 预测输出2. 与已学模型的核心差异
| 维度 | DLinear | PatchTST | Autoformer | TimesNet |
|---|---|---|---|---|
| 核心 token 视角 | 每个变量一条线性序列 | patch token | 时间 token + seasonal/trend | 周期折叠后的 2D 网格 |
| 主要归纳偏置 | 趋势/季节线性外推 | patch 局部片段 | 分解 + FFT lag 聚合 | FFT 周期 + Conv2d |
| 是否用 attention | 否 | 是 | 用 AutoCorrelation 替代 attention | 否 |
| 频域作用 | 无 | 无 | 用 FFT 做互相关 | 用 FFT 选主周期 |
| 核心张量变形 | (B,T,C) 到 (B,C,T) | unfold patch | Q/K/V 到 lag 聚合 | (B,T,D) 到 (B,D,周期段数,period) |
| 预测区处理 | Linear 直接输出未来 | head 输出未来窗口 | decoder 并行生成 | predict_linear 先把 hidden 时间长度扩到 seq_len + pred_len |
3. 论文组件到代码对应表
| 论文/原理组件 | 真实代码位置 | 精读文档 |
|---|---|---|
| TFB 参数进入模型 | TransformerAdapter._process()、TimesNet.forward() | [[01-Layer0-接入界面]] |
| forecast 主链 | TimesNet.forecast() | [[02-Layer1-forecast主链]] |
| 输入 embedding | DataEmbedding.forward() | [[03A-Layer2A-DataEmbedding]] |
| 周期发现 | FFT_for_Period(x, k) | [[03B1-Layer3-FFT_for_Period]] |
| TimesBlock 主体 | TimesBlock.forward(x) | [[03B-Layer2B-TimesBlock]] |
| 1D 到 2D 周期网格 | reshape(B, length // period, period, N).permute(0, 3, 1, 2) | [[03B-Layer2B-TimesBlock]] |
| 多尺度二维卷积 | Inception_Block_V1.forward(x) | [[03B2-Layer3-Inception_Block_V1]] |
| 多周期加权融合 | torch.stack、softmax、sum | [[03B-Layer2B-TimesBlock]] |
| 输出与反归一化 | projection、stdev/means broadcast | [[02-Layer1-forecast主链]] |
4. TFB 调用链
接入层重点
TimesNet 是 encoder-only 风格的预测模型。
TransformerAdapter._process()仍会构造dec_input,但TimesNet.forecast()实际不使用x_dec和x_mark_dec,真正进入计算的是x_enc与x_mark_enc。
5. 文档 BFS 树形索引
阅读时按 BFS 走:先看同一层的全貌,再进入下层组件。不要在 forecast() 里看到 TimesBlock 就立刻钻到 Conv2d,否则会失去主链坐标。
6. 全局 Toy 参数
TimesNet 文档统一用这套 toy 参数。真实调试参数可以更大,但文档里的数学例子都按这里计算。
| 参数 | 值 | 含义 |
|---|---|---|
B | 3 | batch size |
seq_len | 8 | 输入历史长度 |
pred_len | 5 | 预测长度 |
T | 13 | seq_len + pred_len,TimesBlock 内部全长度 |
enc_in = c_out | 4 | 输入与输出变量数 |
time_dims | 4 | 小时级 timeF 时间特征数 |
d_model | 6 | embedding 后 hidden channel |
d_ff | 7 | Inception 中间 channel |
top_k | 2 | FFT 选两个主周期 |
num_kernels | 3 | kernel_size = 1, 3, 5 |
e_layers | 1 | 只跑一个 TimesBlock,便于调试 |
dropout | 0.0 | 文档例子关闭随机性 |
维度说明
enc_in=4与time_dims=4数值相同,但语义不同:前者是原始变量数,后者是时间标记维度。读 shape 时必须看变量名,不只看数字。
7. 端到端形状主线
text
input / x_enc:
(B, seq_len, enc_in) = (3, 8, 4)
Normalization:
x_enc 保持 (3, 8, 4)
means/stdev 为 (3, 1, 4)
DataEmbedding:
(3, 8, 4) + x_mark(3, 8, 4) 到 enc_out(3, 8, 6)
predict_linear:
enc_out.permute(0,2,1): (3, 6, 8)
Linear(8 到 13): (3, 6, 13)
permute back: (3, 13, 6)
TimesBlock:
FFT 选 period,例如 [4, 2]
period=4 分支: (3,13,6) padding 到 (3,16,6) 再折成 (3,6,4,4)
period=2 分支: (3,13,6) padding 到 (3,14,6) 再折成 (3,6,7,2)
多周期融合后回到 (3,13,6)
projection + De-Normalization:
Linear(6 到 4): (3,13,4)
乘 stdev 加 means: (3,13,4)
forward tail slice:
dec_out[:, -5:, :] 到 (3,5,4)8. 推荐阅读路径
快速直觉版:
text
[[00-总览]]
到 [[02-Layer1-forecast主链]] §5.1
到 [[03B-Layer2B-TimesBlock]] §5.1
到 [[05-收束]]完整代码精读版:
text
[[01-Layer0-接入界面]]
到 [[02-Layer1-forecast主链]]
到 [[03A-Layer2A-DataEmbedding]]
到 [[03B-Layer2B-TimesBlock]]
到 [[03B1-Layer3-FFT_for_Period]]
到 [[03B2-Layer3-Inception_Block_V1]]
到 [[05-收束]]调试版:
text
[[调试形参]]
到 在 VSCode/PyCharm 打断点
到 对照 [[02-Layer1-forecast主链]] 和 [[03B-Layer2B-TimesBlock]]