1

研究背景

时间序列预测在许多领域有着广泛和关键的应用,例如传感器网络监测、能源和智能电网管理、经济与金融、疾病传播分析等等。在这些应用场景中,可以利用大量关于过去行为的时间序列数据来做出长期预测,即长序列时序预测问题(LSTF)。不过现有的方法是在有限的问题设置下设计的,例如预测48个点或更少,而更长的序列长度则会使得模型的预测能力受到很大影响,这也是LSTF问题研究的关键点。最近的研究表明,Transformer模型具有提高预测能力的潜力。本文受到Transformer模型的启发,设计了Informer模型来解决LSTF问题。

模型的一作周号益长期从事智能软件、机器学习研究,

  • 在KDD、AAAI、IJCAI、TIST等国内外会议期刊上发表学术论文10篇,申请国家发明专利授权10项,担任多个国际顶级期刊会议的PC或审稿人,获“AAAI’21 最佳论文奖”;

  • 作为核心骨干参与国家973、国家自然科学基金重点项目等3项,负责国家电网、华为、京东方等企业项目4项;

  • 服务工业制造智能,成果获工信部工业互联网创新成果转化一等奖;

  • 服务国家新冠疫情大数据防控,国务院办公厅、国家卫健委等专函感谢,受到人民日报、科技日报、解放日报报道;

  • 入选世界人工智能大会WAIC 2021“云帆奖•明日之星”、北京市“海英之星”、智源领域新星。

作者来自于北航ACT实验室的SMART组

ACT实验室秉承“进取(Active)、创新(Creative)、合作(Teamwork)”的治学理念,依托北航计算机学院与北航大数据与脑机智能高精尖创新中心,围绕复杂大数据可计算、群体智能可学习、多态跨域知识可关联等科学问题,面向数据科学、智能科学、认知科学三大研究方向,研究网络数据挖掘、异常检测、时序分析的理论与算法,建立网络行为大数据智能计算平台Ring,为大数据应用提供科学技术手段。

SMART组则是致力于开放序列的智能计算研究,包括序列预测、序列决策、高效计算、模型开放可信等。研究兴趣覆盖机器学习、神经网络、时序预测、异常检测、图像处理、语言处理、强化学习、机器学习系统等人工智能子领域,相关技术目前已在工业、医疗、军事等关键领域的20余家企事业单位开展应用示范。

2

论文主要内容简介

Transformer存在几个严重的问题,使其无法直接应用于LSTF问题,如二次时间复杂度、高内存使用率和编码器-解码器架构的固有限制。

论文设计了一个高效的基于Transformer的模型Informer来解决这些问题,它具有三个独特的特点:

(1) ProbSparse Self-attention机制,在时间复杂度和内存开销上实现了O(LlogL),并且在序列依赖关系对齐上具有相当的性能;

(2) 自注意力蒸馏机制,通过将层级输入减半来突出主导注意力,并高效处理极端长的输入序列;

(3) 生成式解码器,虽然其在概念上简单,但它能够以一次前向操作而不是分步操作的方式预测长时序序列,极大地提高了长序列预测的推理速度。

3

代码链接

论文链接:

https://arxiv.org/abs/2012.07436

基于MindSpore实现代码开源链接(点击“阅读原文”即可获取)

https://gitee.com/mindspore/contrib/tree/master/papers/informer

4

算法框架技术要点

本文基于Transformer网络设计了Informer模型,其具体框架如下图所示。

图中左边的结构是编码器Encoder,其能接受长序列输入(绿色序列)。Encoder采用了自注意力蒸馏机制(蓝色梯形),通过将层级输入减半,来提取主导的注意力,并大幅减少网络规模;同时论文在Encoder中用ProbSparse self-attention替换掉了原始的self-attention,提高长序列处理的性能。

图中右边的结构是解码器Decoder,其同样能接受长序列输入,并将需要预测的目标元素填充为零,通过将需要预测的该全零序列也作为特征图的加权注意力组成部分,用生成式的方式对预测序列(橙色序列)进行预测。

在多个数据集如ETT,Weather,ECL上的大量实验表明,Informer显著优于现有方法,为LSTF问题提供了新的解决方案。

其中最为关键的ProbSparse self-attention是基于传统自注意力机制的概率分布具有潜在的稀疏性这一点。对学习到的自注意模式做了定性评估后,发现“稀疏性”自注意力分数会形成长尾分布,即少数点积对构成了主要的注意力,而其它的可以忽略。基于这种稀疏性假设,本文认为部分query用处较小,即不需要计算这部分query对于value的贡献。

在具体操作时,只需要随机取样

个点积对来计算,而其他的不需要计算,作者选择Top-u个作为询问。在实际操作中,一般query和key的长度相等,即

则ProbSparse Self-attention的时间复杂度和空间复杂度为O(LlogL)。

5

MindSpore代码实现

使用的mindspore版本为Linux-x86_64下的mindspore 1.5.0,GPU CUDA11.1,Python3.7.5。

总体代码结构如下:

Informer_mindspore
├─models                   #Informer模型实现相关代码
│      attn.py                #概率稀疏注意力机制
│      decoder.py         #decoder层
│      embed.py           #特征编码
│      encoder.py         #encoder层
│      model.py            #将上述模块整合为Informer模型
└─utils               #模型所用到的工具masking.py         he_normal.pytrans_tools.py

5.1 embed.py

embed.py实现了数据的编码,位置的编码和时间的编码,最终的编码由这三种编码直接相加得到。

数据的编码在TokenEmbedding类中实现:

class TokenEmbedding(nn.Cell):def __init__(self, c_in, d_model):super(TokenEmbedding, self).__init__()padding = 1#一维卷积层,将输入数据从维映射到维self.token_conv = nn.Conv1d(in_channels=c_in,
out_channels=d_model,kernel_size=3,
padding=padding, pad_mode='pad')#对参数进行初始化的方法,对应torch的nn.init.kaiming_normal_self.henormal = HeNormal(mode='fan_in', nonlinearity='leaky_relu')#将一维卷积层的参数初始化for m in self.cells():if isinstance(m, nn.Conv1d):self.henormal(m.weight.data)def construct(self, x):#[batch_size, seq_len, enc_in]x = self.token_conv(P.Transpose()(x, (0, 2, 1,)))#[batch_size, d_model, seq_len]#trans_shape是为方便使用transpose算子实现的一个辅助函数x = x.transpose(trans_shape((1, 2), x.ndim))#[batch_size, seq_len, d_model]return x

对位置进行编码是为了模型能够关注到输入序列的位置信息,因为Transformer架构对于输入的元素是一起处理的,会忽略掉输入原有的前后顺序。所使用的编码方法和Transformer一样,使用公式:

进行编码,其中pos是token在序列中的位置,i表示对token编码后向量的第i个位置。

具体实现在PositionalEmbedding类中:

class PositionalEmbedding(nn.Cell):def __init__(self, d_model, max_len=5000):super(PositionalEmbedding, self).__init__()pe = ms_np.zeros((max_len, d_model)).astype(dtype.float32)self.expand = ExpandDims() #对应torch的unsqueezeposition = self.expand(ms_np.arange(0, max_len), 1).astype(dtype.float32)#先取对数再exp,方便计算div_term = ms_np.exp(ms_np.arange(0, d_model, 2).astype(dtype.float32) * -(math.log(10000.0) / d_model))pe[:, 0::2] = ms_np.sin(position * div_term)pe[:, 1::2] = ms_np.cos(position * div_term)pe = self.expand(pe, 0)self.pe = pedef construct(self, x):return self.pe[:, :P.Shape()(x)[1]] #截取和输入等长的位置编码

时间的编码有两种方式,一种是将月、周、天、小时和分钟(可选)使用mindspore自带的Embedding层进行编码并相加。

具体实现在TemporalEmbedding类中:

class TemporalEmbedding(nn.Cell):def __init__(self, d_model, embed_type='timeF', freq='h'):super(TemporalEmbedding, self).__init__()self.embed = nn.Embedding#频率为t的时候会对分钟进行编码if freq == 't':self.minute_embed = self.embed(4, d_model)self.hour_embed = self.embed(24, d_model)   #小时编码self.weekday_embed = self.embed(7, d_model) #周编码self.day_embed = self.embed(32, d_model)    #天编码self.month_embed = self.embed(13, d_model)  #月编码def construct(self, x):x = x.astype(dtype.float64)#截取数据对应的时间信息进行编码minute_x = self.minute_embed(x[:, :, 4]) if hasattr(self, 'minute_embed') else 0.hour_x = self.hour_embed(x[:, :, 3])weekday_x = self.weekday_embed(x[:, :, 2])day_x = self.day_embed(x[:, :, 1])month_x = self.month_embed(x[:, :, 0])#将所有编码相加得到最终编码return hour_x + weekday_x + day_x + month_x + minute_x

另外一种则是TimeFeatureEmbedding类中实现的直接使用一个全连接层将输入的时间戳映射到dmodel维完成编码,具体代码如下:

class TimeFeatureEmbedding(nn.Cell):def __init__(self, d_model, freq='h'):super(TimeFeatureEmbedding, self).__init__()# s:secondly, t:minutely, h:hourly# d:daily, b:business days, w:weekly, m:monthlyfreq_map = {'h': 4, 't': 5, 's': 6, 'm': 1, 'a': 1, 'w': 2, 'd': 3, 'b': 3}d_inp = freq_map[freq]#Dense对应torch的Linearself.embed = nn.Dense(in_channels=d_inp,out_channels=d_model)def construct(self, x):return self.embed(x)

最后直接将三种编码相加并通过一个dropout层就得到了最终的编码,代码如下:

class DataEmbedding(nn.Cell):def __init__(self, c_in, d_model, embed_type='timeF', freq='h', dropout=0.1):super(DataEmbedding, self).__init__()self.value_embedding = TokenEmbedding(c_in=c_in, d_model=d_model)self.position_embedding = PositionalEmbedding(
d_model=d_model)self.temporal_embedding = TemporalEmbedding(
d_model=d_model, embed_type=embed_type, freq=freq) \if embed_type != 'timeF' else \TimeFeatureEmbedding(d_model=d_model, freq=freq)#mindspore中Dropout的参数为keep_prob即1 - drop_probself.dropout = nn.Dropout(keep_prob = 1.0 - dropout)def construct(self, x, x_mark):#将三种编码相加得到最终的编码x = self.value_embedding(x) + self.position_embedding(x) + self.temporal_embedding(x_mark)return self.dropout(x)

5.2 attn.py

这一部分实现了两种注意力机制,一是Transformer的多头自注意力机制(Full Attention),二是Informer提出的概率稀疏注意力机制(Prob Attention)。

Full Attention的代码如下:

class FullAttention(nn.Cell):def __init__(self, mask_flag=True, factor=5, scale=None, attention_dropout=0.1, output_attention=False):super(FullAttention, self).__init__()self.scale = scaleself.mask_flag = mask_flagself.output_attention = output_attentionself.dropout = nn.Dropout(keep_prob=1.0 - attention_dropout)self.softmax = Softmax()self.factor = factordef construct(self, queries, keys, values, attn_mask):b, l, _, e = queries.shape#如果有自定义的scale,使用自定义的,否则使用和原论文一样的值scale = self.scale or 1. / sqrt(e)#用transpose和matmul等价替换torch中的einsum算子#等价于scores=torch.einsum("blhe,bshe->bhls",queries,keys)#scores=〖QK〗^Tscores = ms_np.matmul(queries.transpose((0, 2, 1, 3)), keys.transpose((0, 2, 3, 1)))if self.mask_flag:if attn_mask is None:attn_mask = TriangularCausalMask(b, l)mask_fill(attn_mask.mask, scores, -math.inf)a = self.dropout(self.softmax(Tensor(scale * scores, dtype.float32)))#v的计算同理,等价于torch.einsum("bhls,bshd->blhd", a, values)v = ms_np.matmul(a, values.transpose((0, 2, 1, 3)))v = v.transpose(trans_shape((1, 2), v.shape))if self.output_attention:return(v, a)return(v, None)

然后是概率稀疏注意力机制的实现,原论文中对于这个概率稀疏注意力算法的描述如下:

首先是_prob_QK函数,它完成了算法的前五步,具体代码实现如下:

def _prob_qk(self, q, k, sample_k, n_top):  # n_top: c*ln(L_q)#q [batch_size, head, l_q, d_q]#k [batch_size, head, l_k, d_k]b, h, l_k, e = k.shape_, _, l_q, _ = q.shape#第二步:对于每个Q采样一部分K
#扩展一维是为了实现采样方便k_expand = self.expand(k, -3).expand_as(ms_np.ones((b, h, l_q, l_k, e)))         #对于每个q随机生成采样的位置,sample_k为采样的k的个数#uniform_int等价于torch的randint,采样了l_q * sample_k个元素#sample_k的值为min(factor * log(l_k), l_k) ,保证了复杂度index_sample = self.uniform_int((l_q, sample_k), 0, l_k)#根据随机生成的位置进行采样k_sample = k_expand[:, :, self.expand(ms_np.arange(l_q), 1), index_sample, :]#第三步:计算sample scoreq_k_sample = ms_np.matmul(self.expand(q, -2),k_sample.transpose(trans_shape((-1, -2), k_sample.dim()))).squeeze()#第四步:计算用于评估的M值m = q_k_sample.max(-1)[0] - P.Div()(q_k_sample.sum(-1), l_k)#第五步:找到值最大的Top-u(n_top)个询问并得到对应的索引#n_top的值为min(factor * log(l_q), l_q),保证了复杂度m_top = self.topk(m, int(n_top.asnumpy()))[1]#根据得到的少量的q计算q_reduce = q[ms_np.arange(b)[:, None, None],ms_np.arange(h)[None, :, None],m_top, :]q_k = ms_np.matmul(q_reduce, k.transpose(trans_shape((-1, -2), k.shape)))return q_k, m_top

对于算法剩下的步骤的实现,作者是先在_get_initial_context函数中将context全部设置成Mean(Value),然后使用_update_context()函数将选出来的qi对应的行的值更新为

代码实现如下:

def _get_initial_context(self, v, l_q):b, h, l_v, _ = v.shapeif not self.mask_flag:#对应torch的meanv_sum = P.ReduceMean()(v, -2)context = self.expand(v_sum, -2).expand_as(ms_np.ones((b, h, l_q, v_sum.shape[-1]))).copy()else:context = ms_np.cumsum(v, axis=-2)return contextdef _update_context(self, context_in, v, scores, index, l_q):b, h, l_v, _ = v.shapeif self.mask_flag:#如果需要mask,将对应的位置置为infattn_mask = ProbMask(b, h, l_q, index, scores)scores.masked_fill_(attn_mask.mask, -math.inf)attn = self.softmax(scores)#根据索引更新对应的值context_in[ms_np.arange(b)[:, None, None], ms_np.arange(h)[None, :, None], index, :] \= ms_np.matmul(attn, v).astype(context_in.dtype)if self.output_attention:attns = (ms_np.ones([b, h, l_v, l_v]) / l_v).astype(attn.dtype)attns[ms_np.arange(b)[:, None, None], ms_np.arange(h)[None, :, None], index, :] = attnreturn context_in, attns#原本应是return context_in, None但是mindspore训练时不允许None的出现于是随便返回了一个attn,但它在后续代码中不会被使用,所以无影响return context_in, attn

最后是AttentionLayer,这个类主要是将输入映射为Q,K,V三个矩阵并进行多头的一个划分,代码如下:

class AttentionLayer(nn.Cell):def __init__(self, attention, d_model, n_heads,d_keys=None, d_values=None, mix=False):super(AttentionLayer, self).__init__()d_keys = d_keys or (d_model // n_heads)d_values = d_values or (d_model // n_heads)self.inner_attention = attention#将输出的Q,K,V进行映射self.query_projection = nn.Dense(in_channels=d_model, out_channels=d_keys * n_heads)self.key_projection = nn.Dense(in_channels=d_model, out_channels=d_keys * n_heads)self.value_projection = nn.Dense(in_channels=d_model, out_channels=d_values * n_heads)#将输出的维度映射回d_modelself.out_projection = nn.Dense(in_channels=d_values * n_heads, out_channels=d_model)self.n_heads = n_headsself.mix = mixdef construct(self, queries, keys, values, attn_mask):b, l, _ = queries.shape_, s, _ = keys.shapeh = self.n_headsqueries = self.query_projection(queries).view(b, l, h, -1)keys = self.key_projection(keys).view(b, s, h, -1)values = self.value_projection(values).view(b, s, h, -1)out, attn = self.inner_attention(queries, keys, values, attn_mask)if self.mix:out = out.transpose(trans_shape((1, 2), out.dim()))out = P.Reshape()(out, (b, l, -1,))return self.out_projection(out), attn

5.3 masking.py

mask主要是为了使decoder在解码过程中只依赖于当前时刻之前的输出。它会生成一个右上角全为1的布尔型矩阵,为1表示score矩阵这个位置的值需要被置为负无穷,softmax之后会变成0也就对它没有关注。

TriangularCausalMask类是用于对FullAttenion的mask,ProbMask则是用于对ProbAttention的mask,代码实现如下:

class TriangularCausalMask():def __init__(self, B, L):mask_shape = [B, 1, L, L]self.mask = ms_np.triu(ms_np.ones(mask_shape).astype(dtype.bool_), k=1)class ProbMask():def __init__(self, B, H, L, index, scores):mask = ms_np.triu(ms_np.ones((L, scores.shape[-1])).astype(dtype.bool_), k=1)mask_ex = mask[None, None, :].expand_as(ms_np.ones((B, H, L, scores.shape[-1])))
#取出概率稀疏注意力选出的行对应的maskindicator = mask_ex[ms_np.arange(B)[:, None, None],ms_np.arange(H)[None, :, None],index, :]self.mask = indicator.view(scores.shape)indicator = mask_ex[ms_np.arange(b)[:, None, None],ms_np.arange(h)[None, :, None],index, :]self.mask = indicator.view(scores.shape)

5.4 encoder.py

这一部分主要是实现了encoder部分的代码。具体实现了ConvLayer层和Encoder的一个单层EncoderLayer。

首先是ConvLayer层,它位于两个EncoderLayer之间,通过一个最大池化使输入的规模减半。当distil为True时才会有这个层。

class ConvLayer(nn.Cell):def __init__(self, c_in):super(ConvLayer, self).__init__()padding = 1self.down_conv = nn.Conv1d(in_channels=c_in,out_channels=c_in,kernel_size=3,padding=padding,pad_mode='pad')self.norm = nn.BatchNorm1d(num_features=c_in, momentum=0.9)self.activation = nn.ELU()self.maxpool = nn.MaxPool1d(kernel_size=3, stride=2)self.pad = self.pad = nn.Pad(((0, 0), (0, 0), (1, 1), (1, 1)), "CONSTANT")def construct(self, x):x = self.down_conv(P.Transpose()(x, (0, 2, 1,)))x = self.norm(x)x = self.activation(x)x = self.pad(x)x = self.maxpool(x)x = x.transpose(trans_shape((1, 2), x.shape))return x

然后是EncoderLayer,它们通过堆叠组成Encoder。它的基本结构和Transformer中的EncoderLayer相似,有一个注意力层和一个包含两层线性映射的Feed Forward层,两个子层后都有归一化层以及跳跃连接,这里不做具体讲解。

最后根据上面两个层构造Encoder:

class Encoder(nn.Cell):def __init__(self, attn_layers, conv_layers=None, norm_layer=None):super(Encoder, self).__init__()#对应torch的ModuleListself.attn_layers = nn.CellList(attn_layers)self.conv_layers = nn.CellList(conv_layers) if conv_layers is not None else Noneself.norm = norm_layerdef construct(self, x, attn_mask=None):attns = []if self.conv_layers is not None:#conv_layer的层数(如果非None)为attn_layer的层数-1for attn_layer, conv_layer in zip(self.attn_layers, self.conv_layers):x, attn = attn_layer(x, attn_mask=attn_mask)x = conv_layer(x)#conv_layer在两层encoder_layer之间attns.append(attn)x, attn = self.attn_layers[-1](x, attn_mask=attn_mask)attns.append(attn)else:for attn_layer in self.attn_layers:x, attn = attn_layer(x, attn_mask=attn_mask)attns.append(attn)if self.norm is not None:x = self.norm(x)return x, attns

5.5 decoder.py

和Encoder类似,Decoder是由多个DecoderLayer堆叠而成。DecoderLayer的结构也和Transformer中的层类似,有两个attention层和一个包含两层线性映射Feed Forward层,层之后都有归一化以及跳跃连接。这里也不做具体讲解。

然后将DecoderLayer简单堆叠就得到了Decoder:

class Decoder(nn.Cell):def __init__(self, layers, norm_layer=None):super(Decoder, self).__init__()self.layers = nn.CellList(layers)self.norm = norm_layerdef construct(self, x, cross, x_mask=None, cross_mask=None):for layer in self.layers:x = layer(x, cross, x_mask=x_mask, cross_mask=cross_mask)if self.norm is not None:x = self.norm(x)return x

5.6 model.py

这一部分将Encoder和Decoder拼接起来形成整个Informer模型。

Informer的模型定义部分如下:

def __init__(self, enc_in, dec_in, c_out, out_len, seq_len,factor=5, d_model=512, n_heads=8, e_layers=3, d_layers=2, d_ff=512,dropout=0.0, attn='prob', embed='fixed', freq='h', activation='gelu',output_attention=False, distil=True, mix=True):super(Informer, self).__init__()self.pred_len = out_lenself.attn = attnself.output_attention = output_attention#对encoder和decoder的输入进行编码self.enc_embedding = DataEmbedding(enc_in, d_model, embed, freq, dropout)self.dec_embedding = DataEmbedding(dec_in, d_model, embed, freq, dropout)# 选择使用的注意力attn_f = ProbAttention if attn == 'prob' else FullAttention# Encoder部分,e_layers个Encoder Layer和e_layers-1个ConvLayer(如果distil为True)self.encoder = Encoder([EncoderLayer(AttentionLayer(attn_f(False, factor, None, attention_dropout=dropout,output_attention=output_attention),d_model, n_heads, mix=False),d_model,d_ff,dropout=dropout,activation=activation) for l in range(e_layers)],[ConvLayer(d_model, seq_len) for l in range(e_layers - 1)] if distil else None,norm_layer=nn.LayerNorm(normalized_shape=[d_model], epsilon=1e-05))# Decoder部分,d_layers个Decoder Layerself.decoder = Decoder([DecoderLayer(AttentionLayer(attn_f(True, factor, None, attention_dropout=dropout, output_attention=False),d_model, n_heads, mix=mix),AttentionLayer(FullAttention(False, factor, None, attention_dropout=dropout,output_attention=False),d_model, n_heads, mix=False),d_model,d_ff,dropout=dropout,activation=activation,)for l in range(d_layers)],  norm_layer=nn.LayerNorm(normalized_shape=[d_model], epsilon=1e-05))#将输出映射到c_outself.projection = nn.Dense(in_channels=d_model, out_channels=c_out, has_bias=True)

模型推理部分不作详细讲解,需要注意的是输出时对于每个batch的最后pred_len长度的结果是最终的输出,即:

            dec_out[:, -self.pred_len:, :] #dec_out : [batch_size, pred_len, c_out]

5.7 生成式解码器

Start token 是 NLP “动态解码, dynamic decoding”中的一项有效技术,尤其是对预训练模型来说,而作者将其扩展到生成式的方法中。

作者没有选择一个额定的标志作为标记,而是从输入序列中抽取一个相对“更短”的长序列,这也是输出序列前的一段序列。

以预测480个点为例(ETT数据集中的5天预测),使用预测序列前的已知的5天作为 “start-token”,并把它作为生成式推理解码器的输入,可以通过一次推理得到所有的预测结果,具体实现如下:

             # decoder inputdec_inp = ms_np.zeros([batch_y.shape[0], self.pred_len, batch_y.shape[-1]]).astype(mstype.float32)#padding:决定用1填充预测的位置还是用0填充if self.padding == 1:dec_inp = ms_np.ones([batch_y.shape[0], self.pred_len, batch_y.shape[-1]]).astype(mstype.float32)dec_inp = self.cat([batch_y[:, :self.label_len, :], dec_inp]).astype(mstype.float32)

最后的输出中填充部分的结果即为最终的输出(5.6节的dec_out)。

6

实验结果

实验选取了一些经典的时序模型和基于Transformer的模型与Informer模型做对比,选取了ETT(Electricity Transformer Temperature),ECL (Electricity Consuming Load)和Weather数据集进行实验,并使用Mean Absolute Error (MAE), Mean Squared Error (MSE)两个指标进行评估。

从单变量实验的结果可以看出:Informer模型显著提高了预测效果,表现和它的退化变体 Informer+相当,且效果更好的次数更多(获胜计数32>12)。

相比与RNN系列的模型LSTMa,Informer模型在MSE这个指标上平均降低了40.9% (168), 51.4% (336) 和58.0% (720),这说明了自注意力机制中较短的网络路径比基于RNN的模型会带来更好的预测能力。

和经典的时序预测模型DeepAR, Arima和Prophet相比,Informer模型在MSE指标上平均降低了35.5% (168), 39.3% (336), and 40.9% (720)。

从多变量实验的结果中也可以得出和单变量实验结果类似的结论。相比于基于RNN的模型LSTMa和基于CNN的模型LSTnet,Informer在MSE指标上平均下降了19.7% (168), 19.2% (336), 22.8%(720)。

在自注意力机制的消融实验中,使用更大规模的数据(更长的输入和更长的预测长度)进行实验,可以看出:Informer能够处理相当长的数据,而原始的Transformer (Informer+)已经无法处理。在相同规模下对比Reformer也取得了更好的结果。

7

总结与展望

本文研究了长序列时间序列预测问题,并提出了用于预测长序列的模型Informer。

具体来说,作者设计了ProbSparse Self-attention机制和自注意力蒸馏操作来解决原始Transformer模型中存在的二次时间复杂度和内存占用的问题。

同时,使用生成式解码器减轻了传统编码-解码结构的局限性,在真实数据集上的实验证明了Informer模型在提高LSTF问题的预测能力方面是十分有效的。

未来将结合Mindspore做一些工作,如结合Mindspore框架改进代码,提升模型性能,提高模型的推理效率,将Informer部署在Mindspore的服务器上,做轻量化Informer并将其部署到移动端,携手华为一起将模型推广出去。

MindSpore官方资料

GitHub : https://github.com/mindspore-ai/mindspore

Gitee : https : //gitee.com/mindspore/mindspore

官方QQ群 : 486831414

是科学还是魔法?Informer on MindSpore——时间序列预测技术实践相关推荐

  1. 【统计】时间序列预测之 Holt-Winters 指数平滑模型

    Holt-Winters Exponential Smoothing 原文连接:link 作者作者:Sachin Date 翻译校对:datamonday Holt-Winters 指数平滑法用于预测 ...

  2. 抽丝剥茧看时间序列预测

    时间序列预测本质上允许企业通过分析以前的数据来预测未来的结果,并让企业了解数据趋势的方向.不过,时间序列预测并非没有挑战,要使用时间序列预测,我们就必须拥有过去的准确数据,并保证这些数据将代表未来事件 ...

  3. 解读:Informer——比Transformer更有效的长时间序列预测方法

    写在前面 下面这篇文章的内容主要是来自发表于AAAI21的一篇最佳论文<Informer: Beyond Efficient Transformer for Long Sequence Time ...

  4. 时间序列预测之为何舍弃LSTM而选择Informer?(Informer模型解读)

    LSTM的劣势 Figure 1: (a) LSTF can cover an extended period than the short sequence predictions, making ...

  5. Informer:用于长序列时间序列预测的新型Transformer

    论文标题:Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting 论文链接:https://a ...

  6. 时间序列预测步骤_建立时间序列预测模型的5个简单步骤

    时间序列预测步骤 I am a strong believer in "learning by doing" philosophy. 我坚信"做中学"的哲学. ...

  7. 干货 | 时间序列预测类问题下的建模方案探索实践

    作者 | 陆春晖 责编 | Carol 出品 | AI科技大本营(ID:rgznai100) 背景 时间序列类问题是数据分析领域中一类常见的问题,人们有时需要通过观察某种现象一段时间的状态,来判断其未 ...

  8. 如何用XGBoost做时间序列预测?

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 来源:Jason Brownlee,整理:数据派THU 本文约3300字 ...

  9. 序列每天从1开始_时间序列预测一

    什么是时间序列: 时间序列可以看作是普通的二维的无序的特征矩阵向时间空间的拓展,相对来说多了仅仅一个维度但也是非常重要的时间维度: 时间序列是按时间顺序进行的一系列观察,通常包括了连续性时间序列数据和 ...

最新文章

  1. 输入A、B,输出A+B
  2. Linux虚机安装配置Tomcat
  3. vbs 连oracle 负载均衡,(原)QTP中用VBS调用PLSQL并执行相关语句
  4. 字典排序什么意思_字典排序问题
  5. ActiveMQ学习总结(5)——Java消息服务JMS详解
  6. git can‘t merge 的处理 代码冲突问题的解决
  7. 提高xshell使用效率
  8. 一个figure存在多个legend:多行多列图例
  9. spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)
  10. Apache基金会获得Pineapple基金88.34比特币捐赠
  11. 2021微信公开课PRO:微信视频号首次公布运营规则,“点赞”表情成视频号年度表情
  12. 企业研发人员配备比例_高新技术企业对研发技术人员占企业总职工人数的比例为多少?...
  13. arm汇编—bic ,orr
  14. codelite编译器配置
  15. 6p14推挽胆机20w功放电路图_6P14推挽双输出牛胆机
  16. 使用MyEntunnel和Proxifier搭建代理服务器
  17. 朴素贝叶斯情感分析评分python_「豆瓣影评」从爬取豆瓣影评到基于朴素贝叶斯的电影评论情感分析(上) - seo实验室...
  18. 李开复成长中的十句格言:求知若饥 虚心若愚(from cnbeta)
  19. OSChina 周六乱弹 ——姑娘原来你爱的是如来
  20. 【Python3零基础入门笔记】05 Python时间处理——time库的使用

热门文章

  1. c51单片机led奇数偶数亮_编写LED控制程序,完成LED奇数号灯和偶数号灯的交替显示...
  2. 信息安全技术 工业控制系统安全控制应用指南
  3. Facebook母公司Meta将开设第一家商店。这里是里面的样子
  4. android的系统优势,安卓新系统也有优势! 对比iOS一点也不输
  5. vmware 14 安装window 7时,出现Network boot from Intel E1000
  6. SpringBoot Web项目结构梳理
  7. 查找一个数等于一组数中某些数相加的和
  8. 用 TypeScript 写一个轻量级的 UI 框架之十三:Grid 表格组件(下)
  9. 四、指针高级应用总结
  10. Git报错:remote: HTTP Basic: Access denied的解决方法