用Python玩轉時序資料
時間序列是日常生活中最常見的資料型別之一。股票價格、銷售資訊、氣候資料、能源使用,甚至個人身高體重都是可以用來定期收集的資料樣本。幾乎每個資料科學家在工作中都會遇到時間序列,能夠有效地處理這些資料是資料科學領域之中的一項非常重要的技能。
本文簡要介紹瞭如何從零開始使用Python中的時間序列。這包括對時間序列的簡單定義,以及對利用pandas訪問倫敦市居民智慧電錶所獲取資料的處理。可以點選此處獲取本文中所使用的資料。還提供了一些我認為有用的程式碼。
讓我們從基礎開始,時間序列的定義是這樣的:
時間序列是按時間的順序進行索引、排列或者繪製的資料點的集合。最常見的定義是,一個時間序列是在連續的相同間隔的時間點上取得的序列,因此它是一個離散時間資料的序列。
時間序列資料是圍繞相對確定的時間戳而組織的。因此,與隨機樣本相比,可能包含我們將要嘗試提取的一些相關資訊。
載入和控制時間序列
資料集
讓我們使用一些關於能源消耗計費的資料作為例子,以kWh(每半小時)為單位, 在2011年11月至2014年2月期間,對參與英國電力網路領導的低碳倫敦專案的倫敦居民樣本資料進行分析。我們可以從繪製一些圖表開始,最好了解一下樣本的結構和範圍,這也將允許我們尋找最終需要糾正的缺失值。
對於本文的其餘部分,我們只關注DateTime和kWh兩列。
重取樣
讓我們從較簡單的重取樣技術開始。重取樣涉及到更改時間序列觀測的頻率。特徵工程可能是你對重新取樣時間序列資料感興趣的一個原因。實際上,它可以用來為監督學習模型提供額外的架構或者是對學習問題的領會角度。
·data.resample()方法將用於對DataFrame的kWh列資料重新取樣;
·“W”表示我們要按每週重新取樣;
·sum()方法用於表示在此時間段計算kWh列的總和;
我們可以對每日的資料也這麼做處理,並且可以使用groupby和mean函式進行按小時處理:
為了進一步進行重新取樣,pandas有許多內建的選項,你甚至還可以定義自己的方法。下面兩個表分別顯示了時間週期選項及其縮寫別名和一些可能用於重取樣的常用方法。
其它探索
這裡還有一些你可以用於處理資料而進行的其它探索:
用Prophet建模
Facebook Prophet於2017年釋出的,可用於Python,而R.Prophet是設計用於分析在不同時間間隔上顯示模式的日觀測時間序列。Prophet對於資料丟失情況和趨勢的變化具有很強的魯棒性,並且通常能夠很好地處理異常值。它還具有高階的功能,可以模擬假日在時間序列上產生的影響並執行自定義的變更點,但我將堅持使用基本規則來啟動和執行模型。我認為Prophet可能是生產快速預測結果的一個好的選擇,因為它有直觀的引數,並且可以由有良好領域知識背景的但缺乏預測模型的技術技能的人來進行調整。有關Prophet的更多資訊,大家可以點選這裡查閱官方文件。
在使用Prophet之前,我們將資料裡的列重新命名為正確的格式。Date列必須稱為“ds”和要預測值的列為“y”。我們在下面的示例中使用了每日彙總的資料。
然後我們匯入Prophet,建立一個模型並與資料相匹配。在Prophet中,changepoint_prior_scale引數用於控制趨勢對變化的敏感度,越高的值會更敏感,越低的值則敏感度越低。在試驗了一系列值之後,我將這個引數設定為0.10,而不是預設值0.05。
為了進行預測,我們需要建立一個稱為未來資料框(future dataframe)的東西。我們需要指定要預測的未來時間段的數量(在我們的例子中是兩個月)和預測頻率(每天)。然後我們用之前建立的Prophet模型和未來資料框進行預測。
非常簡單!未來資料框包含了未來兩個月內的預估居民使用電量。我們可以用一個圖表來進行視覺化預測展示:
圖中的黑點代表了實際值,藍線則代表了預測值,而淺藍色陰影區域代表不確定性。
如下圖所示,不確定性區域隨著我們在之後的進一步變化而擴大,因為初始的不確定性隨著時間的推移而擴散和增多。
Prophet還可以允許我們輕鬆地對整體趨勢和元件模式進行視覺化展示:
每年的模式很有趣,因為它看起來表明了居民的電量使用在秋季和冬季會增加,而在春季和夏季則會減少。直觀地說,這正是我們期望要看到的。從每週的趨勢來看,週日的使用量似乎比一週中其它時間都要多。最後,總體的趨勢表明,使用量增長了一年,然後才緩慢地下降。需要進行進一步的調查來解釋這一趨勢。在下一篇文章中,我們將嘗試找出是否與天氣有關。
LSTM(Long Short-Term Memory,長短期記憶網路)預測
LSTM迴圈神經網路具有學習長序列觀測值的前景。部落格文章《瞭解LSTM網路》,在以一種易於理解的方式來解釋底層複雜性方面做的非常出色。以下是一個描述LSTM內部單元體系結構的示意圖:
來源:Understanding LSTM Networks
LSTM似乎非常適合於對時間序列的預測。讓我們再次使用一下每日彙總的資料。
LSTM對輸入資料的大小很敏感,特別是當使用Sigmoid或Tanh這兩個啟用函式的時候。通常,將資料重新調整到[0,1]或[-1,1]這個範圍是一個不錯的實踐,也稱為規範化。我們可以使用scikit-learn庫中的MinMaxScaler預處理類來輕鬆地規範化資料集。
現在我們可以將已排好序的資料集拆分為訓練資料集和測試資料集。下面的程式碼計算出了分割點的索引,並將資料拆分為多個訓練資料集,其中80%的觀測值可用於訓練模型,剩下的20%用於測試模型。
我們可以定義一個函式來建立一個新的資料集,並使用這個函式來準備用於建模的訓練資料集和測試資料集。
LSTM網路要求輸入的資料以如下的形式提供特定的陣列結構:[樣本、時間間隔、特徵]。
資料目前都規範成了[樣本,特徵]的形式,我們正在為每個樣本設計兩個時間間隔。可以將準備好的分別用於訓練和測試的輸入資料轉換為所期望的結構,如下所示:
就是這樣,現在已經準備好為示例設計和設定LSTM網路了。
從下面的損失圖可以看出,該模型在訓練資料集和測試資料集上都具有可比較的表現。
在下圖中,我們看到LSTM在擬合測試資料集方面做得非常好。
聚類(Clustering)
最後,我們還可以使用示例的資料進行聚類。執行聚類有很多不同的方式,但一種方式是按結構層次來形成聚類。你可以通過兩種方式形成一個層次結構:從頂部開始來拆分,或從底部開始來合併。我決定先看看後者。
讓我們從資料開始,只需簡單地匯入原始資料,併為某年中的某日和某日中的某一小時新增兩列。
Linkage和Dendrograms
linkage函式根據物件的相似性,將距離資訊和物件對分組放入聚類中。這些新形成的聚類隨後相互連線,以建立更大的聚類。這個過程將會進行迭代,直到在原始資料集中的所有物件在層次樹中都連線在了一起。
對資料進行聚類:
完成了!!!這難道不是很簡單嗎?
當然很簡單了,但是上面程式碼中的“ward”在那裡意味著什麼呢?這實際上是如何執行的?正如scipy linkage文件上告訴我們的那樣,“ward”是可以用來計算新形成的聚類之間距離的一個方法。關鍵字“ward”讓linkage函式使用Ward方差最小化演算法。其它常見的linkage方法,如single、complete、average,還有不同的距離度量標準,如euclidean、manhattan、hamming、cosine,如果你想玩玩的話也可以使用一下。
現在讓我們來看看這個稱為dendogram的分層聚類圖。dendogram圖是聚類的層次圖,其中那些條形的長度表示到下一個聚類中心的距離。
如果這是你第一次看到dendrogram圖,那看起來挺複雜的,但是別擔心,讓我們把它分解來看:
·在x軸上可以看到一些標籤,如果你沒有指定任何其它內容,那麼這些標籤就是X上樣本的索引;
·在y軸上,你可以看到那些距離長度(在我們的例子中是ward方法);
·水平線是聚類的合併;
·那些垂線告訴你哪些聚類或者標籤是合併的一部分,從而形成了新的聚類;
·水平線的高度是用來表示需要被“橋接”以形成新聚類的距離;
即使有解釋說明,之前的dendogram圖看起來仍然不明顯。我們可以減少一點,以便能更好地檢視資料。
建議查詢聚類文件以便能瞭解更多內容,並嘗試使用不同的引數。
本文由北郵@愛可可-愛生活 老師推薦,阿里云云棲社群組織翻譯。
文章原標題《Playing with time series data in python》
譯者:Mags,審校:袁虎。
文章為簡譯,更為詳細的內容,請檢視原文