I. 前言
前面已经写了很多关于时间序列预测的文章,这些文章中都没有涉及到近些年来比较火的Attention机制,随Attention机制一起提出的是transformer模型,关于transformer模型的原理网上各种讲解很多,这里就不具体描述了,有机会再写。
II. Transformer
PyTorch封装了Transformer的具体实现,如果导入失败可以参考:torch.nn.Transformer导入失败。
Transformer模型搭建如下:
class TransformerModel(nn.Module):
def __init__(self, args):
super(TransformerModel, self).__init__()
self.args = args
# embed_dim = head_dim * num_heads?
self.input_fc = nn.Linear(args.input_size, args.d_model)
self.output_fc = nn.Linear(args.input_size, args.d_model)
self.pos_emb = PositionalEncoding(args.d_model)
encoder_layer = nn.TransformerEncoderLayer(
d_model=args.d_model,
nhead=8,
dim_feedforward=4 * args.d_model,
batch_first=True,
dropout=0.1,
device=device
)
decoder_layer = nn.TransformerDecoderLayer(
d_model=args.d_model,
nhead=8,
dropout=0.1,
dim_feedforward=4 * args.d_model,
batch_first=True,
device=device
)
self.encoder = torch.nn.TransformerEncoder(encoder_layer, num_layers=5)
self.decoder = torch.nn.TransformerDecoder(decoder_layer, num_layers=5)
self.fc = nn.Linear(args.output_size * args.d_model, args.output_size)
self.fc1 = nn.Linear(args.seq_len * args.d_model, args.d_model)
self.fc2 = nn.Linear(args.d_model, args.output_size)
def forward(self, x):
# print(x.size()) # (256, 24, 7)
y = x[:, -self.args.output_size:, :]
# print(y.size()) # (256, 4, 7)
x = self.input_fc(x) # (256, 24, 128)
x = self.pos_emb(x) # (256, 24, 128)
x = self.encoder(x)
# 不经过解码器
x = x.flatten(start_dim=1)
x = self.fc1(x)
out = self.fc2(x)
# y = self.output_fc(y) # (256, 4, 128)
# out = self.decoder(y, x) # (256, 4, 128)
# out = out.flatten(start_dim=1) # (256, 4 * 128)
# out = self.fc(out) # (256, 4)
return out
初始时的数据输入维度为7,也就是每个时刻的负荷值以及6个环境变量。在Transformer的原始论文中,文本的嵌入维度为512,而且PyTorch规定nhead数和d_model也就是嵌入维度必须满足整除关系,因此首先将原始数据从7维映射到d_model维度:
x = self.input_fc(x)
其中input_fc:
self.input_fc = nn.Linear(args.input_size, args.d_model)
然后对原始输入进行位置编码:
x = self.pos_emb(x)
然后经过编码层:
x = self.encoder(x)
得到的输出和输入维度一致。
原始Transformer中的解码器效果很差,因此这里直接将编码器的编码结果经过两个线性层得到输出:
x = x.flatten(start_dim=1)
x = self.fc1(x)
out = self.fc2(x)
III. 代码实现
3.1 数据处理
利用前24小时的负荷值+环境变量预测后12个时刻的负荷值,数据处理和前面一致。
3.2 模型训练/测试
和前文一致。
3.3 实验结果
训练50轮,MAPE为7.09%:
IV. 源码及数据
后面将陆续公开~