Appearance
Level2 数据进入 DLinear
Abstract
这一篇对应 00-DLinear总览与Level树 的
Level 2。它只讲一件事:
batch 四元组怎样经过
_process(...),变成 DLinear 的真正输入。
1. 当前层第一性
这一层存在的第一性是:
把框架里的统一 batch 四元组,翻译成
DLinear.forward(...)的四输入。
同时要钉死一个关键事实:
虽然 DLinear 也走统一四输入接口,但 forecasting 路径里真正决定预测的是
x_enc。
也就是说,这一层的意义不是“DLinear 真需要一个 decoder”,而是:
- TFB 给了统一的接口壳
- DLinear 接受这个壳
- 但它内部只强依赖其中一部分输入
2. 上下文
父节点:
下一层:
当前入口接口:
python
_process(input, target, input_mark, target_mark)当前出口接口:
python
DLinear.forward(x_enc, x_mark_enc, x_dec, x_mark_dec)3. 当前真实例子里的 batch 是什么
当前真实运行例子里:
input.shape = (4, 96, 7)target.shape = (4, 72, 7)input_mark.shape = (4, 96, 4)target_mark.shape = (4, 72, 4)
这些张量的语义:
input- encoder 侧历史数值窗口。
target- decoder 侧监督窗口,长度 =
label_len + pred_len = 48 + 24 = 72。
- decoder 侧监督窗口,长度 =
input_markinput这 96 个时间步对应的时间特征。
target_marktarget这 72 个时间步对应的时间特征。
4. 顺序图
5. 抽象树
6. _process(...) 完整代码
位置:
python
def _process(self, input, target, input_mark, target_mark):
dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()
dec_input = (
torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)
.float()
.to(input.device)
)
output = self.model(input, input_mark, dec_input, target_mark)
return {"output": output}7. 中文注释版完整代码
python
def _process(self, input, target, input_mark, target_mark):
# 第一步:先造未来 pred_len 段的零占位
dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()
# 第二步:把 target 前半段的 label_len 段历史尾部拼到前面
dec_input = (
torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)
.float()
.to(input.device)
)
# 第三步:统一调用底层模型 forward
output = self.model(input, input_mark, dec_input, target_mark)
return {"output": output}8. 固定 toy 例子
固定 toy 参数:
B = 1label_len = 2pred_len = horizon = 2enc_in = 2
固定 toy 输入:
text
input =
[
[1, 10],
[2, 11],
[3, 12],
[4, 13],
]
shape = (1, 4, 2)
target =
[
[3, 12],
[4, 13],
[5, 14],
[6, 15],
]
shape = (1, 4, 2)9. 代码块 1:先造未来零占位
代码:
python
dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()9.1 输入/输出语义
输入:
target[:, -pred_len:, :]- 未来监督区的形状模板。
输出:
dec_input- 一个和未来监督区同 shape 的零占位张量。
9.2 toy 张量逐步演变
先取 target 最后 pred_len = 2 段:
text
[
[5, 14],
[6, 15],
]torch.zeros_like(...) 后变成:
text
dec_input =
[
[0, 0],
[0, 0],
]这一段在总体里的作用:
先给 decoder 输入留出“未来位置”,但这些位置暂时没有真实值,所以先用 0 占位。
虽然 DLinear 最后不真正依赖这个 decoder 语义,但统一接口层还是要这么造。
10. 代码块 2:拼上历史尾部
代码:
python
torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)10.1 输入/输出语义
输入:
target[:, :label_len, :]- decoder 历史段。
dec_input- 未来零占位段。
输出:
x_dec- 长度 =
label_len + pred_len的 decoder 输入。
- 长度 =
10.2 toy 张量逐步演变
先取 target 前 label_len = 2 段:
text
[
[3, 12],
[4, 13],
]再和零占位拼接:
text
x_dec =
[
[3, 12],
[4, 13],
[0, 0],
[0, 0],
]这一段在总体里的作用:
把“历史尾部 + 未来空位”拼成一个统一 decoder 输入。
这对 Informer 这种真正有 decoder 的模型是核心语义; 对 DLinear 来说,这一步更多是为了服从统一接口。
11. 代码块 3:四输入进入 DLinear
代码:
python
output = self.model(input, input_mark, dec_input, target_mark)11.1 输入/输出语义
传进去后,对应关系是:
x_enc = input- 历史数值窗口。
x_mark_enc = input_mark- encoder 侧时间特征。
x_dec = dec_input- decoder 侧历史尾部 + 零占位。
x_mark_dec = target_mark- decoder 侧时间特征。
输出:
output- DLinear 的预测张量,形状
(B, pred_len, C)。
- DLinear 的预测张量,形状
11.2 最关键的解释
这里必须固定一个事实:
DLinear 虽然接受四输入,但 forecasting 主链里真正参与计算主体的是
x_enc。
所以你读 DLinear 时,不能把注意力放在:
x_mark_encx_decx_mark_dec
而应该把注意力放在:
x_enc是怎样被分解成 seasonal / trend- seasonal / trend 怎样各自外推到未来
pred_len
12. 这一层最该固定什么
- DLinear 仍然走统一
_process(...)接口。 - 所以
x_dec仍然会被构造。 - 但 DLinear 的 forecasting 主体几乎只依赖
x_enc。 - 这一层的根本作用,是把框架 batch 翻译成模型可接受的统一四输入。
13. 下一步
继续看:
补查 torch 算子: