Appearance
Level3 forward 主链
Abstract
这一篇对应 00-DLinear总览与Level树 的
Level 3。它只讲一件事:
进入
DLinear.forward(...)以后,forecasting 任务到底走哪条分支,以及encoder(...)在这里到底扮演什么角色。
1. 当前层第一性
这一层存在的第一性是:
先确定 forecasting 任务里,
forward(...)真实走的是哪条分支,并钉死 DLinear 里的encoder(...)不是 Transformer encoder,而是“分解 + 两路线性预测”的主体函数。
用户最容易误解的地方就在这里:
- 名字叫
encoder - 但它并不是注意力 encoder
- 它实际上就是 DLinear 的主运算体
2. 上下文
父节点:
下一层:
当前入口接口:
python
DLinear.forward(x_enc, x_mark_enc, x_dec, x_mark_dec)当前出口接口:
python
forecast(x_enc)
-> encoder(x_enc)
-> output.shape = (B, pred_len, C)3. 顺序图
4. 抽象树
5. forward(...) 完整代码
位置:
python
def forward(self, x_enc, x_mark_enc, x_dec, x_mark_dec, mask=None):
if (
self.task_name == "long_term_forecast"
or self.task_name == "short_term_forecast"
):
dec_out = self.forecast(x_enc)
return dec_out[:, -self.pred_len :, :]
if self.task_name == "imputation":
dec_out = self.imputation(x_enc)
return dec_out
if self.task_name == "anomaly_detection":
dec_out = self.anomaly_detection(x_enc)
return dec_out
if self.task_name == "classification":
dec_out = self.classification(x_enc)
return dec_out
return None6. 中文注释版完整代码
python
def forward(self, x_enc, x_mark_enc, x_dec, x_mark_dec, mask=None):
# forecasting 任务:真正走 forecast(x_enc)
if (
self.task_name == "long_term_forecast"
or self.task_name == "short_term_forecast"
):
dec_out = self.forecast(x_enc)
# 只保留最后 pred_len 段作为预测输出
return dec_out[:, -self.pred_len :, :]
if self.task_name == "imputation":
dec_out = self.imputation(x_enc)
return dec_out
if self.task_name == "anomaly_detection":
dec_out = self.anomaly_detection(x_enc)
return dec_out
if self.task_name == "classification":
dec_out = self.classification(x_enc)
return dec_out
return None7. 代码块 1:任务分支判断
7.1 输入/输出语义
输入:
task_name- 当前任务类型。
输出:
- 决定走哪一条模型内部路径。
当前真实例子里:
task_name = short_term_forecast
所以一定走:
python
dec_out = self.forecast(x_enc)
return dec_out[:, -self.pred_len :, :]这一段在总体里的作用:
先把 forecasting 任务和其他任务分开。DLinear 不同任务会共享部分代码壳,但当前例子只关心 forecasting。
8. 代码块 2:forecast(x_enc)
代码:
python
def forecast(self, x_enc):
return self.encoder(x_enc)8.1 输入/输出语义
输入:
x_enc- 历史数值窗口,形状
(B, seq_len, C)。
- 历史数值窗口,形状
输出:
dec_out- 未来预测窗口,形状
(B, pred_len, C)。
- 未来预测窗口,形状
8.2 这里最该固定的认识
这里没有 decoder、没有 attention、没有复杂桥接。
forecast(...) 的语义非常直接:
把历史窗口
x_enc直接送进 DLinear 的主体函数encoder(...),得到未来预测。
9. 代码块 3:为什么名字叫 encoder
这是用户最容易困惑的点。
在 DLinear 里:
python
def encoder(self, x):
...这个名字容易让人误以为:
- 它像 Informer 一样是一个注意力 encoder
- 只是整个模型的一部分
但在当前 forecasting 主链里,它其实承担的是:
DLinear 的核心运算主体。
也就是:
- 输入原始历史序列
x_enc - 先分解 seasonal / trend
- 再各自线性预测到未来
pred_len - 最后相加返回
所以这里更准确的脑内翻译应该是:
text
encoder(x)
≈
DLinear 的主运算体10. toy 例子贴代码讲解
固定 toy 参数:
B = 1seq_len = 4pred_len = 2C = 2
固定 toy 输入:
text
x_enc =
[
[1, 10],
[2, 11],
[3, 12],
[4, 13],
]10.1 代码块 1:进入 forecasting 分支
python
dec_out = self.forecast(x_enc)这一步的语义:
- 输入:4 个历史时间步
- 输出:2 个未来时间步
10.2 代码块 2:最终返回
python
return dec_out[:, -self.pred_len :, :]因为当前 forecast(...) 本来就输出长度 = pred_len,所以这句在 toy 例子里只是:
text
如果 dec_out =
[
[5/3, 32/3],
[10/3, 35/3],
]
那返回的还是这两个时间步。这一句在总体里的作用:
统一保证 forecasting 输出语义总是
(B, pred_len, C)。
11. 这一层最该固定什么
- 当前 forecasting 任务里,
forward(...)只走forecast(x_enc)。 x_mark_enc / x_dec / x_mark_dec不是真正核心。encoder(...)在 DLinear 里不是 Transformer encoder,而是模型主体。- 这层的真正出口是:
python
encoder(x_enc)12. 下一步
继续看: