TPA注意力机制(TPA-LSTM)

TPA注意力机制(TPA-LSTM)

论文题目:Temporal Pattern Attention for Multivariate Time Series Forecasting

TPA-LSTM:

  • 用于多变量时间序列预测(Multivariate Time Series)
  • 传统attention机制会选择相关的时间步timesteps加权
  • 论文中的attention机制(Temporl Pattern Attention)会选择相关变量加权

代码:TPA-LSTM

这里结合代码介绍TPA注意力机制选择相关变量的原因

其它时间序列方法可参考回答,时间序列预测方法总结


1.根据论文理解TPA

论文中TPA注意力机制示意图如下所示:

1.1 LSTM处理时间序列

对原始时间序列使用LSTMBlockCell处理,得到每个timesteps的隐状态h_i(列向量),每个h_i维度为m。其中,w是滑窗窗口长度,得到的隐状态矩阵H={h_t-w, h_t-w+1, ..., h_t-1}。因此,隐状态矩阵的行列向量意义:

  • 行向量代表单个变量在所有时间步下状态,即同一变量的所有时间步构成的向量。
  • 列向量代表单个时间步状态,即同一时间步下的所有变量构成的向量。

1.2 CNN检测时间模式(Temporal Pattern)

利用卷积捕获可变的信号模式,公式如下:

卷积配置为k个filters,kernel尺寸为1×T(T代表attention时所覆盖的范围,可理解为attn_length,通常令T=w),将上述kernel沿隐状态矩阵H的行向量计算卷积,提取该变量在该卷积核范围attn_length内的时间模式矩阵H^c。H_(i,j)表示第i个行向量和第j个卷积核作用的结果值。

1.3 注意力加权

1) 令query=h_t, key=H^c, 则scoring function为:

2) 利用sigmoid进行归一化,得到注意力权重,便于选择多变量:

3) 利用注意力权重,对H^c每行做加权求和,得到上下文向量v_t:

备注:

  • 这里仅与最后一个隐向量h_t计算得分
  • 最终的上下文向量表示对时间模式矩阵H^c行向量的加权求和,且其行向量代表单个变量的temporal pattern,因此TPA选择相关变量加权。

2. 根据代码理解TPA

tensorflow中可以使用AttentionCellWrapper为基类实现注意力机制,关键在于替换注意力计算原理即可,涉及这行代码。

# _attention计算
new_attns, new_attn_states = self._attention(new_state_cat, attn_states)

因此,在TemporalPatternAttentionCellWrapper类中,作者也是仿照AttentionCellWrapper实现,注意力计算替换为:

# TPA注意力计算
self._attention_mech = TemporalPatternAttentionMechanism()
new_attns, new_attn_states = self._attention_mech(
            new_state_cat, attn_states, self._attn_size, self._attn_length,
            self._attn_vec_size)

备注:

  • _atten_length表示时间timesteps,_atten_size表示特征维度dims。实际代码中的行列向量意义与前面公式描述的隐状态矩阵的行列向量意义相反。

2.1 传统attention计算

传统attention选择timesteps,即选择某个h_i更重要,代码如下:

with vs.variable_scope("attention"):
    # 1.k为卷积核,kernel尺寸为(1,1),输入通道数attn_size, 输出通道数attn_vec_size
    k = vs.get_variable("attn_w",
                        [1, 1, self._attn_size, self._attn_vec_size])
    v = vs.get_variable("attn_v", [self._attn_vec_size])

    # 2.隐状态矩阵reshape为 H,W,C =  [self._attn_length, 1, self._attn_size]
    # 代表该矩阵, 宽度=1, 通道数=attn_size
    hidden = array_ops.reshape(attn_states,
                               [-1, self._attn_length, 1, self._attn_size])

    # 3.根据hidden和k的维度特点,该卷积操作实际是在融合hidden矩阵中同一隐状态向量hi的所有通道信息
    # 其中,attn_length保持不变,因此在计算隐状态向量hi的得分
    hidden_features = conv2d(hidden, k, [1, 1, 1, 1], "SAME")

    if self._linear3 is None:
      self._linear3 = _Linear(query, self._attn_vec_size, True)
    y = self._linear3(query)
    y = array_ops.reshape(y, [-1, 1, 1, self._attn_vec_size])
    s = reduce_sum(v * tanh(hidden_features + y), [2, 3])
    a = softmax(s)
    
    # 4.权重a矩阵reshape为[-1, self._attn_length, 1, 1],说明是沿着attn_length方向加权
    # 因此该注意力选择重要的隐状态向量hi
    d = reduce_sum(
        array_ops.reshape(a, [-1, self._attn_length, 1, 1]) * hidden, [1, 2])

    new_attns = array_ops.reshape(d, [-1, self._attn_size])
    new_attn_states = array_ops.slice(attn_states, [0, 1, 0], [-1, -1, -1])

卷积操作过程如下图所示:

2.2 TPA attention计算

TPA attention选择重要的相关变量,即选择某个维度更重要,代码如下:

with tf.variable_scope("attention"):
    filter_num = 32
    filter_size = 1

    # w: [batch_size, 1, filter_num]
    w = tf.reshape(
        dense(query, filter_num, use_bias=False), [-1, 1, filter_num])
    # 1.隐状态矩阵reshape为 H,W,C =  [attn_length, attn_size, 1]
    # 代表该矩阵, 宽度=attn_size, 通道数=1
    reshape_attn_vecs = tf.reshape(attn_states,
                                   [-1, attn_length, attn_size, 1])
    
    # 2.卷积核尺寸为[attn_length, 1],该卷积融合隐状态矩阵中同一变量维度的所有隐状态向量,
    # 其中atten_size保持不变,沿attn_length融合,计算各变量维度的得分
    conv_vecs = tf.layers.conv2d(
        inputs=reshape_attn_vecs,
        filters=filter_num,
        kernel_size=[attn_length, filter_size],
        padding="valid",
        activation=None,
    )
    feature_dim = attn_size - filter_size + 1

    # 3.卷积特征图reshape为[feature_dim, filter_num]
    # conv_vecs: [batch_size, feature_dim, filter_num]
    conv_vecs = tf.reshape(conv_vecs, [-1, feature_dim, filter_num])

    # s: [batch_size, feature_dim]
    s = tf.reduce_sum(tf.multiply(conv_vecs, w), [2])

    # a: [batch_size, feature_dim]
    a = tf.sigmoid(s)

    # 4.权重a矩阵reshape为[-1, feature_dim, 1],说明是沿着feature_dim方向加权
    # 因此该注意力选择重要的变量维度
    # d: [batch_size, filter_num]
    d = tf.reduce_sum(
        tf.multiply(tf.reshape(a, [-1, feature_dim, 1]), conv_vecs),
        [1])
    
    new_conv_vec = tf.reshape(d, [-1, filter_num])
    new_attns = tf.layers.dense(
        tf.concat([query, new_conv_vec], axis=1), attn_size)
    new_attn_states = tf.slice(attn_states, [0, 1, 0], [-1, -1, -1])
    return new_attns, new_attn_states

卷积操作过程如下图所示:


欢迎讨论,转载请联系我~

编辑于 03-25