楠木軒

為什麼LSTM看起來那麼複雜,以及如何避免時序數據處理差異和混亂

由 宮繼梅 發佈於 科技

LSTM(long short term memory,長短期記憶網絡)是預測時間序列最常用的神經網絡模型之一。但是這種神經網絡模型相當複雜,需要特定的結構、數據前期處理等操作。

當在網上搜尋要學習的代碼時,很難將另一個程序員的代碼合併到當前開展的項目中。對於LSTM尤其如此,導致這些問題的關鍵在於:

· 數據準備的順序

· 數據存儲的結構

簡單地説,由於兩個關鍵步驟有多種方法可以獲得相同的結果,因此每個程序員選擇的路徑可能有所不同。

在這篇文章中,將分析為什麼我們必須下定決心使用一組特定的範例,特別是在為冗長的LSTM編程時,以便更好地調試和共享。

LSTM 數據準備階段

本質上,當我們為模型準備時間序列數據時,需要執行以下關鍵步驟:

· 按時間分割數據集

· 將數據集轉換為有監督學習問題

這兩個步驟的執行順序沒有明確規定。因此一部分程序員先分割數據集,然後將其轉化為監督學習問題。而其他程序員則顛倒兩者順序。

先分割數據集,然後轉換為有監督學習問題

先轉換為有監督學習問題,然後分割數據集

處理結果

對比而言,雖然處理的結果相同,但是先分割數據集的方式所需代碼更少。而部分程序員在編程過程中,會使用第二種方式,這就導致了社區中交流問題和代碼時產生一定的差異和混亂。所以本文推薦優先分割數據集的方式。

數據結構

在我們決定了為LSTM準備數據的正確順序之後,我們需要選擇使用哪種合適的數據結構。數據結構大致可以分為以下三種:

· Pandas DataFrame

· Numpy Arrays

· Lists

Pandas DataFrame

Pandas 是一個可靠的且便於操作的數據處理庫。而我們在編寫人工智能算法時,總是需要在進程的任何一步檢查數據以便於調試。在 Pandas 庫中可以很方便地做到這一點:

df.head()

Pandas 示例:谷歌股票

通過 Pandas 可以打印出數據情況,以檢查在程序運行過程中是否出現錯誤。

Pandas 示例:一個模擬有監督學習問題的pandas dataframe

相比較而言, List 則具有多維度、不易於理解的缺點,對於調試工作不太友好。

Numpy Arrays

所有數據集或多或少都會轉換為 NumPy Arrays 以進行編輯或縮放操作。例如,如果我們希望在0和1之間縮放數據集,可以使用名為MinMaxScaler的工具:

from sklearn.preprocessing import MinMaxScaler#df is pandas DataFrame#conversion to numpy arraydf = df.Valuesscaler = MinMaxScaler(feature_range=(0, 1))scaled_values = scaler.fit_transform(df)

將整個數據集作為NumPy Array 的問題在於,無法詳細查看其中的內容。不能夠以列名稱的方式查看數據(將數據集轉換為有監督的學習問題時,這一點非常重要)。並且對於算法的調試工作不夠友好。

幸運的是,可以輕鬆地從NumPy Arrays 切換回 DataFrame。

Lists

將數據集的內容存儲在多維列表中是十分低效的。以 Kaggle 上發表的一段代碼為例:

List 示例:一個四因素的時間序列數據存儲

不難發現,通過 Lists 難以直接定位數據並查看數據,並且不能夠通過列名稱的方式組織數據。

總結

規範化這個問題並不侷限於LSTM,但是在 LSTM 編程過程中十分普遍。缺乏規範化導致在實際編程中,不能夠直接一個接一個地調用程序或函數。

現在的情況下,代碼看起來可能很簡單而且很快,但是搜索錯誤、調試代碼是個很大的問題。在函數聲明過程中,輸入數據的名稱可能會更改,因此當想要檢查隱藏在代碼中的變量的值或輸出時,往往不能簡單地調用原始的數據名稱,必須使用它所涉及到的所有代碼才能提取該數據的真實值。

這就是本文推薦使用統一的數據框架的原因。通過統一使用 Pandas Dataframe,可以輕鬆地檢查每個函數的輸出,更好地進行算法調試工作。

deephub 小組經驗

基本上所有的所有的編程語言的數字下標都是從0開始的,這就使得我們在處理序列數據的時候需要改掉以 1為起始的現實中的習慣。並且在python處理分片的時候使用的是左閉右開(絕大部分,並不是全部)的原則,這也是導致了我們對時序數組的操作需要特別的注意。

實際案例:LSTM需要通過前30天的數據,預測當天的數據,處理輸入數據的數組下標如何寫,有興趣的小夥伴可以手動試試。