复现论文 A Dual-Stage Attention-Based Recurrent Neural Network for Time Series Prediction 用于时间序列预测

星期二, 03. 十二月 2019 09:34下午

注:论文实现代码和论文都在我的git账号下,欢迎交流讨论

论文题目:

论文基本框架

1.png

1、主要内容

该论文主要通过在编码层和解码层都引入双向注意力机制实现时间序列更好的预测

2、输入数据

输入数据地址来自于:https://cseweb.ucsd.edu/~yaq007/NASDAQ100_stock_data.html
数据名称为 nasdaq100/small/nasdaq100_padding.csv
直接下载该csv文件,会得到一个82列的df,最后一列是标签,训练集和验证集通过如下代码生成:

def get_data(data_path,T, n):
    input_X = []
    input_Y = []
    label_Y = []

    df = pd.read_csv(data_path)
    row_length = len(df)
    column_length = df.columns.size
    for i in range(row_length-T+1):
        X_data = df.iloc[i:i+T, 0:column_length-1]
        Y_data = df.iloc[i:i+T-1,column_length-1]
        label_data = df.iloc[i+T-1,column_length-1]
        input_X.append(np.array(X_data))
        input_Y.append(np.array(Y_data))
        label_Y.append(np.array(label_data))
    input_X = np.array(input_X).reshape(-1,T,n)
    input_Y = np.array(input_Y).reshape(-1,T-1,1)
    label_Y = np.array(label_Y).reshape(-1,1)
    return input_X,input_Y,label_Y

其中,T为窗口长度,n为传感器数目,即81(82-1),算法通过第k个窗口中前T个传感器数据值和T-1个标签值,预测第T个标签值。

模型框架

模型一共分为两层,即编码阶段Attention和解码阶段Attention,两者实现的思路是一致的,这里只说论文核心的两部分

Attention程序实现

    @staticmethod
    def _attention_layer(_h_t_1 = None,     # [-1, cell_dim]
                         _s_t_1 = None,     # [-1, cell_dim]
                         _x_k   = None,     # input attention layer   : [-1, input_dim, time_step]
                                            # temporal attention layer: [-1, time_step, input_dim];
                         _We    = None,     # [2*cell_dim, time_step]
                         _Ue    = None,     # [time_step, time_step]
                         _Ve    = None, ):  # [time_step, 1]
        _input = tf.concat([_h_t_1, _s_t_1], axis=1)  # [-1, 2*cell_dim]
        _output = tf.reshape(tf.transpose(tf.tensordot(_We, _input, axes=[0, 1])), [-1, _We.get_shape().as_list()[-1], 1]) + \
                  tf.transpose(tf.tensordot(_Ue, _x_k, axes=[0, 2]), perm=[1, 0, 2])   # [-1, time_step, input_dim]
        return tf.reshape(tf.tensordot(_Ve, tf.tanh(_output), axes=[0, 1]), \
                          [-1, _x_k.get_shape().as_list()[1]])    # input attention layer   : [-1, input_dim]
                                                                  # temporal attention layer: [-1, time_step]

Attention的实现是很简单的,这里不详细叙说。

论文中主要解决的问题

  • 第一个问题:LSTM中如何实现Attention?
  • 第二个问题:如何将历史标签用于解码阶段?

关于第一个问题,论文中用了如下公式:
论文中的公式(8):
e_t^k=V_e^Ttanh(W_e[h_{t-1};s_{t-1}]+U_ex^k)
论文中的公式(9):
\alpha_t^k=\frac{exp(e_t^k)}{\sum_{i=1}^nexp(e_t^i)}
式中,x^k为第k个传感器窗口为T的样本;h_{t-1}s_{t-1}分别为编码器LSTM在t-1时刻的隐层状态和细胞状态,V_e, W_e, U_e为需要学习的参数。

关于第二个问题,论文中用了如下公式:
论文中的公式(15):
\breve{y}_{t-1}=\breve{w}^T[y_{t-1};c_{t-1}]+\breve{b}
式中,y_{t-1}t-1时刻的历史标签,c_{t-1}为解码器LSTM在t-1时刻的细胞状态,得到的\breve{y}_{t-1}为解码器LSTM在t-1时刻的输入。

论文中的编码阶段实现:

    def _Encode(self, encode_input=None):  # encode_input: [-1, time_step, input_dim]
        x_k = tf.transpose(encode_input, perm=[0, 2, 1], name='Series_of_length_TIME_STEP')#[-1,input_dim,time_step]
        encode_time_step_hidden = []
        for t in range(encode_input.get_shape()[1]):  # [t < time_step]
            e_t = self._attention_layer(_h_t_1 = self.encode_hidden,
                                        _s_t_1 = self.encode_cell,
                                        _x_k   = x_k,
                                        _We    = self._weights['Input_attention_layer_We'],
                                        _Ue    = self._weights['Input_attention_layer_Ue'],
                                        _Ve    = self._weights['Input_attention_layer_Ve'], )
            a_t = tf.nn.softmax(e_t)  # [-1, input_dim]
            tmp = tf.reshape(encode_input[:, t, :], shape=[-1, encode_input.get_shape().as_list()[-1]])
            x_t = tf.multiply(a_t, tmp)
            (self.encode_cell, self.encode_hidden) = self._LSTMCell(h_t_1 = self.encode_hidden,
                                                                    s_t_1 = self.encode_cell,
                                                                    x_t   = x_t,
                                                                    name  = 'Encode_LSTMCell')
            encode_time_step_hidden.append(self.encode_hidden)
        return tf.reshape(tf.stack(encode_time_step_hidden), [-1, self.TIME_STEP, self.DECODE_CELL])

注:程序用了for循环,因为每一个LSTM单元都用了Attention

论文中的解码阶段实现:

    def _Decode(self, decode_input=None, y_t=None):
        for t in range(decode_input.get_shape()[1]-1):
            l_t = self._attention_layer(_h_t_1 = self.decode_hidden,
                                        _s_t_1 = self.decode_cell,
                                        _x_k   = decode_input,
                                        _We    = self._weights['Temporal_attention_layer_Wd'],
                                        _Ue    = self._weights['Temporal_attention_layer_Ud'],
                                        _Ve    = self._weights['Temporal_attention_layer_Vd'], )
            b_t = tf.reshape(tf.nn.softmax(l_t), shape=[-1, decode_input.get_shape().as_list()[1], 1])  # [-1, time_step, 1]
            c_t = tf.reduce_sum(tf.multiply(b_t, decode_input), axis=1)  # [-1, time_step, 1]*[-1, time_step, cell_dim]
                                                                         # ---> [-1, time_step, cell_dim]-->[-1, cell_dim]
            y_t_ = self._Dense(_input       = tf.concat([c_t, tf.reshape(y_t[:, t], [-1, 1])], axis=1),
                               _weights     = self._weights['Decode_layer_yt_weights'],
                               _bias        = self._weights['Decode_layer_yt_bias'],
                               _activation  = None,
                               _dtype       = tf.float32,
                               _is_bias     = True, )
            (self.decode_cell, self.decode_hidden) = self._LSTMCell(h_t_1 = self.decode_hidden,
                                                                    s_t_1 = self.decode_cell,
                                                                    x_t   = y_t_,
                                                                    name  = 'Decode_LSTMCell')
        pre_y_ = self._Dense(_input       = tf.concat([self.decode_hidden, self.decode_cell], axis=1),
                             _weights     = self._weights['Decode_layer_output_1_weights'],
                             _bias        = self._weights['Decode_layer_output_1_bias'],
                             _activation  = None,
                             _dtype       = tf.float32,
                             _is_bias     = True, )
        pre_y = self._Dense(_input       = pre_y_,
                            _weights     = self._weights['Decode_layer_output_2_weights'],
                            _bias        = self._weights['Decode_layer_output_2_bias'],
                            _activation  = None,
                            _dtype       = tf.float32,
                            _is_bias     = True, )
        return pre_y

注:编码和解码的程序是相似的,但是加入了历史标签
简而言之,论文就是在编码阶段对每一个LSTM单元引入了Attention,解码阶段也是这样

程序实现

程序的具体实现都在我的git账户上,对比其他git上的实现,亲测我的实现mse是更好的,关于具体的程序请看git或者留言与我讨论,关于程序中可能出现的问题欢迎打扰。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容