拓端tecdat|R語言Keras用RNN、雙向RNNs遞歸神經(jīng)網(wǎng)絡、LSTM分析預測溫度時間序列、 IM
原文鏈接:http://tecdat.cn/?p=23616?
原文出處:拓端數(shù)據(jù)部落公眾號
在這篇文章中,我們將回顧三種提高循環(huán)神經(jīng)網(wǎng)絡的性能和泛化能力的高級方法。我們將在一個溫度預測問題上演示這三個概念,我們使用來自安裝在建筑物屋頂?shù)膫鞲衅鞯臄?shù)據(jù)點的時間序列。
概述
安裝在建筑物屋頂?shù)膫鞲衅鞯臄?shù)據(jù)點的時間序列,如溫度、氣壓和濕度,你用這些數(shù)據(jù)點來預測最后一個數(shù)據(jù)點之后24小時的溫度。這是一個相當具有挑戰(zhàn)性的問題,它體現(xiàn)了在處理時間序列時遇到的許多常見困難。
我們將介紹以下方法。
遞歸剔除--這是一種特定的、內(nèi)置的方式,使用剔除來對抗遞歸層中的過度擬合。
堆疊遞歸層--這增加了網(wǎng)絡的表示能力(以較高的計算負荷為代價)。
雙向遞歸層--這些層以不同的方式向遞歸網(wǎng)絡呈現(xiàn)相同的信息,提高了準確性并緩解了遺忘問題。
溫度預測的問題
到目前為止,我們所涉及的序列數(shù)據(jù)只有文本數(shù)據(jù),如IMDB數(shù)據(jù)集和路透社數(shù)據(jù)集。但是,序列數(shù)據(jù)在許多問題中都能找到,而不僅僅是語言處理。在本節(jié)的所有例子中,你將分析一個天氣時間序列數(shù)據(jù)集,該數(shù)據(jù)集來自生物地球化學研究所的氣象站記錄。
在這個數(shù)據(jù)集中,14個不同的量(如氣溫、大氣壓力、濕度、風向等)每10分鐘被記錄一次,歷時數(shù)年。原始數(shù)據(jù)可以追溯到2003年,但這個例子僅限于2009-2016年的數(shù)據(jù)。這個數(shù)據(jù)集是學習處理數(shù)字時間序列的完美選擇。你將用它來建立一個模型,把最近的一些數(shù)據(jù)(幾天的數(shù)據(jù)點)作為輸入,預測未來24小時的空氣溫度。
下載并解壓數(shù)據(jù)如下。
unzip(
"~/Downloads/climate.csv.zip",
)
我們來看看這些數(shù)據(jù)。
glimpse(data)

這里是溫度(攝氏度)隨時間變化的曲線圖。在這個圖上,你可以清楚地看到溫度的年度周期性。
plot(data, ?geom_line)

下面是前10天的溫度數(shù)據(jù)圖(見圖6.15)。因為數(shù)據(jù)是每10分鐘記錄一次,所以每天得到144個數(shù)據(jù)點。
plot(data[,], line()

在這個圖上,你可以看到每天的周期性,特別是在過去的4天里很明顯。還要注意的是,這10天的時間來自寒冷的冬季。
如果你根據(jù)過去幾個月的數(shù)據(jù)來預測下個月的平均溫度,問題就很容易了,因為數(shù)據(jù)具有可靠的年尺度的周期性。看一下過去的數(shù)據(jù)?
準備數(shù)據(jù)
問題的確切表述如下:給定的數(shù)據(jù)最遠可追溯到回溯時間段(一個時間段是10分鐘),并且每步時間段取樣,你將使用以下參數(shù)值。
lookback = 1440
?— 觀察結(jié)果將回到10天前。steps = 6
?— 觀察結(jié)果將以每小時一個數(shù)據(jù)點的速度進行采樣。delay = 144
?—目標是未來的24小時。
準備工作。
將數(shù)據(jù)預處理成神經(jīng)網(wǎng)絡可以攝入的格式。這很容易:數(shù)據(jù)已經(jīng)是數(shù)值化的,所以你不需要做任何矢量化。但是,數(shù)據(jù)中的每個時間序列都在不同的量綱上(例如,溫度通常在-20和+30之間,但大氣壓力,以mbar為單位,大約是1000)。你將獨立地對每個時間序列進行歸一化處理,使它們都在一個類似的量綱上取小值。
編寫一個生成器函數(shù),獲取當前的浮點數(shù)據(jù)數(shù)組,并產(chǎn)生最近的數(shù)據(jù)批,以及未來的目標溫度。因為數(shù)據(jù)集中的樣本是高度冗余的(樣本N和樣本N+1將有大部分共同的時間步長),明確分配每個樣本是不合理的。取而代之的是,你將使用原始數(shù)據(jù)生成樣本。
理解生成器函數(shù)
生成器函數(shù)是一種特殊類型的函數(shù),你反復調(diào)用它來獲取一連串的值。通常情況下,生成器需要保持內(nèi)部狀態(tài),所以它們通常是通過調(diào)用另一個又一個返回生成器函數(shù)的函數(shù)來構(gòu)造的(返回生成器的函數(shù)的環(huán)境隨后被用來跟蹤狀態(tài))。
例如,下面產(chǎn)生一個無限的數(shù)字序列。
generator <- function(start) {
value <- start - 1
value <<- value + 1
value
}
gen <- generator(10)
[1] 10
gen()
[1] 11
生成器的當前狀態(tài)是定義在函數(shù)之外的值變量。注意,超級賦值(<<->)是用來從函數(shù)內(nèi)部更新這個狀態(tài)的。
生成器函數(shù)可以通過返回值NULL來表示完成。然而,傳遞給Keras訓練方法(例如生成器函數(shù)應該總是無限地返回值(對生成器函數(shù)的調(diào)用次數(shù)由epochs和psych_per_epoch參數(shù)控制)。
首先,你要把我們之前讀到的R數(shù)據(jù)幀轉(zhuǎn)換為浮點值矩陣。
data <- data.matrix(data[,-1])
然后,你將對數(shù)據(jù)進行預處理,減去每個時間序列的平均值并除以標準差。你將使用前20萬個時間段作為訓練數(shù)據(jù),所以只對這部分數(shù)據(jù)計算均值和標準差進行歸一化。
train_data <- data[1:200000,]
data <- scale(data, center = mean, scale = std)
下面是你要使用的數(shù)據(jù)生成器的代碼。它產(chǎn)生一個列表(samples, targets),其中samples是一批輸入數(shù)據(jù),target是相應的目標溫度陣列。它需要以下參數(shù)。
data - 原始的浮點數(shù)據(jù)數(shù)組,你對其進行了標準化處理
lookback
?— 輸入的數(shù)據(jù)應該回到多少個時間段。delay
?—目標應該在未來多少個時間段.min_index
?和?max_index
?—數(shù)據(jù)數(shù)組中的索引,用來限定從哪個時間段提取。這對于保留一部分數(shù)據(jù)用于驗證,另一部分用于測試很有用.shuffle
?— 是否對樣本進行隨機打亂或按時間順序抽取.batch_size
?—每批樣本的數(shù)量.step
?— 你對數(shù)據(jù)進行采樣的周期,以時間為單位。你將設置為6,以便每小時繪制一個數(shù)據(jù)點.
i變量包含跟蹤下一個數(shù)據(jù)窗口返回的狀態(tài),所以它使用超級賦值進行更新(例如,i <<- i + length(rows))。
現(xiàn)在,讓我們使用生成器函數(shù)來實例化三個生成器:一個用于訓練,一個用于驗證,還有一個用于測試。每個生成器將查看原始數(shù)據(jù)的不同時間段:訓練生成器查看前20萬個時間段,驗證生成器查看隨后的10萬個時間段,而測試生成器查看剩余的時間段。
# 為了遍歷整個驗證集,要從val_gen中抽取多少步
val_steps <- (300000 - 200001 - lookback) / batch_size
# 為了遍歷整個測試集,要從test_gen中抽取多少步
test_steps <- (nrow(data) - 300001 - lookback) / batch_size
常識性、非機器學習的基準模型
在你開始使用黑盒深度學習模型來解決溫度預測問題之前,讓我們嘗試一個簡單的、常識性的方法。這將作為一種理智的檢查,它將建立一個基準模型,以證明更先進的機器學習模型的有用性。當你在處理一個新的問題時,這種常識性的基線可能是有用的,因為目前還沒有已知的解決方案。一個典型的例子是不平衡的分類任務,其中一些類別比其他類別要常見得多。如果你的數(shù)據(jù)集包含90%的A類實例和10%的B類實例,那么分類任務的一個常識性方法就是在遇到新樣本時總是預測 "A"。這樣的分類器總體上有90%的準確度,因此任何基于學習的方法都應該超過這個90%的分數(shù),以證明其有用性。
在這種情況下,可以安全地假設溫度時間序列是連續(xù)的(明天的溫度可能與今天的溫度接近),以及具有每日周期性的。因此,一個常識性的方法是始終預測24小時后的溫度將與現(xiàn)在的溫度相等。讓我們使用平均絕對誤差(MAE)指標來評估這種方法。
mean(abs(preds - targets))
下面是評估循環(huán)。
for (step in 1:val_steps) {
c(samples, targets) %<-% val_gen()
preds <- samples[,dim(samples)[[2]],2]
mae <- mean(abs(preds - targets))
batch_maes <- c(batch_maes, mae)
}
這得出的MAE為0.29。因為溫度數(shù)據(jù)已經(jīng)被歸一化,以0為中心,標準差為1。它轉(zhuǎn)化為平均絕對誤差為0.29 x temperature_std攝氏度:2.57?C。
這是一個相當大的平均絕對誤差?,F(xiàn)在利用深度學習來做得更好。
基本的機器學習方法
在嘗試機器學習方法之前,建立一個常識性的基線是很有用的,同樣,在研究復雜和計算昂貴的模型(如RNN)之前,嘗試簡單、便宜的機器學習模型(如小型、密集連接的網(wǎng)絡)也是很有用的。這是確保你在這個問題上投入的任何進一步的復雜性都是合法的,并帶來真正的好處的最好方法。
下面的列表顯示了一個全連接模型,它從扁平化的數(shù)據(jù)開始,然后通過兩個密集層運行。注意最后一個密集層上沒有激活函數(shù),這對于回歸問題來說是典型的。你使用MAE作為損失函數(shù)。因為你用完全相同的數(shù)據(jù)和完全相同的指標來評估你的常識性方法,所以結(jié)果將是直接可比的。
model %>% compile(
optimizer = optimizer_rmsprop(),
loss = "mae"
)
驗證和訓練的損失曲線。

一些驗證損失接近于無學習基線,但并不可靠。這就說明了首先要有這個基準的好處:事實證明,要超越它并不容易。你的常識包含了很多機器學習模型無法獲得的寶貴信息。
你可能會想,如果存在一個簡單的、表現(xiàn)良好的模型來從數(shù)據(jù)到目標(常識基準),為什么你正在訓練的模型沒有發(fā)現(xiàn)它并在此基礎上進行改進?因為這個簡單的解決方案并不是你的訓練設置所要尋找的。你在其中尋找解決方案的模型空間--也就是你的假設空間--是所有可能的兩層網(wǎng)絡的空間,其配置由你定義。這些網(wǎng)絡已經(jīng)相當復雜了。當你用一個復雜的模型空間尋找解決方案時,簡單的、表現(xiàn)良好的基線可能是不可學習的,即使它在技術上是假設空間的一部分。這是機器學習的一個相當重要的限制:除非學習算法被硬編碼為尋找一種特定的簡單模型,否則參數(shù)學習有時可能無法找到一個簡單問題的簡單解決方案。
第一個遞歸基準模型
第一個全連接方法做得不好,但這并不意味著機器學習不適用于這個問題。之前的方法首先對時間序列進行了扁平化處理,將時間的概念從輸入數(shù)據(jù)中移除。相反,讓我們把數(shù)據(jù)看成是:一個序列,其中因果關系和順序很重要。你將嘗試一個循環(huán)序列處理模型--它應該是最適合這種序列數(shù)據(jù)的,正是因為它利用了數(shù)據(jù)點的時間順序,與第一種方法不同。
你將使用Chung等人在2014年開發(fā)的GRU層,而不是上一節(jié)中介紹的LSTM層。門控遞歸單元(GRU)層的工作原理與LSTM相同,但它們有些精簡,因此運行成本更低(盡管它們可能沒有LSTM那么多的表示能力)。在機器學習中,這種計算能力和表現(xiàn)能力之間的權(quán)衡隨處可見。
layer_gru(units = 32, input_shape = list(NULL, dim(data)[[-1]])) %>%
layer_dense(units = 1)
結(jié)果繪制如下。好多了, 你可以大大超越常識性的基準模型,證明了機器學習的價值,以及在這種類型的任務上,遞歸網(wǎng)絡比序列平坦的密集網(wǎng)絡更有優(yōu)勢。

交互顯示訓練過程中的模型損失:?


新的驗證MAE為~0.265(在你開始明顯過擬合之前),轉(zhuǎn)化為去標準化后的平均絕對誤差為2.35?C。與最初的2.57℃的誤差相比,這是一個進步,但你可能仍有一點改進的余地。
使用遞歸丟棄dropout來對抗過擬合
從訓練和驗證曲線中可以看出,該模型正在過度擬合:訓練和驗證損失在幾個 epochs之后開始出現(xiàn)明顯的分歧。你已經(jīng)熟悉了對抗這種現(xiàn)象的經(jīng)典技術:dropout,它隨機地將一個層的輸入單元清零,以打破該層所接觸的訓練數(shù)據(jù)中的偶然相關性。
Yarin Gal使用Keras進行研究,并幫助將這一機制直接構(gòu)建到Keras的遞歸層中。Keras中的每個遞歸層都有兩個與dropout相關的參數(shù):dropout,一個指定該層輸入單元的dropout率的浮點數(shù),以及recurrent_dropout,指定遞歸單元的dropout率。讓我們在layer_gru中加入dropout和recurrent dropout,看看這樣做對過擬合有什么影響。因為用dropout進行正則化的網(wǎng)絡總是需要更長的時間來完全收斂,所以你將訓練網(wǎng)絡兩倍的epochs。
?layer_gru(dropout = 0.2))
下面的圖顯示了結(jié)果。 你在前20個 epochs中不再過度擬合。但是,盡管你有更穩(wěn)定的評估分數(shù),你的最佳分數(shù)并沒有比以前低很多。

堆疊遞歸層
因為你不再過度擬合,但似乎遇到了性能瓶頸,你應該考慮增加網(wǎng)絡的容量。回顧一下通用機器學習工作流程的描述:一般來說,增加網(wǎng)絡的容量是個好主意,直到過擬合成為主要障礙(假設你已經(jīng)采取了基本措施來減輕過擬合,比如使用dropout)。
增加網(wǎng)絡容量通常是通過增加層中的單元數(shù)量或添加更多的層來實現(xiàn)的。遞歸層堆疊是建立更強大的遞歸網(wǎng)絡的經(jīng)典方法:例如,目前為谷歌翻譯算法提供動力的是七個大型LSTM層的堆疊。
為了在Keras中把遞歸層堆疊起來,所有的中間層都應該返回它們的完整輸出序列(一個三維張量),而不是它們在最后一個時間步的輸出。這可以通過指定return_sequences = TRUE來實現(xiàn)。
?
layer_gru(
return_sequences = TRUE,
input_shape = list(NULL, dim(data)[[-1]])) %>%
下圖顯示了結(jié)果。你可以看到,添加的層確實改善了一些結(jié)果,盡管并不明顯。你可以得出兩個結(jié)論。
因為你的過擬合情況仍然不是很嚴重,所以你可以安全地增加層的大小以尋求驗證損失的改善。不過,這有一個不可忽視的計算成本。
增加一個層并沒有明顯的幫助,所以在這一點上,你可能會看到增加網(wǎng)絡容量的回報越來越少。

使用雙向的RNNs
本節(jié)介紹的最后一項技術被稱為雙向RNNs。雙向RNN是一種常見的RNN變體,在某些任務上可以提供比普通RNN更大的性能。它經(jīng)常被用于自然語言處理--你可以把它稱為用于自然語言處理的深度學習的瑞士軍刀。
值得注意的是,RNN是順序依賴的,或者說是時間依賴的:它們按順序處理其輸入序列的時間段顛倒時間段可以完全改變RNN從序列中提取的表示。這正是它們在順序有意義的問題上表現(xiàn)良好的原因,如溫度預測問題。雙向RNN利用了RNN的順序敏感性:它包括使用兩個常規(guī)的RNN,比如你已經(jīng)熟悉的layer_gru和layer_lstm,每個都從一個方向(按時間順序和按反時間順序)處理輸入序列,然后合并它們的表示。通過雙向處理一個序列,雙向RNN可以識別到可能被單向RNN忽略的模式。
值得注意的是,本節(jié)中的RNN層按時間順序處理了序列(較早的時間段在前),這可能是一個隨意的決定。如果RNN按反時序處理輸入序列,例如(較新的時間段在前),它們的表現(xiàn)是否足夠好?讓我們在實踐中嘗試一下,看看會發(fā)生什么。訓練你在本節(jié)第一個實驗中使用的相同的單層GRU網(wǎng)絡,你會得到如下的結(jié)果。

反序GRU的表現(xiàn)甚至低于常識性基線,表明在這種情況下,時間處理對你的方法的成功很重要。這是很有道理的:底層的GRU層通常會在記憶最近的過去方面比記憶遙遠的過去方面做得更好,而對于這個問題來說,較近的天氣數(shù)據(jù)點自然比較早的數(shù)據(jù)點更具預測性(這就是常識性基線相當強大的原因)。因此,按時間順序排列的圖層的表現(xiàn)必然會優(yōu)于倒序的版本。重要的是,對于許多其他問題,包括自然語言,這并不正確:憑直覺,一個詞在理解一個句子中的重要性通常并不取決于它在句子中的位置。
讓我們在LSTM IMDB例子上嘗試同樣的技巧。
# 考慮作為特征的詞的數(shù)量
max_features <- 10000
# 剔除超過這個字數(shù)的文本
maxlen <- 500
# 反轉(zhuǎn)序列
x_train <- lapply(x_train, rev)
x_test <- lapply(x_test, rev)
layer_lstm(units = 32)
history <- model %>% fit(
x_train, y_train,
epochs = 10,
batch_size = 128,
)
你得到的性能幾乎與按時間順序排列的LSTM相同。值得注意的是,在這樣的文本數(shù)據(jù)集上,倒序處理與按時間順序處理一樣好,這證實了這樣的假設:盡管詞序在理解語言方面確實很重要,但你使用哪種順序并不關鍵。重要的是,在顛倒的序列上訓練的RNN將與在原始序列上訓練的RNN學習不同的表征,就像在現(xiàn)實世界中,如果時間倒流,你會有不同的心理模型--如果你的生活中,你在第一天死亡,在最后一天出生。
在機器學習中,不同但有用的表征總是值得利用的,而且它們的差異越大越好:它們提供了一個新的角度來觀察你的數(shù)據(jù),識別到了其他方法所遺漏的數(shù)據(jù)方面,因此它們可以幫助提高任務的性能。
雙向RNN利用這個想法來提高按時間順序排列的RNN的性能。它從兩個方面觀察其輸入序列,獲得潛在的更豐富的表征,并識別到可能被單獨的時間順序版本所遺漏的模式。

要在Keras中實例化一個雙向RNN,它需要一個遞歸層實例作為參數(shù)。創(chuàng)建這個遞歸層的第二個獨立實例,并使用一個實例來處理按時間順序排列的輸入序列,另一個實例來處理按相反順序排列的輸入序列。我們在IMDB情感分析任務上試試。
bidirectional(
lstm(units = 32)
)
它的表現(xiàn)比之前嘗試的普通LSTM略好,取得了超過89%的驗證準確性。它似乎也會更快地過擬合,這并不奇怪,因為雙向?qū)拥膮?shù)是按時間順序排列的LSTM的兩倍。通過一些正則化,雙向方法很可能在這個任務中表現(xiàn)出色。
現(xiàn)在讓我們在溫度上嘗試同樣的方法
bidirectional(
layer_gru(units = 32),
) %>%
layer_dense(units = 1)
和普通的layer_gru的表現(xiàn)差不多。這很容易理解:所有的預測能力必須來自于網(wǎng)絡中按時間順序排列的那一半,因為已知反時間順序排列的那一半在這個任務上表現(xiàn)嚴重不足。
進一步
為了提高溫度預測問題的性能,你還可以嘗試許多其他事情。
調(diào)整堆疊設置中每個遞歸層的單元數(shù)量。目前的選擇基本上是任意的,因此可能是次優(yōu)的。
調(diào)整RMSprop優(yōu)化器使用的學習率。
嘗試使用layer_lstm而不是layer_gru。
嘗試在遞歸層之上使用更大的密集連接回歸器:也就是說,一個更大的密集層,甚至是密集層的堆疊。
最終在測試集上運行表現(xiàn)最好的模型(就驗證MAE而言)。否則,你會開發(fā)出過度擬合的架構(gòu)。
深度學習是一門藝術,而不是一門科學。我們可以提供指導方針,但最終,每個問題都是獨一無二的;你必須根據(jù)經(jīng)驗來評估不同的策略。目前還沒有任何理論能夠事先準確地告訴你應該怎樣做才能最有效地解決問題。你必須進行迭代。
總結(jié)
在處理一個新問題時,最好首先為你選擇的指標建立常識性的基準。如果你沒有一個基準,你就無法判斷你是否取得了真正的進展。
先嘗試簡單的模型,以證明合理性。有時,一個簡單的模型會成為你最好的選擇。
當你的數(shù)據(jù)的時間順序很重要時,遞歸網(wǎng)絡是一個很好的選擇。
為了在遞歸網(wǎng)絡中使用dropout,你應該使用時間恒定的dropout mask和遞歸dropout mask。
堆疊的RNN比單一的RNN層提供更多的表示能力。雖然它們在復雜的問題(如機器翻譯)上提供了明顯較好的效果,但它們可能在較簡單的問題表現(xiàn)一般。
雙向的RNNs,從兩個方面看一個序列,在自然語言處理問題上很有用。但它們在序列數(shù)據(jù)上的表現(xiàn)并不突出,因為在這些數(shù)據(jù)中,近期的信息量要比序列的初始數(shù)據(jù)大得多。
注意:股市和機器學習
一些讀者一定會想把我們在這里介紹的技術,在預測股票市場上的證券(或貨幣匯率等)的未來價格問題上進行嘗試。市場與自然現(xiàn)象(如天氣模式)有著非常不同的統(tǒng)計特征,當涉及到股市時,過去的表現(xiàn)并不能很好地預測未來的回報--看后視鏡是一種不好的駕駛方式。另一方面,機器學習適用于那些過去能很好地預測未來的數(shù)據(jù)集。

最受歡迎的見解
1.r語言用神經(jīng)網(wǎng)絡改進nelson-siegel模型擬合收益率曲線分析
2.r語言實現(xiàn)擬合神經(jīng)網(wǎng)絡預測和結(jié)果可視化
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)化的深度學習