Transformer通过其核心的自注意力机制 和位置编码,能够直接建模序列中任意两个时间步之间的全局依赖关系,从而有效捕捉销量预测中的长期趋势(如年度季节性)和短期模式(如周内波动、促销日爆发)。其关键在于避免了RNN/LSTM等循环结构可能存在的梯度消失问题,使模型能够平等地关注历史序列中的所有时间步。
为了同时优化对局部短期模式和全局长期趋势的捕捉,业界常采用以下混合或改进架构策略:
| 策略 | 核心思想 | 如何建模依赖 | 适用场景/优势 |
|---|---|---|---|
| Transformer + TCN/CNN | 用时间卷积网络(TCN)或CNN捕捉局部短期模式,用Transformer捕捉全局长期依赖。 | TCN/CNN:局部卷积核提取短期特征(如日波动)。 Transformer:自注意力捕捉长期关联(如季节性)。 | 能同时处理促销日的瞬间爆发和去年同期的销量模式。 |
| Transformer + LSTM/RNN | 用LSTM作为编码器提取初步时序特征,再用Transformer进行高层关系建模。 | LSTM:逐步处理,捕捉中短期依赖。 Transformer:全局注意力,强化长期依赖。 | 结合了LSTM的序列建模能力和Transformer的全局视野。 |
| Patch Transformer | 将时间序列分割成片段(Patch),对每个片段进行编码,再输入Transformer。 | 片段内:捕捉短期局部模式。 片段间:通过Transformer注意力捕捉长期趋势。 | 降低计算复杂度,并显式地构建层次化时序表示。 |
| 稀疏注意力/局部窗口注意力 | 限制自注意力的计算范围,例如只关注相邻时间步或采用滑动窗口。 | 窗口内:精细建模短期依赖。 跨窗口:通过层级结构间接传递长期信息。 | 大幅减少计算量,尤其适合超长序列。 |
| 因果掩码与掩码训练 | 在训练时随机**掩码(Mask)**部分历史数据,迫使模型学习基于上下文进行鲁棒预测。 | 模型必须利用未被掩码的、可能相距较远的时间步信息来重建被掩码部分,从而强化对长短依赖的利用。 | 提升模型对数据缺失和噪声的鲁棒性,这在零售数据中很常见。 |
位置编码是Transformer感知时序顺序的关键,它确保模型能区分"去年同期"与"上周"等不同时间概念。以下是正弦位置编码的示例代码:
python
import torch
import torch.nn as nn
import math
class PositionalEncoding(nn.Module):
"""正弦位置编码示例"""
def __init__(self, d_model, max_len=5000):
super(PositionalEncoding, self).__init__()
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term) # 偶数维度用sin pe[:, 1::2] = torch.cos(position * div_term) # 奇数维度用cos pe = pe.unsqueeze(0).transpose(0, 1) # 形状: [max_len, 1, d_model]
self.register_buffer('pe', pe)
def forward(self, x):
# x: [seq_len, batch_size, embedding_dim]
x = x + self.pe[:x.size(0), :]
return x
一个结合LSTM(捕捉中短期依赖)和Transformer(捕捉长期依赖)的混合模型PyTorch实现如下:
python
import torch
import torch.nn as nn
class TransformerLSTMForSalesForecasting(nn.Module):
"""Transformer-LSTM混合模型用于销量预测"""
def __init__(self, input_dim, d_model, nhead, num_layers, lstm_hidden, forecast_horizon):
super().__init__()
self.lstm = nn.LSTM(input_dim, lstm_hidden, batch_first=True, bidirectional=True)
self.encoder_layer = nn.TransformerEncoderLayer(d_model=d_model, nhead=nhead, batch_first=True)
self.transformer_encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers)
self.fc = nn.Linear(d_model, forecast_horizon) # 预测未来N步 def forward(self, x):
# x: [batch_size, seq_len, input_dim]
# 第一步:LSTM提取中短期特征
lstm_out, _ = self.lstm(x) # lstm_out: [batch_size, seq_len, lstm_hidden*2]
# 第二步:Transformer捕捉长期全局依赖
transformer_out = self.transformer_encoder(lstm_out) # [batch_size, seq_len, d_model]
# 第三步:取最后一个时间步的输出进行预测
last_step = transformer_out[:, -1, :] # [batch_size, d_model]
prediction = self.fc(last_step) # [batch_size, forecast_horizon]
return prediction
# 模型初始化示例
model = TransformerLSTMForSalesForecasting(
input_dim=10, # 输入特征维度(如销量、价格、促销标识等)
d_model=128, # Transformer模型维度 nhead=8, # 注意力头数
num_layers=4, # Transformer编码器层数 lstm_hidden=64, # LSTM隐藏层维度 forecast_horizon=7 # 预测未来7天
)
关键实践要点 包括:1) Transformer需要足够的数据量(通常十万级以上样本)才能充分发挥优势,并应构建包含数值型时间序列和类别型特征的混合特征 ;2) 位置信息至关重要 ,必须使用有效的位置编码,否则Transformer将退化为一个词袋模型,无法感知时序;3) 对于销量稀疏的长尾商品,可借鉴SPADE-S 等模型的思路,重新设计损失函数和采样策略,消除模型对高销量序列的隐式偏倚;4) 对于促销评估等场景,可引入因果推断模块,帮助模型区分相关性(如节假日)与因果性(如促销活动),提升决策价值。