Skip to content

TimesNet 总览

第一性

TimesNet 的核心不是 attention,而是:==时间序列的变化常由多个周期共同组成==。代码先用 FFT 找主要周期,再把一维时间轴按周期折成二维网格,最后用 Conv2d 同时建模“周期内变化”和“周期间变化”。


1. 论文问题与动机

普通时序模型直接在一维时间轴上建模:

text
t0  t1  t2  t3  t4  t5  t6  t7  t8  t9  t10 t11

这个视角能表达相邻时间点的连续变化,但不能直接表达“第几个周期块”和“周期内部第几个位置”的二维关系。

TimesNet 的论文直觉是:如果主周期是 p=4,那么长度 12 的序列可以折成:

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. 与已学模型的核心差异

维度DLinearPatchTSTAutoformerTimesNet
核心 token 视角每个变量一条线性序列patch token时间 token + seasonal/trend周期折叠后的 2D 网格
主要归纳偏置趋势/季节线性外推patch 局部片段分解 + FFT lag 聚合FFT 周期 + Conv2d
是否用 attention用 AutoCorrelation 替代 attention
频域作用用 FFT 做互相关用 FFT 选主周期
核心张量变形(B,T,C)(B,C,T)unfold patchQ/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主链]]
输入 embeddingDataEmbedding.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.stacksoftmaxsum[[03B-Layer2B-TimesBlock]]
输出与反归一化projectionstdev/means broadcast[[02-Layer1-forecast主链]]

4. TFB 调用链

接入层重点

TimesNet 是 encoder-only 风格的预测模型。TransformerAdapter._process() 仍会构造 dec_input,但 TimesNet.forecast() 实际不使用 x_decx_mark_dec,真正进入计算的是 x_encx_mark_enc


5. 文档 BFS 树形索引

阅读时按 BFS 走:先看同一层的全貌,再进入下层组件。不要在 forecast() 里看到 TimesBlock 就立刻钻到 Conv2d,否则会失去主链坐标。


6. 全局 Toy 参数

TimesNet 文档统一用这套 toy 参数。真实调试参数可以更大,但文档里的数学例子都按这里计算。

参数含义
B3batch size
seq_len8输入历史长度
pred_len5预测长度
T13seq_len + pred_len,TimesBlock 内部全长度
enc_in = c_out4输入与输出变量数
time_dims4小时级 timeF 时间特征数
d_model6embedding 后 hidden channel
d_ff7Inception 中间 channel
top_k2FFT 选两个主周期
num_kernels3kernel_size = 1, 3, 5
e_layers1只跑一个 TimesBlock,便于调试
dropout0.0文档例子关闭随机性
维度说明

enc_in=4time_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]]

*记录并在线阅读我的笔记*