<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 九、從頭開始訓練 RNN **循環神經網絡**(**RNN**)是為建模順序數據而構建的一組神經網絡。 在最后幾章中,我們研究了使用卷積層從圖像中學習特征。 當我們想從所有相關的值中學習特征時,循環層同樣有用: `x[t]`, `x[t-1]`,`x[t-2]`,`x[t-3]`。 在本章中,我們將討論如何將 RNN 用于時間序列問題,這無疑是涉及按時間或時間順序排列的一系列數據點的問題。 我們將在本章介紹以下主題: * 循環神經網絡介紹 * 時間序列問題 * 將 LSTM 用于時間序列預測 # 循環神經網絡介紹 如果定義不清楚,我們來看一個例子:一個股票行情指示器,我們可以在其中觀察股票價格隨時間的變化,例如以下屏幕快照中的 Alphabet Inc.,這是時間序列的一個示例: ![](https://img.kancloud.cn/ea/40/ea408914519f04423922f2f5b4fe6288_623x446.png) 在下一章中,我們將討論使用循環神經網絡為語言建模,這是另一種類型的序列,即單詞序列。 由于您正在閱讀本書,因此無疑已經對語言順序有了一些直覺。 如果您不熟悉時間序列,您可能想知道是否可以使用普通的多層感知器來解決時間序列問題。 您當然可以做到; 但是,實際上,使用循環網絡幾乎總是可以得到更好的結果。 也就是說,循環神經網絡在序列建模方面還有其他兩個優點: * 他們可以比普通的 MLP 更輕松地學習很長的序列 * 他們可以處理不同長度的序列 當然,這給我們提出了一個重要的問題... # 是什么使神經元循環? 循環神經網絡具有循環,可以使信息從一個預測持續到下一個預測。 這意味著每個神經元的輸出取決于網絡的當前輸入和先前的輸出,如下圖所示: ![](https://img.kancloud.cn/b8/ad/b8ad8eb00935c88b231a531617ee4590_960x540.jpg) 如果我們將這個圖跨時間展平,它將看起來更像下圖。 網絡通知本身的想法是“循環”一詞的來源,盡管作為 CS 專業,我始終將其視為循環神經網絡。 ![](https://img.kancloud.cn/df/65/df654f481858dffd8fa60e4b725efdc6_960x540.jpg) 在上圖中,我們可以看到神經元`A`接受輸入`x[t0]`并輸出`h[t0]`在時間步 0 處。然后在時間步 1,神經元使用輸入`x[t1]`以及來自其上一個時間步的信號來輸出`h[t1]`。 現在在時間步驟 2,它認為它是輸入`x[t2]`以及上一個時間步驟的信號,該信號可能仍包含時間步驟 0 的信息。我們繼續這種方式,直到到達序列中的最后一個時間步,網絡逐步增加其內存。 標準 RNN 使用權重矩陣將前一個時間步的信號與當前時間步的輸入和隱藏權重矩陣的乘積混合。 在通過非線性函數(通常是雙曲正切函數)進行饋送之前,將所有這些函數組合在一起。 對于每個時間步驟,它看起來像: ![](https://img.kancloud.cn/e2/34/e2345f62040d33a54144dac6fd081dd6_1800x200.png) ![](https://img.kancloud.cn/ef/ae/efae4df609f3a0d25e92247e536c0fe3_1110x210.png) ![](https://img.kancloud.cn/d5/b8/d5b813de8ae394fbfe941a7d5fd815a3_1030x190.png) 此處`t`是前一個時間步輸出和當前時間步輸入的線性組合,均由權重矩陣`W`和`U`進行參數化。 一旦計算出`t`,它就具有非線性函數,最常見的是雙曲正切`h[t]`。 最后,神經元的輸出`o[t]`將`h[t]`與權重矩陣結合在一起,`V`和`a`偏置,`c`偏置。 當您查看此結構時,請嘗試想象一下一種情況,在該情況下,您很早就需要一些非常重要的信息。 隨著序列的延長,重要的早期信息被遺忘的可能性就更高,因為新信號會輕易地壓倒舊信息。 從數學上講,單元的梯度將消失或爆炸。 這是標準 RNN 的主要缺點。 在實踐中,傳統的 RNN 難以按順序學習真正的長期交互作用。 他們很健忘! 接下來,讓我們看一下可以克服此限制的長短期內存網絡。 # 長期短期記憶網絡 每當需要循環網絡時,**長期短期記憶網絡**(**LSTM**)都能很好地工作。 您可能已經猜到了,LSTM 在學習長期交互方面很出色。 實際上,這就是他們的設計意圖。 LSTM 既可以積累先前時間步驟中的信息,又可以選擇何時忘記一些不相關的信息,而選擇一些新的更相關的信息。 例如,考慮序列`In highschool I took Spanish. When I went to France I spoke French.`。 如果我們正在訓練一個網絡來預測`France`一詞,那么記住`French`并有選擇地忘記`Spanish`是非常重要的,因為上下文已經發生了變化。 當序列的上下文發生變化時,LSTM 可以有選擇地忘記某些事情。 為了完成這種選擇性的長期記憶,LSTM 實現了一個“忘記門”,該門使 LSTM 成為了稱為門控神經網絡的神經網絡家族的成員。 該遺忘門允許 LSTM 有選擇地學習何時應從其長期存儲器中丟棄信息。 LSTM 的另一個關鍵特性是內部自循環,使設備可以長期積累信息。 除了我們在 RNN 中看到的循環之外,還使用了該循環,可以將其視為時間步之間的外部循環。 相對于我們已經看到的其他神經元,LSTM 非常復雜,如下圖所示: ![](https://img.kancloud.cn/91/be/91bef5f8af99916c7cd5e66fda359598_500x222.png) 每個 LSTM 單元展開時,都有一個時間段`t`的輸入,稱為`x[t]`,一個輸出,稱為`o[t]`以及從上一個時間步`C[t-1]`到下一個`C[t]`進行存儲的存儲器總線`C`。 除這些輸入外,該單元還包含多個門。 我們已經提到的第一個是忘記門,在圖中標記為`F[t]`: ![](https://img.kancloud.cn/8d/75/8d7524a7291591af2e82120bebbad2e6_2180x220.png) 該門的輸出(將在 0 和 1 之間)逐點乘以`C[t-1]`。 這允許門調節從`C[t-1]`到`C[t]`的信息流。 下一個門,即輸入門`i[t]`與函數候選`C[t]`結合使用。 候選`C[t]`學習可以添加到內存狀態的向量。 輸入門了解總線`C`中的哪些值得到更新。 下式說明`i[t]`和候選`C[t]`: ![](https://img.kancloud.cn/55/2d/552d3f460c1cc71dc1b52e7241024a27_2070x210.png) ![](https://img.kancloud.cn/09/37/093773f8c76df321d53aa45369203f9b_3320x210.png) 我們取`i[t]`和候選`C[t]`的點積,決定添加到總線`C`的對象, 使用`F[t]`決定要忘記什么之后,如以下公式所示: ![](https://img.kancloud.cn/61/8a/618a6c33ff04071e1fb213f9f8c3eadc_2870x200.png) 最后,我們將決定獲取輸出的內容。 輸出主要來自內存總線`C`; 但是,它被另一個稱為輸出門的門過濾。 以下公式說明了輸出: ![](https://img.kancloud.cn/b5/90/b590bc53fec50d4d4faeb1a7ba3bd84b_2690x210.png) ![](https://img.kancloud.cn/90/53/905313ce26e43e53a1d3246683dbfd8d_2070x210.png) 盡管很復雜,但 LSTM 在各種問題上都非常有效。 盡管存在 LSTM 的多個變體,但在大多數任務上仍基本認為該基本實現是最新技術。 這些任務之一是預測時間序列中的下一個值,這就是我們將在本章中使用的 LSTM。 但是,在我們開始將 LSTM 應用于時間序列之前,必須對時間序列分析和更傳統的方法進行簡短的復習。 # 時間上的反向傳播 訓練 RNN 要求**反向傳播**的實現略有不同,即在整個時間(**BPTT**)中稱為**反向傳播**。 與正常反向傳播一樣,BPTT 的目標是使用整體網絡誤差,通過梯度來調整每個神經元/單元對它們對整體誤差的貢獻的權重。 總體目標是相同的。 但是,當使用 BPTT 時,我們對誤差的定義會稍有變化。 正如我們剛剛看到的,可以通過幾個時間步長展開神經元循環。 我們關心所有這些時間步長的預測質量,而不僅僅是終端時間步長,因為 RNN 的目標是正確預測序列,因為邏輯單元誤差定義為所有時間步長上展開的誤差之和。 使用 BPTT 時,我們需要總結所有時間步驟中的誤差。 然后,在計算完該總體誤差后,我們將通過每個時間步的梯度來調整單元的權重。 這迫使我們明確定義將展開 LSTM 的程度。 在下面的示例中,您將看到這一點,當我們創建一組特定的時間步長時,將為每個觀察值進行訓練。 您選擇反向傳播的步驟數當然是超參數。 如果您需要從序列中很遠的地方學習一些東西,顯然您必須在序列中包括很多滯后。 您需要能夠捕獲相關期間。 另一方面,捕獲太多的時間步長也不可取。 該網絡將變得非常難以訓練,因為隨著時間的流逝,梯度會變得非常小。 這是前面幾章中描述的梯度消失問題的另一個實例。 如您想象的那樣,您可能想知道是否選擇太大的時間步會使程序崩潰。 如果梯度驅動得太小以至于變為 NaN,那么我們將無法完成更新操作。 解決此問題的一種常見且簡便的方法是在某些上下閾值之間固定梯度,我們將其稱為梯度裁剪。 默認情況下,所有 **Keras** 優化器均已啟用梯度剪切。 如果您的梯度被剪裁,則在該時間范圍內網絡可能不會學到很多東西,但是至少您的程序不會崩潰。 如果 BPTT 看起來確實令人困惑,請想象一下 LSTM 處于展開狀態,其中每個時間步都有一個單元。 對于該網絡結構,該算法實際上與標準反向傳播幾乎相同,不同之處在于所有展開的層均共享權重。 # 時間序列問題回顧 時間序列問題是涉及按時間順序放置的一系列數據點的問題。 我們通常將這些數據點表示為一組: ![](https://img.kancloud.cn/60/0a/600a67e30d5fcad80a94199d8d62a940_2550x220.png) 通常,我們在時間序列分析中的目標是預測。 但是,使用時間序列當然還可以執行許多其他有趣的事情,而這不在本書的討論范圍之內。 預測實際上只是回歸的一種特殊形式,我們的目標是根據給定的先前點`x[t-1], ..., x[t-n]`來預測某個點`x[t]`或點`x[t], x[t+1], x[t+2], ..., x[t+n]`。 當時間序列自動關聯時,我們可以執行此操作,這意味著數據點與其自身關聯一個或多個時間上的點(稱為滯后)。 自相關性越強,預測就越容易。 在許多書中,時間序列問題用`y`表示,而不是用`x`表示,以暗示我們通常關心預測給定自身的變量 y 的想法。 # 庫存和流量 在計量經濟學時間序列中,數量通常被定義為**庫存**或**流量**。 庫存度量是指特定時間點的數量。 例如,2008 年 12 月 31 日的 SP500 的值是庫存測量值。 流量測量是一段時間間隔內的速率。 美國股票市場從 2009 年到 2010 年的增長率是一種流量度量。 最經常進行預測時,我們會關注預測流量。 如果我們將預測想象為一種特定的回歸,那么我們偏愛流量的第一個也是最明顯的原因是,流量估計更有可能是插值而不是外推,而且插值幾乎總是更安全。 此外,大多數時間序列模型都具有平穩性的假設。 固定時間序列是其統計屬性(均值,方差和自相關)隨時間恒定的序列。 如果我們使用一定數量的庫存測量,則會發現大多數現實世界中的問題遠非靜止不動。 使用 LSTM 進行時間序列分析時,雖然沒有假設(讀取規則)需要平穩性,但根據實際經驗,我發現對相對固定的數據進行訓練的 LSTM 更加健壯。 使用 LSTM 進行時間序列預測時,幾乎在所有情況下,一階差分就足夠了。 將庫存數量轉換為流量數量非常簡單。 如果您具有`n`個點,則可以創建具有一階差分的`n-1`流量測量值,其中,對于每個值`t'[n]`,我們通過從`t[n]`中減去`t[n-1]`來進行計算,從而得出跨時間間隔的兩次測量的變化率,如以下公式所示: ![](https://img.kancloud.cn/da/40/da406d79f57055e32a8eb1f836e5a005_1190x190.png) 例如,如果我們在三月份擁有價值 80 美元的股票,而在四月份突然價值 100 美元,則該股票的流率將為 20 美元。 一階微分不能保證平穩的時間序列。 我們可能還需要刪除季節或趨勢。 趨勢消除是專業預測員日常生活的重要組成部分。 如果我們使用傳統的統計模型進行預測,則需要做更多的工作。 雖然我們沒有涵蓋這些內容的頁面,但我們可能還需要執行二階差分,季節性趨勢下降或更多操作。 **增強 Dickey-Fuller**(**ADF**)測試是一種統計測試,通常用于確定我們的時間序列是否實際上是靜止的。 如果您想知道時間序列是否穩定,[可以使用增強的 Dickey-Fuller 檢驗來檢查](https://en.wikipedia.org/wiki/Augmented_Dickey%E2%80%93Fuller_test)。 但是,對于 LSTM,一階微分通常可能就足夠了。 只需了解網絡最肯定會學習您數據集中剩余的季節和周期。 # ARIMA 和 ARIMAX 預測 值得一提的是**自回歸綜合移動平均值**(**ARIMA**)模型,因為它們傳統上用于時間序列預測。 雖然我顯然是深度神經網絡的忠實擁護者(事實上,我寫過關于它們的書),但我建議從 ARIMA 開始并逐步進行深度學習。 在許多情況下,ARIMA 的表現將優于 LSTM。 當數據稀疏時尤其如此。 從可能可行的最簡單模型開始。 有時這將是一個深層的神經網絡,但通常情況會更簡單一些,例如線性回歸或 ARIMA 模型。 該模型的復雜性應通過其提供的提升來證明,通常越簡單越好。 盡管整本書中多次重申,但在時間序列預測中,這一說法比其他任何話題都更為真實。 ARIMA 模型是三個部分的組合。 AR,即自回歸部分,是根據自身的自相關性對序列進行建模的部分。 MA 部分嘗試對時間序列中的本地突發事件或沖擊建模。 I 部分涵蓋了差異,我們剛剛介紹了差異。 ARIMA 模型通常采用三個超參數`p`,`d`和`q`,分別對應于建模的自回歸滯后的數量,微分度和模型的移動平均部分的順序。 ARIMA 模型在 R 的`auto.arima()`和預測包中實現得很好,這可能是使用 R 語言的唯一很好的理由之一。 ARIMAX 模型允許在時間序列模型中包含一個或多個協變量。 您問這種情況下的協變量是多少? 這是一個附加時間序列,也與因變量相關,可用于進一步改善預測表現。 交易員的常見做法是嘗試通過使用另一種商品的一個或多個滯后以及我們預測的商品的自回歸部分來預測某些商品的價值。 在這種情況下,ARIMAX 模型將很有用。 如果您有許多具有復雜的高階交互作用的協變量,那么您已進入 LSTM 的最佳預測時間序列。 在本書的開頭,我們討論了多層感知器如何對輸入變量之間的復雜相互作用進行建模,從而為我們提供了自動特征工程,該工程提供了線性或邏輯回歸的提升。 此屬性可以繼續使用 LSTM 進行具有許多輸入變量的時間序列預測。 如果您想全面了解 ARIMA,ARIMAX 和時間序列預測,建議從 [Rob J. Hyndman 的博客 Hyndsight](https://robjhyndman.com/hyndsight/) 開始。 # 將 LSTM 用于時間序列預測 在本章中,我們將通過使用 2017 年 1 月至 5 月的比特幣分鐘價格來預測 2017 年 6 月美元的比特幣分鐘價格。我知道這聽起來確實很賺錢,但是在您購買那條船之前,我建議您通讀本章的最后; 說起來容易做起來難,甚至建模起來也容易。 即使我們能夠使用這種模型在美元和比特幣之間創造套利潛力(由于效率低下而導致兩個市場之間的價格差異),但由于存在延遲,圍繞比特幣制定交易策略可能極其復雜。 在完成比特幣交易中。 在撰寫本文時,比特幣交易的平均交易時間超過一個小時! 任何交易策略都應考慮這種“非流動性”。 和以前一樣,本書的 Git 存儲庫中的`Chapter09`下提供了本章的代碼。 文件`data/bitcoin.csv`包含數年的比特幣價格。 基于以下假設,即前幾年的市場行為與 2017 年加密貨幣流行后的行為無關,我們將僅使用幾個月的價格信息作為模型。 # 數據準備 對于此示例,我們將不使用驗證集,而是將測試集用作驗證集。 在處理此類預測問題時,驗證成為一項具有挑戰性的工作,因為訓練數據從測試數據中獲取的越多,執行效果越差的可能性就越大。 另一方面,這并不能為過度安裝提供太多保護。 為了使事情簡單,在這里我們將只使用一個測試集,并希望最好。 在繼續之前,讓我們看一下將要進行的數據準備的總體流程。 為了使用此數據集訓練 LSTM,我們需要: 1. 加載數據集并將周期時間轉換為熊貓日期時間。 2. 通過對日期范圍進行切片來創建訓練和測試集。 3. 差分我們的數據集。 4. 將差異縮放到更接近我們的激活函數的程度。 我們將使用 -1 到 1,因為我們將使用`tanh`作為激活 5. 創建一個訓練集,其中每個目標`x[t]`都有一系列與之相關的滯后`x[t-1], ..., x[t-n]`。 在此訓練集中,您可以將`x[t]`視為我們的典型因變量`y`。 滯后序列`x[t-1], ..., x[t-n]`可以看作是典型的`X`訓練矩陣。 我將在接下來的主題中介紹每個步驟,并在進行過程中顯示相關的代碼。 # 加載數據集 從磁盤加載數據集是一項相當簡單的工作。 如前所述,我們將按日期對數據進行切片。 為此,我們需要將數據集中的 Unix 周期時間轉換為可分割的日期。 可以通過`pandas to_datetime()`方法輕松實現,如以下代碼所示: ```py def read_data(): df = pd.read_csv("./data/bitcoin.csv") df["Time"] = pd.to_datetime(df.Timestamp, unit='s') df.index = df.Time df = df.drop(["Time", "Timestamp"], axis=1) return df ``` # 按日期切片和測試 現在,我們的數據幀已通過`datetime`時間戳編制索引,因此我們可以構造基于日期的切片函數。 為此,我們將定義一個布爾掩碼,并使用該掩碼選擇現有的數據框。 雖然我們可以肯定地將其構造成一行,但我認為以這種方式閱讀起來要容易一些,如以下代碼所示: ```py def select_dates(df, start, end): mask = (df.index > start) & (df.index <= end) return df[mask] ``` 現在我們可以使用日期來獲取數據框的某些部分,我們可以使用以下代碼通過幾次調用這些函數輕松地創建訓練和測試數據框: ```py df = read_data() df_train = select_dates(df, start="2017-01-01", end="2017-05-31") df_test = select_dates(df, start="2017-06-01", end="2017-06-30") ``` 在使用這些數據集之前,我們需要對它們進行區別,如下所示。 # 差分時間序列 Pandas 數據框最初是為對時間序列數據進行操作而創建的,幸運的是,由于對數據集進行差分是時間序列中的一種常見操作,因此很容易內置。但是,根據良好的編碼習慣,我們將圍繞我們的一階差分運算包裝一個函數。 請注意,我們將用 0 填充無法進行一階差分的所有空間。以下代碼說明了此技術: ```py def diff_data(df): df_diffed = df.diff() df_diffed.fillna(0, inplace=True) return df_diffed ``` 通過差分數據集,我們將這個問題(庫存問題)轉移到了流量問題。 在比特幣投放中,流量可能會很大,因為比特幣的價值會在數分鐘之間發生很大變化。 我們將通過縮放數據集來解決此問題。 # 縮放時間序列 在此示例中,我們將使用`MinMaxScaler`將每個差異數據點縮放為最小值為 -1 且最大值為 1 的比例。這將使我們的數據與雙曲線正切函數(`tanh` ),這是我們針對該問題的激活函數。 我們將使用以下代碼縮放系列: ```py def scale_data(df, scaler=None): scaled_df = pd.DataFrame(index=df.index) if not scaler: scaler = MinMaxScaler(feature_range=(-1,1)) scaled_df["Price"] = scaler.fit_transform(df.Close.values.reshape(-1,1)) return scaler, scaled_df ``` 請注意,此函數可以選擇使用已經適合的縮放器。 這使我們能夠將訓練定標器應用到我們的測試儀上。 # 創建滯后的訓練集 對于每個訓練示例,給定一系列延遲`x[t-1], ..., x[t-n]`,我們希望訓練網絡以預測值`x[t]`。 理想的延遲數是一個超參數,因此需要進行一些實驗。 如前所述,以這種方式構造輸入是 BPTT 算法的要求。 我們將使用以下代碼來訓練數據集: ```py def lag_dataframe(data, lags=1): df = pd.DataFrame(data) columns = [df.shift(i) for i in range(lags, 0, -1)] columns.append(df) df = pd.concat(columns, axis=1) df.fillna(0, inplace=True) cols = df.columns.tolist() for i, col in enumerate(cols): if i == 0: cols[i] = "x" else: cols[i] = "x-" + str(i) cols[-1] = "y" df.columns = cols return df ``` 例如,如果我們用`lags = 3`調用`lag_dataframe`,我們期望數據集返回`x[t-1], x[t-2], x[t-3]`。 我發現很難理解這樣的滯后代碼,因此,如果您也這樣做,您并不孤單。 我建議運行它并建立一些熟悉的操作。 在選擇數量滯后時,在將模型部署到生產環境時,您可能還需要考慮要等待多少個滯后才能做出預測。 # 輸入形狀 Keras 期望 LSTM 的輸入是一個三維張量,看起來像: ![](https://img.kancloud.cn/f0/11/f0110de938c6f53561bf2ccb4fbeb29b_5340x220.png) 第一個維度顯然是我們擁有的觀測值的數量,并且我們可以預期。 第二維對應于使用`lag_dataframe`函數時我們選擇的滯后次數。 這是我們要給 Keras 做出預測的時間步數。 第三維是該時間步中存在的特征數。 在我們的示例中,我們將使用一個,因為每個時間步只有一個特征,即該時間步的比特幣價格。 在繼續閱讀之前,請仔細考慮此處定義三維矩陣給您的威力。 我們絕對可以將數百個其他時間序列作為預測該時間序列的特征。 通過這樣做以及使用 LSTM,我們可以免費獲得這些特征之間的特征工程。 正是這種功能使 LSTM 在金融領域變得如此令人興奮。 對于當前的問題,我們將需要將二維矩陣轉換為三維矩陣。 為此,我們將使用 NumPy 的便捷`reshape`函數,如以下代碼所示: ```py X_train = np.reshape(X_train.values, (X_train.shape[0], X_train.shape[1], 1)) X_test = np.reshape(X_test.values, (X_test.shape[0], X_test.shape[1], 1)) ``` # 數據準備 在此示例中,我們做了很多轉換。 在繼續進行訓練之前,我認為最好將兩者結合起來。 如此處所示,我們將使用另一個函數將所有這些步驟聯系在一起: ```py def prep_data(df_train, df_test, lags): df_train = diff_data(df_train) scaler, df_train = scale_data(df_train) df_test = diff_data(df_test) scaler, df_test = scale_data(df_test, scaler) df_train = lag_dataframe(df_train, lags=lags) df_test = lag_dataframe(df_test, lags=lags) X_train = df_train.drop("y", axis=1) y_train = df_train.y X_test = df_test.drop("y", axis=1) y_test = df_test.y X_train = np.reshape(X_train.values, (X_train.shape[0], X_train.shape[1], 1)) X_test = np.reshape(X_test.values, (X_test.shape[0], X_test.shape[1], 1)) return X_train, X_test, y_train, y_test ``` 此函數采用訓練和測試數據幀,并應用差分,縮放和滯后代碼。 然后,將這些數據幀重新調整為我們熟悉的`X`和`y`張量,以進行訓練和測試。 現在,我們可以使用幾行代碼將這些轉換粘合在一起,從而從加載數據到準備進行訓練和測試,它們可以: ```py LAGS=10 df = read_data() df_train = select_dates(df, start="2017-01-01", end="2017-05-31") df_test = select_dates(df, start="2017-06-01", end="2017-06-30") X_train, X_test, y_train, y_test = prep_data(df_train, df_test, lags=LAGS) ``` 這樣,我們就可以開始訓練了。 # 網絡輸出 我們的網絡將輸出一個單一值,該值是在前一分鐘內給定分鐘內比特流價格的縮放流量或預期變化。 我們可以使用單個神經元獲得此輸出。 該神經元可以在 Keras 密集層中實現。 它將多個 LSTM 神經元的輸出作為輸入,我們將在下一部分中介紹。 最后,此神經元的激活可以是`tanh`,因為我們已將數據縮放到與雙曲正切函數相同的比例,如下所示: ```py output = Dense(1, activation='tanh', name='output')(lstm2) ``` # 網絡架構 我們的網絡將使用兩個 Keras LSTM 層,每個層具有 100 個 LSTM 單元: ```py inputs = Input(batch_shape=(batch_shape, sequence_length, input_dim), name="input") lstm1 = LSTM(100, activation='tanh', return_sequences=True, stateful=True, name='lstm1')(inputs) lstm2 = LSTM(100, activation='tanh', return_sequences=False, stateful=True, name='lstm2')(lstm1) output = Dense(1, activation='tanh', name='output')(lstm2) ``` 要特別注意`return_sequences`參數。 連接兩個 LSTM 層時,您需要前一個 LSTM 層來輸出序列中每個時間步的預測,以便下一個 LSTM 層的輸入是三維的。 但是,我們的密集層僅需要二維輸出即可預測其執行預測的確切時間步長。 # 有狀態與無狀態 LSTM 在本章的前面,我們討論了 RNN 跨時間步長維護狀態或內存的能力。 使用 Keras 時,可以用兩種方式配置 LSTM,即**有狀態**和**無狀態**。 默認為無狀態配置。 使用無狀態 LSTM 配置時,每批 LSTM 單元存儲器都會重置。 這使得批量大小成為非常重要的考慮因素。 當您正在學習的序列彼此不依賴時,無狀態效果最佳。 下一個單詞的句子級預測可能是何時使用無狀態的一個很好的例子。 有狀態配置會在每個周期重置 LSTM 單元存儲器。 當訓練集中的每個序列取決于其之前的序列時,最常使用此配置。 如果句子級別的預測對于無狀態配置可能是一項好任務,那么文檔級別的預測對于有狀態模型可能是一項好任務。 最終,這種選擇取決于問題,并且可能需要在測試每個選項時進行一些試驗。 對于此示例,我已經測試了每個選項,并選擇使用有狀態模型。 當我們考慮問題的背景時,這可能不足為奇。 # 訓練 盡管此時的情況似乎有很大不同,但是訓練 LSTM 實際上與訓練典型橫截面問題的深度神經網絡沒有什么不同: ```py LAGS=10 df = read_data() df_train = select_dates(df, start="2017-01-01", end="2017-05-31") df_test = select_dates(df, start="2017-06-01", end="2017-06-30") X_train, X_test, y_train, y_test = prep_data(df_train, df_test, lags=LAGS) model = build_network(sequence_length=LAGS) callbacks = create_callbacks("lstm_100_100") model.fit(x=X_train, y=y_train, batch_size=100, epochs=10, callbacks=callbacks) model.save("lstm_model.h5") ``` 在準備好數據之后,我們使用我們已經遍歷的架構實例化一個網絡,然后按預期對其進行擬合。 在這里,我使用的是有狀態的 LSTM。 有狀態 LSTM 的一個實際好處是,與無狀態 LSTM 相比,它們傾向于在更少的時間進行訓練。 如果要將其重構為無狀態 LSTM,則在網絡完成學習之前可能需要 100 個周期,而此處我們僅使用 10 個周期。 # 測量表現 在有狀態的配置中經過 10 個星期之后,我們的損失已經停止改善,并且我們的網絡也受到了良好的訓練,如下圖所示: ![](https://img.kancloud.cn/45/d4/45d468485e91b3f2575a7785e220e9fa_417x354.png) 我們擁有一個合適的網絡,似乎已經學到了一些東西。 現在,我們可以對比特幣的價格流做出某種預測。 如果我們能做好,我們所有人都會非常富有。 在去買那棟豪宅之前,我們可能應該測量一下模型的表現。 財務模型的最終檢驗是這個問題:“您愿意在上面花錢嗎?”很難回答這個問題,因為在時間序列問題中衡量表現可能具有挑戰性。 一種衡量表現的非常簡單的方法是使用均方根誤差來評估`y_test`與`X_test`預測之間的差異。 我們最肯定可以做到這一點,如以下代碼所示: ```py RMSE = 0.0801932157201 ``` 0.08 是一個好分數嗎? 讓我們通過比較我們的預測與 6 月份比特幣流量的實際值,開始對商品的調查。 這樣做可能會使我們對模型的表現有直觀的了解,這是我始終建議的一種做法: ![](https://img.kancloud.cn/6e/19/6e193f68fe4e8d7c67b760bb9f43b201_685x632.png) 我們用綠色表示的預測有很多不足之處。 我們的模型已經學會了預測平均流量,但是在匹配完整信號方面確實做得很差。 甚至有可能我們只是在學習一種趨勢,因為我們所做的努力不那么激烈。 我認為我們可能不得不把那棟豪宅推遲更長的時間,但是我們走了正確的道路。 考慮到我們的預測,即僅給出比特幣的先前價值,該模型就可以解釋盡可能多的比特幣價格。 我們可能在建模時間序列的自回歸部分方面做得相當不錯。 但是,可能有許多不同的外部因素影響比特幣的價格。 美元的價值,其他市場的動向,也許最重要的是,圍繞比特幣的嗡嗡聲或信息流通,都可能在美元的價格中發揮重要作用。 這就是 LSTM 用于時間序列預測的功能真正發揮作用的地方。 通過添加附加的輸入特征,所有這些信息都可以在某種程度上輕松地添加到模型中,希望可以解釋越來越多的整個圖片。 但是,讓我再破一次您的希望。 對表現進行更徹底的調查還將包括考慮模型相對于某些幼稚模型所提供的提升。 此簡單模型的典型選擇可能包括稱為**隨機游走**模型,指數平滑模型的模型,或者可能使用樸素的方法,例如使用上一個時間步長作為當前時間步長的預測。 如下圖所示: ![](https://img.kancloud.cn/ef/f1/eff153fec191200dfdd036399d31f172_685x632.png) 在此圖中,我們將紅色的預測與一個模型進行比較,在模型中,我們僅將前一分鐘用作綠色的下一分鐘的預測。 以藍色表示的實際價格幾乎完美地覆蓋了這個樸素的模型。 我們的 LSTM 預測不如幼稚模型好。 僅使用最后一分鐘的價格來預測當前分鐘的價格會更好。 盡管我堅持認為我們走在正確的道路上,但在那艘船成為我們的船之前,我們還有很長的路要走。 對任何商品建模非常困難。 對于這種類型的問題,使用深度神經網絡是可以肯定的,但是這個問題并不容易。 我加入了這個也許詳盡的解釋,以便如果您決定走這條路,便會明白自己的目標。 就是說,當您使用 LSTM 套利金融市場時,請記住給小費。 # 總結 在本章中,我們討論了使用循環神經網絡來預測序列中的下一個元素。 我們既涵蓋了一般的 RNN,也涵蓋了特定的 LSTM,我們專注于使用 LSTM 預測時間序列。 為了確保我們了解將 LSTM 用于時間序列的好處和挑戰,我們簡要回顧了時間序列分析的一些基礎知識。 我們還花了幾分鐘討論傳統的時間序列模型,包括 ARIMA 和 ARIMAX。 最后,我們介紹了一個具有挑戰性的用例,其中我們使用 LSTM 來預測比特幣的價格。 在下一章中,我們將繼續使用 RNN,現在將重點放在自然語言處理任務上,并介紹嵌入層的概念。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看