拓端tecdat|R語言用FNN-LSTM假近鄰長短期記憶人工神經(jīng)網(wǎng)絡模型進行時間序列深度學習預
原文鏈接:http://tecdat.cn/?p=23792
原文出處:拓端數(shù)據(jù)部落公眾號
在最近的一篇文章中,我們展示了一個LSTM模型,通過假近鄰(FNN)損失進行正則化,可以用來重建一個非線性動態(tài)系統(tǒng)。在這里,我們探討了同樣的技術是如何協(xié)助預測的。與 "普通LSTM "相比,F(xiàn)NN-LSTM在數(shù)據(jù)集上提高了性能,特別是在多步驟預測的初始階段。
深度學習與時間序列的結合:生成經(jīng)驗性時間序列數(shù)據(jù)的預測。
簡而言之,解決的問題如下。對一個已知或假定為非線性且高度依賴初始條件的系統(tǒng)進行觀測,得出一系列標量的測量結果。這些測量結果不僅僅有噪聲,而且,它們是多維狀態(tài)空間對一條線的投影。
通常在非線性時間序列分析中,這種標量系列的觀測值是通過在每個時間點上補充同一系列的滯后測量值來增加的--這種技術稱為滯后坐標嵌入(Sauer, Yorke, and Casdagli 1991)。例如,我們可以有一個由向量X1、X2和X3組成的矩陣,而不是只有一個向量X1,X2包含與X1相同的值,但從第三個觀測點開始,而X3則從第五個觀測點開始。在這種情況下,滯后將是2,而嵌入維度是3。各種定理指出,如果這些參數(shù)被充分選擇,就有可能重建完整的狀態(tài)空間。但是有一個問題。這些定理假定真實狀態(tài)空間的維度是已知的,而在許多現(xiàn)實世界的應用中,情況并非如此。
訓練一個自動編碼器,它的中間表示法封裝了系統(tǒng)的吸引子。但不是任何MSE優(yōu)化的自動編碼器。潛在表征通過假近鄰(FNN)損失進行規(guī)范化,這是一種常用于延遲坐標嵌入的技術,以確定適當?shù)那度刖S度。假近鄰是指那些在n維空間中接近,但在n+1維空間中明顯相距較遠的樣本。
我們首先描述設置,包括模型定義、訓練程序和數(shù)據(jù)準備。
設置
從重建到預測
像通常的自動編碼器一樣,訓練時的目標與輸入相同,這意味著整體損失由兩部分組成。FNN損失,僅在潛像上計算,以及輸入和輸出之間的均方誤差損失?,F(xiàn)在,對于預測來說,目標由未來的值組成,只要我們想預測,就有很多。換句話說。架構保持不變,但我們以標準的RNN方式進行預測,而不是重建。通常的RNN設置只是直接連接所需數(shù)量的LSTM,我們有一個LSTM編碼器,輸出一個(無時間步長的)潛在代碼,和一個LSTM解碼器,從該代碼開始,根據(jù)需要重復多次,預測所需數(shù)量的未來值。
這當然意味著,為了評估預測性能,我們需要與僅有LSTM設置的模型進行比較。這
我們在四個數(shù)據(jù)集上進行這些比較。
模型定義和訓練設置
在所有四個實驗中,我們使用相同的模型定義和訓練程序,唯一不同的參數(shù)是LSTMs中使用的時間步數(shù)。
兩種架構都簡單明了,并且在參數(shù)數(shù)量上具有可比性--基本上都是由兩個具有32個單元的LSTM組成(所有實驗中n_recurrent將被設置為32)。?
FNN-LSTM
我們把編碼器LSTM分成了兩個,最大潛在狀態(tài)維度保持為10。
# DL-相關軟件包
library(tensorflow)
library(keras)
keras_custom(name = ne,) {
self$noe <- layer_gausise(stddev = 0.5)
selfst <- ?layelstm(
units = nrecent,
input_se = c(n_times, n_features),
return_seces = TRUE
)
self$bm1 <- layer_bation()
self$l2 <- ?lstm(
uni = n_le,
return_= FALSE
)
self$bato<- layer_batcn()
latent <- 10L
features <- 1
hidden <- 32
正則器,F(xiàn)NN損失,沒有變化。
lossnn <- function(x) {
# 改變這些參數(shù)就相當于
# 改變正則器的強度,所以我們保持這些參數(shù)固定(這些值
#對應于Kennel等人1992年使用的原始值)。)
rtol <- 10
atol <- 2
k_frac <- 0.01
k <- max(1, floor(k_frac * batch_size))
##距離矩陣計算的矢量版本
tri_mask <-
tf$linalg$band_part(
tf$ones(
shape
dtype
),
num_lower = -1L,
num_upper = 0L
)
# 潛在的x batch_size x 1
x_squared <-
tf$reduce_sum(batch_masked * batch_masked,
axis = 2L,
keepdims = TRUE)
#(latent, batch_size, batch_size)
all_dists <- pdist_vector
# 避免在有零的情況下出現(xiàn)奇異現(xiàn)象
#(latent, batch_size, batch_size)
all_dists <-
tf$clip_by_value(all_dists, 1e-14, tf$reduce_max(all_dists))
# L2正則化
activations_batch_averaged <-
sqrt(ce_mean(tf$square(x), axis = 0L))
loss <-reduce_sum(multiply(reg_weights, acti_batch_averaged))
損失
訓練也沒有變化,只是現(xiàn)在除了損失之外,我們還不斷地輸出潛變量的變異。這是因為在FNN-LSTM中,我們必須為FNN的損失部分選擇一個適當?shù)臋嘀?。一個 "適當?shù)臋嘀?"是指在前n個變量之后方差急劇下降,n被認為與吸引子維度相對應。這些方差是這樣的。

如果我們把方差作為重要性的一個指標,前兩個變量顯然比其他變量更重要。例如,相關維度被估計為位于2.05左右(Grassberger和Procaccia 1983)。
因此,在這里我們按照常規(guī)訓練。
code <- encoder(batch[[1]] )
l_mse <- mse_loss(batch[[2]], prediction)
l_fnn <- loss_false_nn(code)
loss<- l_mse + fnn_weight * l_fnn
decoder_gradients, decoder$trainable_variables
tf$print("損失: ", train_loss$result()
tf$print("MSE: ", train_mse$result()
tf$print("FNN損失。", train_fnn$result())
# 學習率可能也需要調整
optimizer <- optimizer_adam(lr = 1-3)
我們將用什么作為比較的基線?
VANILLA LSTM
這里是vanilla LSTM,堆疊兩個層,每個層的大小也是32。每個數(shù)據(jù)集都單獨選擇了丟棄Dropout?和遞歸丟棄Dropout?,學習率也是如此。
lstm( dropout = 0.2, recurrent_dropout = 0.2)
數(shù)據(jù)準備
對于所有的實驗,數(shù)據(jù)是以同樣的方式準備的。
這里是第一個數(shù)據(jù)集--間歇泉的數(shù)據(jù)準備代碼--所有其他的數(shù)據(jù)集都以同樣的方式處理。
# 標準化
geyser <- scale(geyser)
# 每個數(shù)據(jù)集的情況不同
n_timesteps <- 60
batch_size <- 32
# 轉化為RNN所需的[batch_size, timesteps, features]格式
purrr::map(seq_along(x),
function(i) {
start <- i
end <- i + n_time - 1
out <- x[start:end]
出
})
) %>%
na.omit()
}
# 分成輸入和目標
x_train <- train[, 1:n_time , ,]
y_train <- train[, (n_time + 1):(2*n_time ), , ]
# 創(chuàng)建 tfdatasets
slices(list(x_train, y_train)) %>%
shuffle(nrow(x_train)) %>%
現(xiàn)在我們準備看看在我們的四個數(shù)據(jù)集上如何進行預測。
實驗
間歇泉數(shù)據(jù)集
從事時間序列分析工作的人可能聽說過Old Faithful,這是一個間歇泉,自2004年以來,每隔44分鐘至2小時就會持續(xù)噴發(fā)。
就像我們上面說的,geyser.csv是這些測量結果的一個子集,包括前10000個數(shù)據(jù)點。為了給LSTM選擇一個適當?shù)臅r間步長,我們以不同的分辨率檢查這個系列。

圖1:Geyer數(shù)據(jù)集。頂部:前1000個觀測值。底部:放大前200個。
看起來行為是周期性的,周期約為40-50;因此,60個時間步長似乎是個不錯的嘗試。
在訓練了FNN-LSTM和vanilla LSTM 200次后,我們首先檢查了測試集上潛變量的方差。這次運行對應的fnn_multiplier的值是0.7。
coded %>% summarise_all(var)

前兩個變量和其他變量之間的重要性有所下降;V1和V2的方差也有一個數(shù)量級的差異。
現(xiàn)在,比較兩個模型的預測誤差是很有意思。
以下是用于計算兩個模型的每時間段預測誤差的代碼。同樣的代碼將用于所有其他數(shù)據(jù)集。
mse_fnn <- get_mse(te_batch, prediion_fnn)
mse_lstm <- get_mse(tesbatch, prediion_lstm)
ggplot(mses, aes(step, mse, color = type)) +
geom_point() +
theme_classic() +
theme(legend.position = "none")
而這里是實際的比較??梢钥吹紽NN-LSTM的預測誤差在初始時間段明顯較低,首先是最開始的預測,從這張圖上看,我們發(fā)現(xiàn)它是相當不錯的!

圖2:FNN-LSTM和vanilla堆疊LSTM得到的每時間段預測誤差,綠色:LSTM,藍色:FNN-LSTM。
有趣的是,我們看到FNN-LSTM的預測誤差在第一次預測和第二次預測之間 "跳躍",然后在第二次預測和隨后的預測之間 "跳躍",讓人想起潛在代碼的變量重要性的類似跳躍。在前10個時間步驟之后,vanilla LSTM已經(jīng)趕上了FNN-LSTM,我們不會僅僅根據(jù)一次運行的輸出來解釋損失的發(fā)展。
相反,讓我們檢查一下實際的預測結果。我們從測試集中隨機挑選序列,并要求FNN-LSTM和vanilla LSTM進行預測。其他數(shù)據(jù)集也將遵循同樣的程序。
bind_rows(given, lstm, fnn)
ggplot(comp_preds_df, aes(num, .data, color = type)) +
geom_line() +
這里有16個隨機抽取的測試集的預測結果?;臼聦嶏@示為粉紅色;藍色預測來自FNN-LSTM,綠色預測來自vanilla LSTM。

圖3:FNN-LSTM(藍色)和vanilla LSTM(天藍色)對測試集中隨機選擇的序列進行的60步提前預測。粉紅色:基礎事實數(shù)據(jù)。
我們從誤差檢查中所期望的結果是真實的。FNN-LSTM對一個給定序列的即時連續(xù)性產(chǎn)生了明顯更好的預測。
電力數(shù)據(jù)集
這是一個關于電力消耗的數(shù)據(jù)集,聚集了321個不同的家庭和15分鐘的時間間隔。
數(shù)據(jù)對應的是2012年至2014年期間321個家庭的平均耗電量,單位為15分鐘內消耗的千瓦數(shù)。
在這里,我們看到一個非常有規(guī)律的模式。

圖4:電力數(shù)據(jù)集。頂部:前2000個觀測值。底部。放大500個觀測值。
發(fā)現(xiàn)這樣有規(guī)律的模式,我們立即嘗試預測更多的時間步數(shù)(120)。
對于fnn_multiplier為0.5,潛變量方差看起來是這樣的。

我們肯定看到在第一個變量之后已經(jīng)有了急劇的下降。
兩種架構上的預測誤差如何比較?

圖5:FNN-LSTM和vanilla堆疊LSTM得到的每時間段預測誤差。天藍色:LSTM,藍色:FNN-LSTM。
在這里,F(xiàn)NN-LSTM在很長的時間段內表現(xiàn)得更好,但同樣,這種差異在即時預測中是最明顯的。對實際預測的檢查能否證實這一觀點?

圖6:FNN-LSTM(藍色)和vanilla LSTM(天藍色)對測試集中隨機選擇的序列的60步超前預測。粉紅色:基礎事實。
FNNN-LSTM的預測在所有時間尺度上都表現(xiàn)不錯。
?
現(xiàn)在我們已經(jīng)看到了簡單和可預測的情況,讓我們來看看其他情況。
心電圖數(shù)據(jù)集
對應的是兩個不同病人的心電圖測量結果。?

圖7:心電圖數(shù)據(jù)集。頂部:前1000個觀測值。底部:放大前400個觀測值。
看起來并不像預期的那樣有規(guī)律。第一次實驗表明,兩個架構都無法處理大量的時間段。在每一次嘗試中,F(xiàn)NN-LSTM在最開始的時間步數(shù)上表現(xiàn)更好。
n_timesteps=12的情況也是如此,這是最后一次嘗試(120、60和30之后)。在fnn_multiplier為1的情況下,所獲得的潛在方差為:

第一個變量和所有其他變量之間存在差距;但V1也沒有解釋多少方差。
除了第一次預測,vanilla?LSTM這次顯示了較低的預測誤差;但是,我們必須補充一點,在試驗其他時間步長設置時,并沒有持續(xù)觀察到這一點。

圖8:FNN-LSTM和vanilla堆疊LSTM得到的每個時間段的預測誤差。綠色:LSTM。藍色:FNN-LSTM。
從實際預測來看,這兩種架構在持久性預測充分的情況下表現(xiàn)最好--事實上,即使在不充分的情況下,它們也會產(chǎn)生一個預測。

圖9:FNN-LSTM(藍色)和vanilla LSTM(綠色)對測試集中隨機選擇的序列的60步超前預測。粉紅色:基礎事實。
在這個數(shù)據(jù)集上,我們當然希望探索其他能夠更好地捕捉數(shù)據(jù)中的高低頻率的架構,比如混合模型。但是--如果我們選擇可以做一步到位的滾動預測,我們會選擇FNN-LSTM。
小鼠數(shù)據(jù)集
"小鼠",這是從小鼠丘腦中記錄的尖峰率。
小鼠丘腦中一個神經(jīng)元的尖峰率時間序列。

圖10:小鼠數(shù)據(jù)集。頂部:前2000個觀察值。底部:放大前500個觀測值。
很明顯,這個數(shù)據(jù)集將是很難預測的。
像往常一樣,我們檢查潛在的代碼變異(fnn_multiplier被設置為0.4)。

同樣,我們沒有看到第一個變量解釋了很多方差。不過,有趣的是,當檢查預測誤差時,我們得到的情況與我們在第一個噴泉數(shù)據(jù)集上得到的情況非常相似。

圖11:FNN-LSTM和vanilla堆疊LSTM得到的每時間段預測誤差。天藍色:LSTM。藍色:FNN-LSTM。
因此,在這里,潛在代碼似乎絕對是有幫助的, 隨著我們試圖預測的時間步數(shù) "增加",預測性能不斷下降--或者反過來說,短時預測應該是相當好的!我們可以看到:在一個小時內,我們的預測結果是:
讓我們來看看。

圖12:FNN-LSTM(藍色)和vanilla LSTM(天藍色)對測試集中隨機選擇的序列進行的60步超前預測。粉紅色:基礎事實。
事實上,在這個數(shù)據(jù)集上,兩個架構之間的行為差異是驚人的。vanilla?LSTM在數(shù)據(jù)的平均值附近產(chǎn)生 "平坦 "的曲線,而FNN-LSTM在收斂到平均值之前接近實際值。選擇FNN-LSTM--如果我們要從這兩者中選擇一個--對這個數(shù)據(jù)集來說是一個明顯的決定。
討論
在整個文本中,我們一直強調實用性--如何使用這種技術來改善預測?但是,看了上述結果,我們想到了一些有趣的問題。我們已經(jīng)猜測,潛在代碼中高變量的數(shù)量是否與我們能合理預測未來的程度有關。然而,更耐人尋味的是,數(shù)據(jù)集本身的特點如何影響FNN的效率。
這些特征可能是:
數(shù)據(jù)集的非線性程度如何?(換句話說,如某種形式的測試算法所示,它與數(shù)據(jù)生成機制是線性機制的假設有多不兼容?)
該系統(tǒng)在多大程度上對初始條件有敏感依賴?
它的(估計的)維度是什么,例如,在相關維度方面?

最受歡迎的見解
1.r語言用神經(jīng)網(wǎng)絡改進nelson-siegel模型擬合收益率曲線分析
2.r語言實現(xiàn)擬合神經(jīng)網(wǎng)絡預測和結果可視化
3.python用遺傳算法-神經(jīng)網(wǎng)絡-模糊邏輯控制算法對樂透分析
4.用于nlp的python:使用keras的多標簽文本lstm神經(jīng)網(wǎng)絡分類
5.用r語言實現(xiàn)神經(jīng)網(wǎng)絡預測股票實例
6.R語言基于Keras的小數(shù)據(jù)集深度學習圖像分類
7.用于NLP的seq2seq模型實例用Keras實現(xiàn)神經(jīng)機器翻譯
8.python中基于網(wǎng)格搜索算法優(yōu)化的深度學習模型分析糖
9.matlab使用貝葉斯優(yōu)化的深度學習