時(shí)間序列預(yù)測(cè)方法之 DeepState

本文鏈接個(gè)人站 | 簡(jiǎn)書 | CSDN
版權(quán)聲明:除特別聲明外觉义,本博客文章均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請(qǐng)注明出處。

最近打算分享一些基于深度學(xué)習(xí)的時(shí)間序列預(yù)測(cè)方法。這是第二篇辽剧。

今次介紹的是 Amazon 在 NIPS 2018 上發(fā)表的文章 Deep State Space Models for Time Series Forecasting臂寝。

狀態(tài)空間模型(State Space Models)起源于控制工程領(lǐng)域章鲤,典型的應(yīng)用包括卡爾曼濾波等。時(shí)間序列分析中的一些經(jīng)典方法咆贬,如 ARIMA败徊、Holt-Winters’ 等,都可以改寫成狀態(tài)空間模型素征。狀態(tài)空間模型對(duì)每個(gè)時(shí)間序列單獨(dú)建模集嵌,無法利用序列之間相似的模式,因而對(duì)歷史數(shù)據(jù)較少的序列往往無能為力御毅。

DeepState 將狀態(tài)空間模型與深度學(xué)習(xí)結(jié)合起來根欧。先用循環(huán)神經(jīng)網(wǎng)絡(luò)將特征映射為狀態(tài)空間模型的參數(shù),再使用狀態(tài)空間模型預(yù)測(cè)序列在每個(gè)時(shí)間步上取值的概率分布端蛆。所有的時(shí)間序列共享網(wǎng)絡(luò)本身的參數(shù)凤粗,而每個(gè)時(shí)間序列都有獨(dú)立的狀態(tài)空間參數(shù)。這樣一來今豆,既能從大量的序列和特征中學(xué)習(xí)到相似的模式嫌拣,又能使模型具有一定的可解釋性。

Model

通常來說呆躲,狀態(tài)空間模型包含一個(gè)狀態(tài)轉(zhuǎn)移方程和一個(gè)觀測(cè)模型异逐,前者描述了隱藏狀態(tài)隨時(shí)間變化的規(guī)律 p(l_t|l_{t-1}),后者概括了給定隱藏狀態(tài)下觀測(cè)值的條件概率分布 p(z_t|l_t)插掂,其中隱藏狀態(tài) l_t \in \mathbb R^L灰瞻。

DeepState 使用的是線性高斯?fàn)顟B(tài)空間模型,其狀態(tài)轉(zhuǎn)移方程形如[1]

l_t = F_tl_{t-1} + w_t\varepsilon_t,\qquad \varepsilon_t\sim N(0, 1)
觀測(cè)模型形如
z_t = H_t l_t + b_t+v_t\epsilon_t, \qquad \epsilon_t\sim N(0, 1)
其中 F_t\in\mathbb R^{L\times L} 為狀態(tài)轉(zhuǎn)移矩陣辅甥,w_t\in\mathbb R_+^L 是狀態(tài)轉(zhuǎn)移噪聲的強(qiáng)度酝润,H_t\in\mathbb R^{1\times L}b_t\in\mathbb R 是觀測(cè)模型的權(quán)重和偏置,v_t\in\mathbb R_+ 是觀測(cè)噪聲的強(qiáng)度璃弄。初始狀態(tài) l_0\sim N(\mu_0, diag(\sigma_0^2))要销。

綜上,線性高斯?fàn)顟B(tài)空間模型的參數(shù)為 \Theta_t = (F_t, H_t, w_t, b_t, v_t, \mu_0, \sigma_0), \forall t>0夏块。

DeepState 模型的結(jié)構(gòu)如下圖所示疏咐。先用循環(huán)神經(jīng)網(wǎng)絡(luò)計(jì)算 h_t = \mathrm{RNN}(h_{t-1}, x_t),再用 h_t 計(jì)算狀態(tài)空間模型的參數(shù) \Theta_t = \Psi(h_t)脐供,最后計(jì)算似然 p_{SS}(z_{1:T}|\Theta_{1:T})凳鬓,通過最大化對(duì)數(shù)似然來學(xué)習(xí)網(wǎng)絡(luò)的參數(shù)。

DeepState 模型

似然函數(shù)可以分解為
p_{SS}(z_{1:T}|\Theta_{1:T}) = \prod_tp(z_t|z_{1:t-1}, \Theta)
參考我們?cè)?a href="http://www.reibang.com/p/da4dd6d0d8a2" target="_blank">《卡爾曼濾波簡(jiǎn)介》中給出的推導(dǎo)患民,可以很容易得到
p(z_t|z_{1:t-1}) = N(H_t\hat l_{t|t-1} + b_t, S_t)
式中的參數(shù)可以通過以下遞推關(guān)系
\begin{aligned} \hat l_{t|t-1} & = F_t\hat l_{t-1|t-1}\\ P_{t|t-1} &= F_tP_{t-1|t-1}F_t^\top + w_tw_t^\top\\ \tilde y_t &= z_t - H_t\hat l_{t|t-1} - b_t\\ S_t &= H_tP_{t|t-1}H_t^\top + v_tv_t^\top\\ K_t &= P_{t|t-1}H_t^\top S_t^{-1}\\ \hat l_{t|t} &= \hat l_{t|t-1} + K_t \tilde y_t\\ P_{t|t} &= P_{t|t-1} - K_tH_tP_{t|t-1} \end{aligned}
計(jì)算得到。其中 \hat l_{0|0} = \mu_0垦梆,P_{0|0} = diag(\sigma_0^2)匹颤。

預(yù)測(cè)階段與之前介紹的 DeepAR 類似仅孩,都是使用祖先采樣方法獲取一批預(yù)測(cè)區(qū)間內(nèi)每個(gè)時(shí)間步上的樣本點(diǎn),然后利用樣本計(jì)算感興趣的統(tǒng)計(jì)量印蓖。

Code

這里給出一個(gè)基于 TensorFlow 構(gòu)建的簡(jiǎn)單 demo辽慕。

import numpy as np

import tensorflow as tf
import tensorflow_probability as tfp

class DeepState(tf.keras.models.Model):
    """
    DeepState 模型
    """
    def __init__(self, lstm_units, latent_dim):
        super().__init__()
        
        self.latent_dim = latent_dim
        self.output_dim = 1
        
        # 注意,文章中使用了多層的 LSTM 網(wǎng)絡(luò)赦肃,為了簡(jiǎn)單起見溅蛉,本 demo 只使用一層
        self.lstm = tf.keras.layers.LSTM(lstm_units, return_sequences=True, return_state=True)
        self.dense_l_prior = tf.keras.layers.Dense(latent_dim)
        self.dense_P_prior = tf.keras.layers.Dense(latent_dim, activation='softplus')
        self.dense_F = tf.keras.layers.Dense(latent_dim * latent_dim)
        self.dense_H = tf.keras.layers.Dense(output_dim * latent_dim)
        self.dense_b = tf.keras.layers.Dense(output_dim)
        self.dense_w = tf.keras.layers.Dense(latent_dim, activation='softplus')
        self.dense_v = tf.keras.layers.Dense(output_dim, activation='softplus')
    
    def call(self, inputs, initial_state=None, prior=True):
        batch_size, time_steps, _ = inputs.shape
        
        outputs, state_h, state_c = self.lstm(inputs, initial_state=initial_state)
        state = [state_h, state_c]
            
        F = tf.reshape(self.dense_F(outputs), [batch_size, time_steps, self.latent_dim, self.latent_dim])
        H = tf.reshape(self.dense_H(outputs), [batch_size, time_steps, self.output_dim, self.latent_dim])
        
        b = tf.expand_dims(self.dense_b(outputs), -1)
        w = tf.expand_dims(self.dense_w(outputs), -1)
        v = tf.expand_dims(self.dense_v(outputs), -1)
        
        Q = tf.matmul(w, tf.transpose(w, [0, 1, 3, 2]))
        R = tf.matmul(v, tf.transpose(v, [0, 1, 3, 2]))
        
        params = [F, H, b, Q, R]
        
        if prior:
            l = tf.expand_dims(self.dense_l_prior(outputs[:, :1, :]), -1)
            P = tf.linalg.diag(self.dense_P_prior(outputs[:, :1, :]))
            params += [l, P]
        
        return [params, state]

def kalman_step(F, H, b, Q, R, l, P, z=None):
    """
    卡爾曼濾波的單步操作
    """
    sampling = z is None

    l = tf.matmul(F, l)
    P = tf.matmul(tf.matmul(F, P), tf.transpose(F, [0, 1, 3, 2])) + Q
    z_pred = tf.matmul(H, l) + b
    S = tf.matmul(tf.matmul(H, P), tf.transpose(H, [0, 1, 3, 2])) + R
    if sampling:
        z = tfp.distributions.Normal(z_pred, S).sample()
    else:
        log_prob = tfp.distributions.Normal(z_pred, S).log_prob(z)
    K = tf.matmul(tf.matmul(P, tf.transpose(H, [0, 1, 3, 2])), tf.linalg.inv(S))
    y = z - z_pred
    l = l + tf.matmul(K, y)
    P = P - tf.matmul(tf.matmul(K, H), P)
    
    if sampling:
        return [l, P, z]
    return [l, P, log_prob]

def kalman_filtering(F, H, b, Q, R, l, P, z=None):
    """
    卡爾曼濾波
    """
    time_steps = F.shape[1]
    if z is None:
        samples = []
        for t in range(time_steps):
            Ft = F[:, t:t+1, :, :]
            Ht = H[:, t:t+1, :, :]
            bt = b[:, t:t+1, :, :]
            Qt = Q[:, t:t+1, :, :]
            Rt = R[:, t:t+1, :, :]
            l, P, zt = kalman_step(Ft, Ht, bt, Qt, Rt, l, P)
            samples.append(zt)
        return samples
    else:
        log_probs = []
        for t in range(time_steps):
            Ft = F[:, t:t+1, :, :]
            Ht = H[:, t:t+1, :, :]
            bt = b[:, t:t+1, :, :]
            Qt = Q[:, t:t+1, :, :]
            Rt = R[:, t:t+1, :, :]
            zt = z[:, t:t+1, :, :]
            l, P, log_prob = kalman_step(Ft, Ht, bt, Qt, Rt, l, P, zt)
            log_probs.append(log_prob)
        loss = -tf.reduce_sum(log_probs)
        return l, P, loss

實(shí)例化模型,指定優(yōu)化器他宛,就可以訓(xùn)練了:

LSTM_UNITS = 16
LATENT_DIM = 10
EPOCHS = 10

# 實(shí)例化模型
model = DeepState(LSTM_UNITS, LATENT_DIM)

# 指定優(yōu)化器
optimizer = tf.keras.optimizers.Adam()

# 定義訓(xùn)練步
def train_step(x, z):
    with tf.GradientTape() as tape:
        params, _ = model(x)
        _, _, loss_value = kalman_filtering(*params, z)
    gradients = tape.gradient(loss_value, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    return loss_value.numpy()

# 數(shù)據(jù)處理(略)
# train_data = do_something()

# 訓(xùn)練
for epoch in range(EPOCHS):
    loss = []
    for x, z in train_data:
        loss.append(train_step(x, z))
    print('Epoch %d, Loss %.4f' % (epoch + 1, np.mean(loss))

為了驗(yàn)證代碼是否有效船侧,我們使用一個(gè)人工生成的時(shí)間序列進(jìn)行訓(xùn)練,下圖展示了這個(gè)序列的一部分?jǐn)?shù)據(jù)點(diǎn)厅各。


時(shí)間序列

經(jīng)過訓(xùn)練后用于預(yù)測(cè)镜撩,效果如下圖所示,其中陰影部分表示 0.05 分位數(shù) ~ 0.95 分位數(shù)的區(qū)間队塘。


預(yù)測(cè)效果

與 DeepAR 對(duì)比

  • DeepAR 學(xué)習(xí)的是概率分布的參數(shù)袁梗,DeepState 學(xué)習(xí)的是狀態(tài)空間模型的參數(shù),因而 DeepState 具有更強(qiáng)的先驗(yàn)憔古,在這個(gè)先驗(yàn)正確的前提下遮怜,理論上需要的訓(xùn)練數(shù)據(jù)應(yīng)該更少一些。
  • DeepAR 將當(dāng)前時(shí)間步的目標(biāo)值作為下一個(gè)時(shí)間步的輸入鸿市,因而更容易受異常值的干擾锯梁,魯棒性不如 DeepState。這種網(wǎng)絡(luò)設(shè)計(jì)也導(dǎo)致了在預(yù)測(cè)階段灸芳,每進(jìn)行一輪采樣涝桅,DeepAR 都要重新展開循環(huán)神經(jīng)網(wǎng)絡(luò)計(jì)算后驗(yàn)分布的參數(shù)。相比之下烙样,DeepState 只需要使用網(wǎng)絡(luò)計(jì)算一次狀態(tài)空間模型的參數(shù)即可進(jìn)行多輪采樣[2]冯遂。
  • DeepSate 基于線性高斯?fàn)顟B(tài)空間模型,很難推廣到其它分布谒获。DeepAR 則不存在這個(gè)問題蛤肌,你可以根據(jù)數(shù)據(jù)特點(diǎn)選擇合適的分布。

  1. 這里使用的記號(hào)與原文略有不同批狱。 ?

  2. 文章里是這樣寫的裸准。但是得到狀態(tài)空間模型的參數(shù)之后,每一輪采樣也需要使用卡爾曼濾波算法遞推計(jì)算赔硫,效率也并沒有高到哪里去啊炒俱。 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末权悟,一起剝皮案震驚了整個(gè)濱河市砸王,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌峦阁,老刑警劉巖谦铃,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異榔昔,居然都是意外死亡驹闰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門撒会,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘹朗,“玉大人,你說我怎么就攤上這事茧彤÷庀裕” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵曾掂,是天一觀的道長(zhǎng)惫谤。 經(jīng)常有香客問我,道長(zhǎng)珠洗,這世上最難降的妖魔是什么溜歪? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮许蓖,結(jié)果婚禮上蝴猪,老公的妹妹穿的比我還像新娘。我一直安慰自己膊爪,他們只是感情好自阱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著米酬,像睡著了一般沛豌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赃额,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天加派,我揣著相機(jī)與錄音,去河邊找鬼跳芳。 笑死芍锦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的飞盆。 我是一名探鬼主播娄琉,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼次乓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了车胡?” 一聲冷哼從身側(cè)響起檬输,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匈棘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體析命,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡主卫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹃愤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片簇搅。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖软吐,靈堂內(nèi)的尸體忽然破棺而出瘩将,到底是詐尸還是另有隱情,我是刑警寧澤凹耙,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布姿现,位于F島的核電站,受9級(jí)特大地震影響肖抱,放射性物質(zhì)發(fā)生泄漏备典。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一意述、第九天 我趴在偏房一處隱蔽的房頂上張望提佣。 院中可真熱鬧,春花似錦荤崇、人聲如沸拌屏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倚喂。三九已至,卻和暖如春喜每,著一層夾襖步出監(jiān)牢的瞬間务唐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工带兜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枫笛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓刚照,卻偏偏與公主長(zhǎng)得像刑巧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345