Skip to content

iTransformer 调试形参

Abstract

这篇只做一件事:

保存用于学习 iTransformer 代码运行流程的 PyCharm / VSCode 参数,并让 encoder、DataEmbedding_inverted、FullAttention 至少完整跑一遍。


1. 推荐使用 ETTh1 的原因

iTransformer 的核心不是 decoder,而是:

text
时间步 token -> 变量 token

因此默认调试数据使用 ETTh1.csv。它是小时级多变量数据,通常有 7 个数值变量,能在断点里看到:

text
x_enc:                 (B, seq_len, N) = (2, 24, 7)
x_mark_enc:            (B, seq_len, time_dims) = (2, 24, 4)
DataEmbedding_inverted:
  x_enc.permute:       (2, 7, 24)
  x_mark_enc.permute:  (2, 4, 24)
  concat:              (2, 11, 24)
  Linear(24 -> 32):    (2, 11, 32)
FullAttention scores:  (2, 2, 11, 11)

token_count = N + time_dims = 7 + 4 = 11。这能直接观察变量 token 和时间特征 token 之间的 attention。


2. PyCharm 配置

Script path

text
D:\1sudyta\1ai-self\aistyle\TFB\scripts\run_benchmark.py

Working directory

text
D:\1sudyta\1ai-self\aistyle\TFB

Environment variables

text
KMP_DUPLICATE_LIB_OK=TRUE

3. Parameters

直接复制下面这一整行到 PyCharm 的 Parameters

text
--config-path rolling_forecast_config.json --data-name-list ETTh1.csv --model-name time_series_library.iTransformer --adapter transformer_adapter --model-hyper-params "{\"batch_size\":2,\"d_model\":32,\"d_ff\":128,\"e_layers\":1,\"factor\":1,\"horizon\":6,\"n_heads\":2,\"norm\":true,\"seq_len\":24,\"dropout\":0.0,\"lr\":0.0001,\"num_epochs\":1,\"num_workers\":0,\"output_attention\":0}" --strategy-args "{\"horizon\":6,\"tv_ratio\":0.8,\"train_ratio_in_tv\":0.75,\"stride\":6,\"num_rollings\":2}" --num-workers 1 --timeout 600 --save-path debug\ETTh1_iTransformer_rolling_min
模型名大小写

这里必须写 time_series_library.iTransformer。仓库真实类名是 iTransformer,不是 ITransformer


4. VSCode 调试配置

VSCode 不把参数写成一整行,而是写进 .vscode/launch.jsonargs 数组。

先在 VSCode 里执行:

text
Ctrl+Shift+P
-> Python: Select Interpreter
-> 选择 D:\Anaconda\envs\tfb\python.exe

然后在仓库根目录创建或修改:

text
D:\1sudyta\1ai-self\aistyle\TFB\.vscode\launch.json

加入下面配置:

json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "TFB iTransformer rolling debug",
      "type": "python",
      "request": "launch",
      "program": "${workspaceFolder}\\scripts\\run_benchmark.py",
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "env": {
        "KMP_DUPLICATE_LIB_OK": "TRUE"
      },
      "args": [
        "--config-path", "rolling_forecast_config.json",
        "--data-name-list", "ETTh1.csv",
        "--model-name", "time_series_library.iTransformer",
        "--adapter", "transformer_adapter",
        "--model-hyper-params", "{\"batch_size\":2,\"d_model\":32,\"d_ff\":128,\"e_layers\":1,\"factor\":1,\"horizon\":6,\"n_heads\":2,\"norm\":true,\"seq_len\":24,\"dropout\":0.0,\"lr\":0.0001,\"num_epochs\":1,\"num_workers\":0,\"output_attention\":0}",
        "--strategy-args", "{\"horizon\":6,\"tv_ratio\":0.8,\"train_ratio_in_tv\":0.75,\"stride\":6,\"num_rollings\":2}",
        "--num-workers", "1",
        "--timeout", "600",
        "--save-path", "debug\\ETTh1_iTransformer_rolling_min"
      ]
    }
  ]
}

5. 这组参数的第一性

这组参数不是为了刷 benchmark 分数,而是为了读代码。

text
1. ETTh1 是多变量小时级数据,可以看到变量 token attention。
2. seq_len=24、horizon=6,窗口较小,断点里的 tensor 不会太大。
3. e_layers=1,保证 Encoder.forward 的 for 循环至少执行 1 次。
4. n_heads=2,保证 AttentionLayer 会拆成两个 head。
5. d_model=32,d_keys = d_model // n_heads = 16,shape 清楚。
6. dropout=0.0,减少随机性,便于比较断点里的 tensor。
7. num_epochs=1、num_rollings=2,保证快速跑到模型主链。

6. 参数含义

数据与策略参数

参数当前值作用
--config-pathrolling_forecast_config.json使用 rolling forecast 策略
--data-name-listETTh1.csv小规模多变量小时级数据,适合观察变量 token
horizon6每次预测未来 6 步,同时映射成 pred_len=6
tv_ratio0.8前 80% 进入 train/valid 区域
train_ratio_in_tv0.75train/valid 区域内部再切训练段
stride6rolling 每次往后移动 6 步
num_rollings2只滚动 2 次,减少调试时间
--num-workers1benchmark 外层只开 1 个 worker,方便断点
--timeout600单任务最长 600 秒

模型参数

参数当前值进入 iTransformer 后的意义
model-nametime_series_library.iTransformer加载 models/iTransformer.py
adaptertransformer_adapterTransformerAdapter._process(...) 统一接口
batch_size2每个训练 batch 两条样本,shape 更小
seq_len24encoder 输入历史长度,也是 DataEmbedding_inverted 的 Linear 输入维
horizon6Config 会设置 pred_len=6
d_model32embedding / encoder hidden size
n_heads2FullAttention 多头数
d_keys=d_values16dmodel/nheads=32/2=16 得到
d_ff128EncoderLayer 里的 Conv1d FFN 隐藏维
e_layers1encoder loop 跑 1 次
factor1传入 FullAttention 构造函数;当前 FullAttention 主链不使用 top-k
dropout0.0关闭 dropout,方便调试
num_epochs1只训练 1 轮,保证能进入训练 forward
output_attention0不返回 attention 权重,先看主输出
normtrueadapter required arg,用于 TFB 模型工厂接口对齐;iTransformer.py 主链不读取 configs.norm

7. 当前参数下的关键 shape

ETTh1.csv 多变量小时级数据为例:

text
B = 2
seq_len = 24
pred_len = horizon = 6
N = enc_in = c_out = 7
time_dims = 4
token_count = N + time_dims = 11
d_model = 32
n_heads = 2
d_keys = d_values = 16

TransformerAdapter._process(...)

text
input / x_enc:        (2, 24, 7)
input_mark:           (2, 24, 4)
target:               (2, label_len + horizon, 7)
dec_input / x_dec:    由 adapter 构造,但 iTransformer.forecast 不使用
target_mark:          传入 x_mark_dec,但 iTransformer.forecast 不使用

iTransformer.forecast(...)

text
x_enc:                         (2, 24, 7)
means:                         (2, 1, 7)
stdev:                         (2, 1, 7)
x_enc normalized:              (2, 24, 7)

DataEmbedding_inverted:
  x_enc.permute(0,2,1):        (2, 7, 24)
  x_mark_enc.permute(0,2,1):   (2, 4, 24)
  torch.cat(..., dim=1):       (2, 11, 24)
  Linear(24 -> 32):            (2, 11, 32)

Encoder:
  Encoder.forward input:       (2, 11, 32)
  EncoderLayer input/output:   (2, 11, 32)
  AttentionLayer Q/K/V view:   (2, 11, 2, 16)
  FullAttention scores:        (2, 2, 11, 11)
  Encoder output:              (2, 11, 32)

Projection:
  Linear(32 -> 6):             (2, 11, 6)
  permute(0,2,1):              (2, 6, 11)
  [:,:,:N]:                    (2, 6, 7)

De-normalization:
  stdev repeat:                (2, 6, 7)
  means repeat:                (2, 6, 7)
  dec_out:                     (2, 6, 7)

forward tail slice:
  dec_out[:, -6:, :]:          (2, 6, 7)
为什么 forward 切片前后 shape 不变

iTransformer 的 forecast() 已经通过 Linear(d_model, pred_len) 输出 (B, pred_len, N),所以 forward() 里的 dec_out[:, -self.pred_len:, :] 是幂等裁剪。它保留这个写法是为了和其他 Transformer 模型共享统一接口。


8. 断点顺序

第一轮只看 iTransformer 主链:

text
TransformerAdapter._process
-> iTransformer.__init__
-> iTransformer.forward
-> iTransformer.forecast
-> DataEmbedding_inverted.forward
-> Encoder.forward
-> EncoderLayer.forward
-> AttentionLayer.forward
-> FullAttention.forward
-> projection

关键断点:

文件函数/位置观察重点
adapters_for_transformers.py_processdec_input 会被构造,但 iTransformer 不使用
models/iTransformer.py__init__DataEmbedding_invertedEncoderprojection 的注册
models/iTransformer.pyforward进入 forecast 分支,最后做幂等裁剪
models/iTransformer.pyforecastnormalization、embedding、encoder、projection、denorm
layers/Embed.pyDataEmbedding_inverted.forwardx.permute(0,2,1)torch.cat([x, x_mark.permute(...)], 1)
layers/Transformer_EncDec.pyEncoder.forwarde_layers=1,循环至少跑一次
layers/Transformer_EncDec.pyEncoderLayer.forwardattention 残差 + Conv1d FFN 残差
layers/SelfAttention_Family.pyAttentionLayer.forwardQ/K/V projection 与 .view(B,L,H,-1)
layers/SelfAttention_Family.pyFullAttention.forwardscores(B,H,token,token) 变量注意力矩阵

9. CIF 快速跑通备选

如果只想最快进入代码主链,也可以把数据集换成 cif_2016_dataset_1.csv

text
--config-path rolling_forecast_config.json --data-name-list cif_2016_dataset_1.csv --model-name time_series_library.iTransformer --adapter transformer_adapter --model-hyper-params "{\"batch_size\":2,\"d_model\":32,\"d_ff\":128,\"e_layers\":1,\"factor\":1,\"horizon\":6,\"n_heads\":2,\"norm\":true,\"seq_len\":24,\"dropout\":0.0,\"lr\":0.0001,\"num_epochs\":1,\"num_workers\":0,\"output_attention\":0}" --strategy-args "{\"horizon\":6,\"tv_ratio\":0.8,\"train_ratio_in_tv\":0.75,\"stride\":6,\"num_rollings\":2}" --num-workers 1 --timeout 600 --save-path debug\cif1_iTransformer_rolling_min

这条命令更快,但 CIF 通常是单变量数据。单变量时 iTransformer 的真实变量 token 数较少,不如 ETTh1 适合观察变量间 attention。它适合验证流程,不适合作为理解 iTransformer 创新点的主例子。


10. 当前学习主线

text
run_benchmark.py
-> TransformerAdapter._process
-> iTransformer.forward
-> iTransformer.forecast
-> DataEmbedding_inverted: 时间轴和变量轴翻转
-> Encoder: 变量 token 之间做 attention
-> AttentionLayer / FullAttention: 11 × 11 token attention
-> projection: Linear(d_model -> pred_len)
-> De-normalization
-> output[:, -pred_len:, :]

第一轮调试只需要记住:

Tip

iTransformer 的关键断点不是 decoder,而是 DataEmbedding_inverted.forward()。这里把 (B, seq_len, N) 变成 (B, N + time_dims, d_model),后面的 FullAttention 就不再是时间步 attention,而是变量 token attention。

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