Appearance
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.pyWorking directory
text
D:\1sudyta\1ai-self\aistyle\TFBEnvironment variables
text
KMP_DUPLICATE_LIB_OK=TRUE3. 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.json 的 args 数组。
先在 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-path | rolling_forecast_config.json | 使用 rolling forecast 策略 |
--data-name-list | ETTh1.csv | 小规模多变量小时级数据,适合观察变量 token |
horizon | 6 | 每次预测未来 6 步,同时映射成 pred_len=6 |
tv_ratio | 0.8 | 前 80% 进入 train/valid 区域 |
train_ratio_in_tv | 0.75 | train/valid 区域内部再切训练段 |
stride | 6 | rolling 每次往后移动 6 步 |
num_rollings | 2 | 只滚动 2 次,减少调试时间 |
--num-workers | 1 | benchmark 外层只开 1 个 worker,方便断点 |
--timeout | 600 | 单任务最长 600 秒 |
模型参数
| 参数 | 当前值 | 进入 iTransformer 后的意义 |
|---|---|---|
model-name | time_series_library.iTransformer | 加载 models/iTransformer.py |
adapter | transformer_adapter | 走 TransformerAdapter._process(...) 统一接口 |
batch_size | 2 | 每个训练 batch 两条样本,shape 更小 |
seq_len | 24 | encoder 输入历史长度,也是 DataEmbedding_inverted 的 Linear 输入维 |
horizon | 6 | Config 会设置 pred_len=6 |
d_model | 32 | embedding / encoder hidden size |
n_heads | 2 | FullAttention 多头数 |
d_keys=d_values | 16 | 由 |
d_ff | 128 | EncoderLayer 里的 Conv1d FFN 隐藏维 |
e_layers | 1 | encoder loop 跑 1 次 |
factor | 1 | 传入 FullAttention 构造函数;当前 FullAttention 主链不使用 top-k |
dropout | 0.0 | 关闭 dropout,方便调试 |
num_epochs | 1 | 只训练 1 轮,保证能进入训练 forward |
output_attention | 0 | 不返回 attention 权重,先看主输出 |
norm | true | adapter 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 = 16TransformerAdapter._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 不变
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 | _process | dec_input 会被构造,但 iTransformer 不使用 |
models/iTransformer.py | __init__ | DataEmbedding_inverted、Encoder、projection 的注册 |
models/iTransformer.py | forward | 进入 forecast 分支,最后做幂等裁剪 |
models/iTransformer.py | forecast | normalization、embedding、encoder、projection、denorm |
layers/Embed.py | DataEmbedding_inverted.forward | x.permute(0,2,1) 和 torch.cat([x, x_mark.permute(...)], 1) |
layers/Transformer_EncDec.py | Encoder.forward | e_layers=1,循环至少跑一次 |
layers/Transformer_EncDec.py | EncoderLayer.forward | attention 残差 + Conv1d FFN 残差 |
layers/SelfAttention_Family.py | AttentionLayer.forward | Q/K/V projection 与 .view(B,L,H,-1) |
layers/SelfAttention_Family.py | FullAttention.forward | scores 的 (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。