DeepAR

        做项目涉及到了时间序列的概率(区间)预测。说到时序概率预测,那最经典的无非是概率循环神经网络DeepAR了。DeepAR 是 Amazon 于 2017 年提出的基于深度学习的时间序列预测方法,目前已集成到 Amazon SageMaker 和 GluonTS 中。前者是 AWS 的机器学习云平台,后者是 Amazon 开源的时序预测工具库。DeepAR有的优势是:输出概率分布,比起点预测,容错率高,在有风险,误差比较大的的领域尤其重要。

        想要快速使用DeepAR,可以直接参考awslabs/gluonts: Probabilistic time series modeling in Python (github.com)

        当自己根据原理观摩大佬写的DeepAR算法的时候,也记录下了自己的心得和理解,在这里分享出来。

        比起LSTM,DeepAR改进的地方主要是输出的概率分布了,而概率分布,主要由高斯分布和负二项分布来实现。这篇文章主要是高斯分布来实现。

        训练模型和预测模型如下,预测思路为多步递归预测(将预测值作为协变量),而模型架构主要采用编码器-译码器(Encoder-Decoder)架构,及使用LSTM做编码器提取时序特征,再将LSTM隐藏层输出传入线性层中计算出概率分布的中值和数学期望(译码):


         z_{i,t-2} 为已有的上一个时间段的目标数据, x_{i,t-1}是协变量,目的是预测下一个时间段的目标数据 z_{i,t-1}。在这里我们使用高斯分布,我们将两个参数inputs进networks的时候,DeepAR采用的network是LSTM,我们可以自己随便换成其他模型:

self.input_embed = nn.Linear(1, embedding_size)
self.encoder = nn.LSTM(embedding_size+input_size, hidden_size, \
    num_layers, bias=True, batch_first=True)
if likelihood == "g":
    self.likelihood_layer = Gaussian(hidden_size, 1)
elif likelihood == "nb":
    self.likelihood_layer = NegativeBinomial(hidden_size, 1)
    self.likelihood = likelihood

#高斯函数的损失函数,用于模型的训练,不作为构建
def gaussian_likelihood_loss(z, mu, sigma):
    negative_likelihood = torch.log(sigma + 1) + (z - mu) ** 2 / (2 * sigma ** 2) + 6
    return negative_likelihood.mean()

#高斯神经网络,用于生成mu和sigma
class Gaussian(nn.Module):

    def __init__(self, hidden_size, output_size):
        super(Gaussian, self).__init__()
        self.mu_layer = nn.Linear(hidden_size, output_size)
        self.sigma_layer = nn.Linear(hidden_size, output_size)
    
    def forward(self, h):
        _, hidden_size = h.size()
        sigma_t = torch.log(1 + torch.exp(self.sigma_layer(h))) + 1e-6
        sigma_t = sigma_t.squeeze(0)
        mu_t = self.mu_layer(h).squeeze(0)
        return mu_t, sigma_t

        值得注意的是,前面我们提到DeepAR是基于递归预测思路的,所以预测的过程中不能像训练时那样直接给decoder输入上一时刻的真实值,只能通过抽样来得到一个估计值(一般是区间的中值) ,将估计值输入到下一时刻的LSTM当中不断迭代以得到预测结果(但会累积误差)。

估计的具体步骤如下: 

 for s in range(seq_len + output_horizon):   #seq_len + output_horizon是训练集和测试集的长度和
    if s < seq_len:   #训练时不断传入真实值
        ynext = y[:, s].view(-1, 1)
        yembed = self.input_embed(ynext).view(num_ts, -1)
        x = X[:, s, :].view(num_ts, -1)
    else:  #进入测试阶段
        yembed = self.input_embed(ynext).view(num_ts, -1)  #训练时迭代上次传入的z
        x = Xf[:, s-seq_len, :].view(num_ts, -1)  #Xf为测试集的协变量
    x = torch.cat([x, yembed], dim=1) # num_ts, num_features + embedding
    inp = x.unsqueeze(1)
    if h is None and c is None:
        out, (h, c) = self.encoder(inp) # h size (num_layers, num_ts, hidden_size)
    else:
        out, (h, c) = self.encoder(inp, (h, c))

        模型基于训练出的高斯分布进行预测的时候,DeepAR 产生一定数量的多步预测结果(你可以自己选择抽样数量,100,1000,2000都ok),我们可以根据模型效果和实际需求设置输出不同的分布区间,例如P10,P50和P90三个值。这里的P10指的是置信度,即10%的可能性会小于P10这个值。

#result为每次抽取ypredict的集合,采用numpy的quantile进行百分比切割
p50 = np.quantile(result, 0.5, axis=1)
p90 = np.quantile(result, 0.9, axis=1)
p10 = np.quantile(result, 0.1, axis=1)

         最后,DeepAR已经是17-18年的产物了,目前预测的性能也许并不能和sota模型相提并论,但它提供的最大价值在于概率预测的思路,我们可以尝试将基于LSTM模型的编码器(局限所在)转换成目前更加主流强大的时序预测模型,我相信一定会有更加优异的预测效果!!

        bishe可联系QQ:2663505372

代码解析来自Github大佬:jingw2/demand_forecast (github.com)

AWS DeepAR网址:https://arxiv.org/abs/1704.04110

概率自回归预测—DeepAR模型浅析:概率自回归预测——DeepAR模型浅析 - 知乎

  • 31
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值