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 = 2seq_len = 6label_len = 3pred_len = horizon = 2enc_in = 3
因此 target.shape = (2, label_len+pred_len, enc_in) = (2, 5, 3)。
固定 toy 输入(只展示 batch=0):
text
input[0]: shape = (6, 3)
[ [1, 10, 100], ← t=0
[2, 11, 101], ← t=1
[3, 12, 102], ← t=2
[4, 13, 103], ← t=3
[5, 14, 104], ← t=4
[6, 15, 105] ] ← t=5
全批 input.shape = (2, 6, 3)
target[0]: shape = (5, 3) ← label_len(3) + pred_len(2) = 5
[ [4, 13, 103], ← 历史尾部 t=3(与 input 重叠)
[5, 14, 104], ← 历史尾部 t=4
[6, 15, 105], ← 历史尾部 t=5
[7, 16, 106], ← 未来 t=6(监督真值)
[8, 17, 107] ] ← 未来 t=7(监督真值)
全批 target.shape = (2, 5, 3)9. 代码块 1:先造未来零占位
代码:
python
dec_input = torch.zeros_like(target[:, -self.config.horizon :, :]).float()9.1 输入/输出语义
输入:
target[:, -pred_len:, :]- 取 target 最后
pred_len步,仅用其形状作模板。
- 取 target 最后
输出:
dec_input- 与未来监督区同 shape 的零张量,形状
(2, 2, 3)。
- 与未来监督区同 shape 的零张量,形状
9.2 toy 张量逐步演变
先取 target[:, -2:, :](最后 pred_len=2 步):
text
batch=0:
[ [7, 16, 106],
[8, 17, 107] ]torch.zeros_like(...) 后:
text
dec_input(此时 shape=(2, 2, 3)):
batch=0:
[ [0, 0, 0],
[0, 0, 0] ]DLinear 不需要这个零占位,但框架统一接口要求构造。
10. 代码块 2:拼上历史尾部
代码:
python
torch.cat([target[:, : self.config.label_len, :], dec_input], dim=1)10.1 输入/输出语义
输入:
target[:, :label_len, :]:历史尾部,shape(2, 3, 3)dec_input:零占位,shape(2, 2, 3)
输出:
x_dec:shape(2, 5, 3),长度 =label_len + pred_len = 5
10.2 toy 张量逐步演变
取 target[:, :3, :](前 label_len=3 步):
text
batch=0:
[ [4, 13, 103],
[5, 14, 104],
[6, 15, 105] ]和零占位拼接:
text
x_dec[0], shape=(5,3):
[ [4, 13, 103], ← 历史尾部
[5, 14, 104],
[6, 15, 105],
[0, 0, 0], ← 未来零占位
[0, 0, 0] ]对 Informer:这是 decoder 的核心输入。对 DLinear:DLinear.forward 接收它但根本不使用它。
11. 代码块 3:四输入进入 DLinear
代码:
python
output = self.model(input, input_mark, dec_input, target_mark)11.1 四输入对应关系
x_enc = input (2, 6, 3) ← DLinear 唯一真正使用的输入
x_mark_enc = input_mark (2, 6, 4) ← DLinear forward 里接收但不用
x_dec = dec_input (2, 5, 3) ← DLinear forward 里接收但不用
x_mark_dec = target_mark (2, 5, 4) ← DLinear forward 里接收但不用输出:
output.shape = (2, 2, 3)即(B, pred_len, enc_in)
11.2 最关键的解释
x_mark_enc、x_dec、x_mark_dec三个输入由 TFB adapter 统一构造,但 DLinear 的forward函数签名虽然接收它们,内部运算完全不使用它们。 DLinear 的所有计算仅依赖x_enc。
12. 这一层最该固定什么
- DLinear 仍然走统一
_process(...)接口。 - 所以
x_dec仍然会被构造。 - 但 DLinear 的 forecasting 主体几乎只依赖
x_enc。 - 这一层的根本作用,是把框架 batch 翻译成模型可接受的统一四输入。
13. 下一步
继续看:
补查 torch 算子: