时间序列预测算法——DeepAR
DeepAR概述
DeepAR是亞馬遜提出的一種針對(duì)大量相關(guān)時(shí)間序列統(tǒng)一建模的預(yù)測(cè)算法,該算法采用了深度學(xué)習(xí)的技術(shù),通過(guò)在大量時(shí)間序列上訓(xùn)練自回歸遞歸網(wǎng)絡(luò)模型,可以從相關(guān)的時(shí)間序列中有效地學(xué)習(xí)全局模型,并且能夠?qū)W習(xí)復(fù)雜的模式,例如季節(jié)性、數(shù)據(jù)隨時(shí)間的不確定性增長(zhǎng),從而對(duì)各條時(shí)間序列進(jìn)行預(yù)測(cè)。
DeepAR原理和實(shí)現(xiàn)過(guò)程
上圖左邊是模型的訓(xùn)練過(guò)程,右邊是模型的預(yù)測(cè)過(guò)程。
原理
deepar目標(biāo)是在給定歷史history_len時(shí)間長(zhǎng)度的值及特征的情況下,預(yù)測(cè)未來(lái)future_len時(shí)間長(zhǎng)度的值。
用zi,t表示第i條序列t時(shí)刻的值,xi,t表示第i條t時(shí)刻的特征,用表達(dá)式來(lái)表示就是:P(zi,t0:T∣zi,1:t0?1,Xi,1:T)P(z_{i,t_0:T}|z_{i,1:t_0-1},X_{i,1:T})P(zi,t0?:T?∣zi,1:t0??1?,Xi,1:T?),其中[zi,t0,zi,t0+1,...,zi,T]:=zi,t0:T[z_{i,t_0},z_{i,t_0{+1}},...,z_{i,T}] := z_{i,t_0:T}[zi,t0??,zi,t0?+1?,...,zi,T?]:=zi,t0?:T?,[zi,1,...zi,t0?2,zi,t0?1]:=zi,1:t0?1[z_{i,1},...z_{i,t_0{-2}},z_{i,t_0{-1}}] := z_{i,1:t_0-1}[zi,1?,...zi,t0??2?,zi,t0??1?]:=zi,1:t0??1?,[1,t0?1][1,t_0-1][1,t0??1]代表歷史區(qū)間,[t0,T][t_0,T][t0?,T]代表預(yù)測(cè)區(qū)間。
基于以上,論文設(shè)定模型分布由似然因子的乘積組成:
hi,th_{i,t}hi,t?由神經(jīng)網(wǎng)絡(luò)獲得,即:hi,t=h(hi,t?1,zi,t?1,Xi,t,Θ)h_{i,t}=h(h_{i,t-1},z_{i,t-1},X_{i,t},Θ)hi,t?=h(hi,t?1?,zi,t?1?,Xi,t?,Θ);似然l(zi,t∣θ(hi,t,Θ))l(z_{i,t}|θ(h_{i,t},Θ))l(zi,t?∣θ(hi,t?,Θ))是一個(gè)fixed分布,其中的參數(shù)由神經(jīng)網(wǎng)絡(luò)(lstm)的輸出hi,th_{i,t}hi,t?經(jīng)過(guò)函數(shù)θ(hi,t,Θ)θ(h_{i,t},Θ)θ(hi,t?,Θ)的仿射獲得。
論文中提及了關(guān)于似然函數(shù)的選擇, Gaussian likelihood比較適合數(shù)值型數(shù)據(jù);計(jì)數(shù)型的數(shù)據(jù)比較適合negative-binomial likelihood,另外還有Bernoulli likelihood,student_t等,亞馬遜在SageMaker中實(shí)現(xiàn)的deepar默認(rèn)選擇的似然函數(shù)就是student_t。
最后關(guān)于模型loss的選擇,論文選用對(duì)數(shù)似然進(jìn)行梯度優(yōu)化訓(xùn)練參數(shù)。
實(shí)現(xiàn)過(guò)程
訓(xùn)練時(shí),模型每一時(shí)刻的輸入包括前一時(shí)刻的真實(shí)值和當(dāng)前時(shí)刻的特征x,x可以是當(dāng)前時(shí)刻的時(shí)間特征;然后經(jīng)過(guò)神經(jīng)網(wǎng)絡(luò)的學(xué)習(xí),對(duì)網(wǎng)絡(luò)返回的狀態(tài)hit進(jìn)行函數(shù)仿射,返回當(dāng)前時(shí)刻的預(yù)測(cè)概率分布。
預(yù)測(cè)時(shí),每個(gè)時(shí)刻的輸入也包括兩部分:前一時(shí)刻的預(yù)測(cè)值和當(dāng)前時(shí)刻的協(xié)變量x,即是一種遞歸式的預(yù)測(cè)方法;然后利用學(xué)習(xí)好的網(wǎng)絡(luò),進(jìn)行預(yù)測(cè)。
基于此,可以通過(guò)encode-decode的模式來(lái)實(shí)現(xiàn)DeepAR,其encode和decode的網(wǎng)絡(luò)部分可以使用lstm。假設(shè)時(shí)間序列的時(shí)間粒度是分鐘級(jí)別,可以利用RNN對(duì)l歷史encode_len分鐘長(zhǎng)度的時(shí)間序列進(jìn)行encode,返回的隱藏狀態(tài)輸入到decode,預(yù)測(cè)接下來(lái)decode_len分鐘長(zhǎng)度的時(shí)間序列值。
下面是給出算法核心部分的代碼實(shí)現(xiàn)
訓(xùn)練
首先定義一個(gè)lstm,encode和decode都是基于lstm。
def lstm_cell(layer_num,hidden_size,keep_prob):stacked_rnn = []for i in range(layer_num):lstm = tf.contrib.cudnn_rnn.CudnnCompatibleLSTMCell(hidden_size)drop = tf.nn.rnn_cell.DropoutWrapper(lstm, output_keep_prob=keep_prob)stacked_rnn.append(drop)lstm_multi = tf.contrib.rnn.MultiRNNCell(stacked_rnn)return lstm_multiencode
def encoder(encoder_input, encoder_seq_len, keep_prob):cells = lstm_cell(layer_num,hidden_size,keep_prob)with tf.variable_scope('encoder', reuse=tf.AUTO_REUSE):_, encoder_state = tf.nn.dynamic_rnn(cell=cells, inputs=encoder_input,sequence_length=encoder_seq_len,dtype=tf.float32)return encoder_statedecode
def decoder(decoder_input, decoder_seq_len, state_in, keep_prob):cells = lstm_cell(keep_prob)with tf.variable_scope('decoder', reuse=tf.AUTO_REUSE):decoder_outputs, decoder_state = tf.nn.dynamic_rnn(cell=cells,inputs=decoder_input,sequence_length=decoder_seq_len, initial_state=state_in)return decoder_outputs, decoder_stateloss
舉例使用高斯似然,對(duì)decode的輸出狀態(tài)進(jìn)行仿射得到計(jì)算高斯似然的參數(shù),從而計(jì)算loss進(jìn)行梯度優(yōu)化。
def create_gaussian_parameters(decoder_outputs, decoder_scale_factor, decoder_len,hidden_size):"""對(duì)decode的輸出進(jìn)行仿射,得出計(jì)算高斯似然的參數(shù)。decoder_scale_factor:是歸一化因子"""batch_size = tf.shape(decoder_outputs)[0]with tf.variable_scope('gaussian_parameters', reuse=tf.AUTO_REUSE):W_mu = tf.get_variable(shape=[hidden_size, 1], dtype=tf.float32,name="W_mu")W_sigma = tf.get_variable(shape=[hidden_size, 1], dtype=tf.float32,name="W_sigma")b_mu = tf.get_variable(shape=[1], dtype=tf.float32, name="b_mu")b_sigma = tf.get_variable(shape=[1], dtype=tf.float32, name="b_sigma")W_mu_expand = tf.tile(tf.expand_dims(W_mu, 0), [batch_size, 1, 1])W_sigma_expand = tf.tile(tf.expand_dims(W_sigma, 0), [batch_size, 1, 1])b_mu_expand = tf.tile(tf.expand_dims(b_mu, 0), [batch_size, 1])b_sigma_expand = tf.tile(tf.expand_dims(b_sigma, 0), [batch_size, 1])mu = tf.reshape(tf.matmul(decoder_outputs, W_mu_expand), [batch_size, -1]) + b_mu_expandsigma = tf.log(1 + tf.math.exp(tf.reshape(tf.matmul(decoder_outputs, W_sigma_expand), [batch_size, -1]) + b_sigma_expand)) + 1e-6mu_scale = tf.math.multiply(mu, tf.reshape(decoder_scale_factor, [-1,decoder_len]))sigma_scale = tf.math.multiply(sigma, tf.reshape(decoder_scale_factor, [-1,decoder_len]))return mu_scale, sigma_scaledef gaussian_likelihood(y_true, mu, sigma):return tf.math.reduce_mean(0.5 * tf.math.log(tf.math.square(sigma)) + 0.5 * tf.math.divide(tf.math.square(y_true - mu),tf.math.square(sigma))) + 1e-6預(yù)測(cè)
encode
預(yù)測(cè)時(shí)候的encode和訓(xùn)練時(shí)候一樣。
decode
def decoder_inference(encoder_state, decoder_x_input_scale, decoder_len,decoder_feature, decoder_scale_factor, keep_prob):"""推理的時(shí)候,需要將當(dāng)前時(shí)刻的預(yù)測(cè)值傳遞給下一個(gè)時(shí)刻的輸入。訓(xùn)練的時(shí)候,因?yàn)閿?shù)據(jù)都已知,所以直接做一個(gè)shift的平移。"""mu_ta = tf.TensorArray(dtype=tf.float32, size=decoder_len)sigma_alpha_ta = tf.TensorArray(dtype=tf.float32, size=decoder_len)def cond_fn(time, prev_state, prev_output, decoder_scale_factor, mu_ta, sigma_alpha_ta):return time < decoder_lendef loop_fn(time, prev_state, prev_output, decoder_scale_factor, mu_ta, sigma_alpha_ta):batch_size = tf.shape(prev_output)[0]features = tf.slice(decoder_feature, [0, time, 0], [-1, 1, -1])next_input = tf.concat([prev_output, features], -1)decoder_seq_len = tf.ones([batch_size])decoder_outputs, decoder_state = decoder(next_input, decoder_seq_len, prev_state, keep_prob)mu, sigma_alpha = create_gaussian_parameters(decoder_outputs, decoder_scale_factor, 1)mu_ta = mu_ta.write(time, mu)sigma_alpha_ta = sigma_alpha_ta.write(time, sigma_alpha)sample_data = musample_data_scale = tf.math.divide(tf.reshape(sample_data, [batch_size, 1, 1]), decoder_scale_factor)return time + 1, decoder_state, sample_data_scale, decoder_scale_factor, mu_ta, sigma_alpha_taloop_init = [tf.constant(0, dtype=tf.int32),encoder_state,decoder_x_input_scale,decoder_scale_factor,mu_ta,sigma_alpha_ta]_, _, _, _, mu_output, sigma_alpha_output = tf.while_loop(cond_fn, loop_fn, loop_init)mu_result = tf.reshape(tf.transpose(mu_output.stack(), perm=[1, 0, 2]),[-1, decoder_len])sigma_alpha_result = tf.reshape(tf.transpose(sigma_alpha_output.stack(), perm=[1, 0, 2]),[-1, decoder_len])return mu_result, sigma_alpha_result算法的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
1.對(duì)實(shí)數(shù)和計(jì)數(shù)分別設(shè)計(jì)了不同的loss;
2.數(shù)據(jù)預(yù)處理方面使用歸一化的變換和預(yù)測(cè)使用weighted sampling。
缺點(diǎn)
1.沒(méi)有attention機(jī)制,對(duì)較長(zhǎng)的時(shí)間序列可能會(huì)出現(xiàn)記憶丟失的問(wèn)題,無(wú)法捕獲長(zhǎng)周期、季節(jié)等信息。但在輸入部分可以加入attention機(jī)制,比如用同期的數(shù)據(jù)作為一個(gè)特征。
其他
1.預(yù)測(cè)多條時(shí)間序列時(shí),論文中提到可以對(duì)每條時(shí)間序序列進(jìn)行category的編碼,訓(xùn)練時(shí)進(jìn)行embedding的學(xué)習(xí);
2.可以提取每條時(shí)間序列的時(shí)間特征,作為feature輸入到模型。
論文
論文連接
總結(jié)
以上是生活随笔為你收集整理的时间序列预测算法——DeepAR的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: EndNoteX7中conference
- 下一篇: java 判断数字二进制有几位_判断一个