使用LSTM深度學習模型進行溫度的時間序列單步和多步預測

2020-12-05 deephub

本文的目的是提供代碼示例,並解釋使用python和TensorFlow建模時間序列數據的思路。

本文展示了如何進行多步預測並在模型中使用多個特徵。

本文的簡單版本是,使用過去48小時的數據和對未來1小時的預測(一步),我獲得了溫度誤差的平均絕對誤差0.48(中值0.34)度。

利用過去168小時的數據並提前24小時進行預測,平均絕對誤差為攝氏溫度1.69度(中值1.27)。

所使用的特徵是過去每小時的溫度數據、每日及每年的循環信號、氣壓及風速。

使用來自https://openweathermap.org/的API獲取數據。這些數據從1990年1月1日到2020.11月30日每小時在維爾紐斯電視塔附近收集一次。維爾紐斯不是一個大城市,電視塔就在城市裡,所以電視塔附近的溫度應該和城市所有地方的溫度非常相似。

這裡和整篇文章的主數據對象被稱為d。它是通過讀取原始數據創建的:

d = pd.read_csv(『data/weather.csv』)# Converting the dt column to datetime object d[『dt』] = [datetime.datetime.utcfromtimestamp(x) for x in d[『dt』]]# Sorting by the date d.sort_values(『dt』, inplace=True)

數據集中共有271008個數據點。

數據似乎是具有明確的周期模式。

上面的圖表顯示,氣溫有一個清晰的晝夜循環——中間溫度在中午左右最高,在午夜左右最低。

這種循環模式在按月份分組的溫度上更為明顯——最熱的月份是6月到8月,最冷的月份是12月到2月。

數據現在的問題是,我們只有date列。如果將其轉換為數值(例如,提取時間戳(以秒為單位))並將其作為建模時的特性添加,那麼循環特性將丟失。因此,我們需要做的第一件事就是設計一些能夠抓住周期性趨勢的特性。

我們想讓機器知道,23點和0點比小時0點和4點更接近。我們知道周期是24小時。我們可以用cos(x)和sin(x)函數。函數中的x是一天中的一個小時。

# Extracting the hour of dayd["hour"] = [x.hour for x in d["dt"]]# Creating the cyclical daily feature d["day_cos"] = [np.cos(x * (2 * np.pi / 24)) for x in d["hour"]]d["day_sin"] = [np.sin(x * (2 * np.pi / 24)) for x in d["hour"]]

得到的dataframe如下:

新創建的特徵捕捉了周期性模式。 可能會出現一個問題,為什麼我們同時使用sin和cos函數?

在上圖中繪製一條水平線並僅分析其中一條曲線,我們將得到例如cos(7.5h)= cos(17.5h)等。 在學習和預測時,這可能會導致一些錯誤,因此為了使每個點都唯一,我們添加了另一個循環函數。 同時使用這兩個功能,可以將所有時間區分開。

為了在一年中的某個時間創建相同的循環邏輯,我們將使用時間戳功能。 python中的時間戳是一個值,用於計算自1970.01.01 0H:0m:0s以來經過了多少秒。 python中的每個date對象都具有timestamp()函數。

# Extracting the timestamp from the datetime object d["timestamp"] = [x.timestamp() for x in d["dt"]]# Seconds in day s = 24 * 60 * 60# Seconds in year year = (365.25) * sd["month_cos"] = [np.cos((x) * (2 * np.pi / year)) for x in d["timestamp"]]d["month_sin"] = [np.sin((x) * (2 * np.pi / year)) for x in d["timestamp"]]

在本節中,我們從datetime列中創建了4個其他功能:daysin,daycos,monthsin和monthcos。

在天氣數據集中,還有兩列:wind_speed和pressure。 風速以米/秒(m / s)為單位,壓力以百帕斯卡(hPa)為單位。

要查看溫度與兩個特徵之間的任何關係,我們可以繪製二維直方圖:

顏色越強烈,兩個分布的某些bin值之間的關係就越大。 例如,當壓力在1010和1020 hPa左右時,溫度往往會更高。

我們還將在建模中使用這兩個功能。

我們使用所有要素工程獲得的數據是:

我們要近似的函數f為:

目標是使用過去的值來預測未來。 數據是時間序列或序列。 對於序列建模,我們將選擇具有LSTM層的遞歸神經網絡的Tensorflow實現。

LSTM網絡的輸入是3D張量:

(樣本,時間步長,功能)

樣本—用於訓練的序列總數。

timesteps-樣本的長度。

功能-使用的功能數量。

建模之前的第一件事是將2D格式的數據轉換為3D數組。 以下功能可以做到這一點:

例如,如果我們假設整個數據是數據的前10行,那麼我們將過去3個小時用作特徵,並希望預測出1步:

def create_X_Y(ts: np.array, lag=1, n_ahead=1, target_index=0) -> tuple:""" A method to create X and Y matrix from a time series array for the training of deep learning models """ # Extracting the number of features that are passed from the array n_features = ts.shape[1] # Creating placeholder lists X, Y = [], [] if len(ts) - lag <= 0: X.append(ts) else: for i in range(len(ts) - lag - n_ahead): Y.append(ts[(i + lag):(i + lag + n_ahead), target_index]) X.append(ts[i:(i + lag)]) X, Y = np.array(X), np.array(Y) # Reshaping the X array to an RNN input shape X = np.reshape(X, (X.shape[0], lag, n_features)) return X, Y

例如,如果我們假設整個數據是數據的前10行,那麼我們將過去3個小時用作特徵,並希望預測出1步:

ts = d[『temp』, 『day_cos』, 『day_sin』, 『month_sin』, 『month_cos』, 『pressure』, 『wind_speed』].head(10).valuesX, Y = create_X_Y(ts, lag=3, n_ahead=1)

如我們所見,X矩陣的形狀是6個樣本,3個時間步長和7個特徵。 換句話說,我們有6個觀測值,每個觀測值都有3行數據和7列。 之所以有6個觀測值,是因為前3個滯後被丟棄並且僅用作X數據,並且我們預測提前1步,因此最後一個觀測值也會丟失。

上圖中顯示了X和Y的第一個值對。

最終模型的超參數列表:

# Number of lags (hours back) to use for modelslag = 48# Steps ahead to forecast n_ahead = 1# Share of obs in testing test_share = 0.1# Epochs for trainingepochs = 20# Batch size batch_size = 512# Learning ratelr = 0.001# Number of neurons in LSTM layern_layer = 10# The features used in the modeling features_final = [『temp』, 『day_cos』, 『day_sin』, 『month_sin』, 『month_cos』, 『pressure』, 『wind_speed』]

模型代碼

class NNMultistepModel():def __init__( self, X, Y, n_outputs, n_lag, n_ft, n_layer, batch, epochs, lr, Xval=None, Yval=None, mask_value=-999.0, min_delta=0.001, patience=5 ): lstm_input = Input(shape=(n_lag, n_ft)) # Series signal lstm_layer = LSTM(n_layer, activation='relu')(lstm_input) x = Dense(n_outputs)(lstm_layer) self.model = Model(inputs=lstm_input, outputs=x) self.batch = batch self.epochs = epochs self.n_layer=n_layer self.lr = lr self.Xval = Xval self.Yval = Yval self.X = X self.Y = Y self.mask_value = mask_value self.min_delta = min_delta self.patience = patience def trainCallback(self): return EarlyStopping(monitor='loss', patience=self.patience, min_delta=self.min_delta) def train(self): # Getting the untrained model empty_model = self.model # Initiating the optimizer optimizer = keras.optimizers.Adam(learning_rate=self.lr) # Compiling the model empty_model.compile(loss=losses.MeanAbsoluteError(), optimizer=optimizer) if (self.Xval is not None) & (self.Yval is not None): history = empty_model.fit( self.X, self.Y, epochs=self.epochs, batch_size=self.batch, validation_data=(self.Xval, self.Yval), shuffle=False, callbacks=[self.trainCallback()] ) else: history = empty_model.fit( self.X, self.Y, epochs=self.epochs, batch_size=self.batch, shuffle=False, callbacks=[self.trainCallback()] ) # Saving to original model attribute in the class self.model = empty_model # Returning the training history return history def predict(self, X): return self.model.predict(X)

創建用於建模之前的最後一步是縮放數據。

# Subseting only the needed columns ts = d[features_final]nrows = ts.shape[0]# Spliting into train and test setstrain = ts[0:int(nrows * (1 — test_share))]test = ts[int(nrows * (1 — test_share)):]# Scaling the data train_mean = train.mean()train_std = train.std()train = (train — train_mean) / train_stdtest = (test — train_mean) / train_std# Creating the final scaled frame ts_s = pd.concat([train, test])# Creating the X and Y for trainingX, Y = create_X_Y(ts_s.values, lag=lag, n_ahead=n_ahead)n_ft = X.shape[2]

現在我們將數據分為訓練和驗證

# Spliting into train and test sets Xtrain, Ytrain = X[0:int(X.shape[0] * (1 — test_share))], Y[0:int(X.shape[0] * (1 — test_share))]Xval, Yval = X[int(X.shape[0] * (1 — test_share)):], Y[int(X.shape[0] * (1 — test_share)):]

數據的最終形狀:

Shape of training data: (243863, 48, 7)Shape of the target data: (243863, 1)Shape of validation data: (27096, 48, 7)Shape of the validation target data: (27096, 1)

剩下的就是使用模型類創建對象,訓練模型並檢查驗證集中的結果。

# Initiating the model objectmodel = NNMultistepModel(X=Xtrain, Y=Ytrain, n_outputs=n_ahead, n_lag=lag, n_ft=n_ft, n_layer=n_layer, batch=batch_size, epochs=epochs, lr=lr, Xval=Xval, Yval=Yval,)# Training of the model history = model.train()

使用訓練好的模型,我們可以預測值並將其與原始值進行比較。

# Comparing the forecasts with the actual valuesyhat = [x[0] for x in model.predict(Xval)]y = [y[0] for y in Yval]# Creating the frame to store both predictionsdays = d[『dt』].values[-len(y):]frame = pd.concat([pd.DataFrame({『day』: days, 『temp』: y, 『type』: 『original』}), pd.DataFrame({『day』: days, 『temp』: yhat, 『type』: 『forecast』})])# Creating the unscaled values columnframe[『temp_absolute』] = [(x * train_std[『temp』]) + train_mean[『temp』] for x in frame[『temp』]]# Pivotingpivoted = frame.pivot_table(index=』day』, columns=’type』)pivoted.columns = [『_』.join(x).strip() for x in pivoted.columns.values]pivoted[『res』] = pivoted[『temp_absolute_original』] — pivoted[『temp_absolute_forecast』]pivoted[『res_abs』] = [abs(x) for x in pivoted[『res』]]

結果可視化

plt.figure(figsize=(12, 12))plt.plot(pivoted.index, pivoted.temp_absolute_original, color=』blue』, label=』original』)plt.plot(pivoted.index, pivoted.temp_absolute_forecast, color=’red』, label=』forecast』, alpha=0.6)plt.title(『Temperature forecasts — absolute data』)plt.legend()plt.show()

使用訓練好的模型,我們可以預測值並將其與原始值進行比較。

中位數絕對誤差為0.34攝氏度,平均值為0.48攝氏度。

要預測提前24小時,唯一需要做的就是更改超參數。 具體來說,是n_ahead變量。 該模型將嘗試使用之前(一周)的168小時來預測接下來的24小時值。

# Number of lags (hours back) to use for modelslag = 168# Steps ahead to forecast n_ahead = 24# Share of obs in testing test_share = 0.1# Epochs for trainingepochs = 20# Batch size batch_size = 512# Learning ratelr = 0.001# Number of neurons in LSTM layern_layer = 10# Creating the X and Y for trainingX, Y = create_X_Y(ts_s.values, lag=lag, n_ahead=n_ahead)n_ft = X.shape[2]Xtrain, Ytrain = X[0:int(X.shape[0] * (1 - test_share))], Y[0:int(X.shape[0] * (1 - test_share))]Xval, Yval = X[int(X.shape[0] * (1 - test_share)):], Y[int(X.shape[0] * (1 - test_share)):]# Creating the model object model = NNMultistepModel(X=Xtrain, Y=Ytrain, n_outputs=n_ahead, n_lag=lag, n_ft=n_ft, n_layer=n_layer, batch=batch_size, epochs=epochs, lr=lr, Xval=Xval, Yval=Yval,)# Training the model history = model.train()

檢查一些隨機的24小時區間:

有些24小時序列似乎彼此接近,而其他序列則不然。

平均絕對誤差為1.69 C,中位數為1.27C。

總結,本文介紹了在對時間序列數據進行建模和預測時使用的簡單管道示例:

讀取,清理和擴充輸入數據

為滯後和n步選擇超參數

為深度學習模型選擇超參數

初始化NNMultistepModel()類

擬合模型

預測未來n_steps

最後本文的完整代碼:https://github.com/Eligijus112/Vilnius-weather-LSTM

作者:Eligijus Bujokas

deephub翻譯組

相關焦點

  • 乾貨|時間序列預測類問題下的建模方案探索實踐
    隨著機器學習和深度學習的興起,時間序列預測類問題越來越多的被抽象為回歸問題,從而可以使用機器學習和深度學習的相關模型,不需要受到基本假設的限制,適用範圍更廣,更受到人們青睞。本文以疫情期間北京重點區域人群密度情況的預測為例,使用統計學模型ARMA,機器學習模型Xgboost和深度學習模型LSTM分別進行建模,並對這三種建模方案在實際操作時的複雜度、運行效率和預測準確度進行對比分析,從而直觀感受每種建模方案的優缺點,為真實場景中建模方案的選擇提供幫助和參考。
  • 摺疊革命,深度學習通過胺基酸序列預測蛋白質結構
    近些年,蛋白質通過自身的胺基酸序列可以實現被預測,在計算方法上有了巨大進步。如果都能使用這些計算方法,那生物醫學研究都可以被轉換成計算公式。然而,現在一些應用則受到了蛋白質規模和範圍的局限而無法決策。近期,來自哈佛醫學院的科學家應用了深度學習的方法,基於胺基酸序列來有效預測蛋白質的3D結構。
  • 如何使用LSTM在Keras中快速實現情感分析任務
    本文對 LSTM 進行了簡單介紹,並講述了如何使用 LSTM 在 Keras 中快速實現情感分析任務。長短期記憶網絡通常被稱為 LSTM,它是由 Hochreiter 和 Schmiduber 提出的,被廣泛地應用在語音識別、語言建模、情感分析和文本預測中。
  • 通過Python 代碼實現時間序列數據的統計學預測模型
    來源 | DeepHub IMBA封圖 | CSDN 付費下載於視覺中國在本篇中,我們將展示使用 Python 統計學模型進行時間序列數據分析。 目標是:根據兩年以上的每日廣告支出歷史數據,提前預測兩個月的廣告支出金額。
  • 時間序列模型matlab代碼 - CSDN
    時間序列數據分析意味著對可用數據進行分析,以找出數據的模式或趨勢,從而預測一些將來的價值,這些價值將有助於提高效率並優化業務決策。常見的用於時間序列分析的技術:本篇將介紹 - ARIMA模型在R中如何使用ARIMA建模ARIMA是AutoRegressive集成移動平均線的縮寫。
  • 通過深度學習來創作自己的音樂(附代碼)
    直到我遇到了深度學習。使用特定的技術和框架,我可以創作自己的原創音樂,而不需要真正了解任何音樂理論!這是我最喜歡的專業項目之一。我把我的兩個愛好——音樂和深度學習——結合起來,創造了一個自動生成音樂的模型。夢想成真了!我很高興與你分享我的方法,包括整個代碼,使你能夠生成自己的音樂!
  • 在Keras中可視化LSTM
    在本文中,我們不僅將在Keras中構建文本生成模型,還將可視化生成文本時某些單元格正在查看的內容。就像CNN一樣,它學習圖像的一般特徵,例如水平和垂直邊緣,線條,斑塊等。類似,在「文本生成」中,LSTM則學習特徵(例如空格,大寫字母,標點符號等)。 LSTM層學習每個單元中的特徵。
  • 「深度學習」運用多通道亞結構圖進行分子性質預測
    隨著人工智慧技術的發展,深度學習方法在藥物分子設計中的應用愈發廣泛。分子性質的預測在藥物發現過程中起著很大作用。為了對分子性質進行預測,首先需要對分子進行表徵。應用深度學習對分子進行表徵有多種途徑,例如SMILES將分子編碼成一個字符串序列,根據成環結構斷開的位置不同,同一分子可能得到不同的SMILES。
  • |利用深度學習實現流式肽合成的預測與優化
    Pentelute和Rafael Gomez-Bombarelli,Pentelute教授專注的方向是蛋白質工程與藥物遞送,而Bombarelli教授則是從事計算輔助的合成方法學研究。固相肽合成(SPPS)是人工合成多肽的重要手段,與基因重組表達相比,SPPS合成的肽不受序列與胺基酸種類的限制,因此使用範圍更廣。然而,SPPS涉及多個步驟的重複反應,對時間和體力的消耗非常大。
  • 深度學習模型創作動漫故事,比較LSTM和GPT2文本生成方法
    這個項目的動機是想看看在短短的幾年時間裡NLP領域的技術已經走了多遠,特別是當它涉及到生成創造性內容的時候。通過生成動畫概要,我探索了兩種文本生成技術,首先是使用相對陳舊的LSTM,然後使用經過微調的GPT2。
  • 8篇論文深入學習深度估計:深度預測;自我運動學習;觀看《冰雪奇緣...
    通過殘留學習對單目圖像和深度圖之間的模糊映射進行建模。反向Huber loss被用來做優化。這個模型可在圖像或視頻上實時運行。這篇論文提出的方法是使用CNN進行深度估計。該模型是完全卷積的,並包含跟蹤高維回歸問題的有效殘留向上採樣模塊(向上投影)。網絡的第一部分基於ResNet50,並使用預訓練的權值進行初始化。
  • Meal Kit 的時間序列數據預測實踐
    在時間序列中,缺失的數據可能會隱藏起來,因為數據可能在時間步長(1周)內不一致,這將在構建模型時可能會導致問題。對每個供應中心標識的數據進行分組。其中一些食材並非每周訂購/提供的,那麼將這幾周的需求量取為0,但是價格設置為組內食材的平均值。我們假設這些食材在缺失的幾周內是有提供的,但是沒有人買。在研究了餐盒市場後,人們意識到大部分成本來自易腐商品。
  • 機器翻譯:谷歌翻譯是如何對幾乎所有語言進行翻譯的?
    它使用人工神經網絡來預測某個單詞序列的概率,通常在單個集成模型中對整個句子進行建模。憑藉神經網絡的強大功能,神經網絡機器翻譯已經成為翻譯領域最強大的算法。這種最先進的算法是深度學習的一項應用,其中大量已翻譯句子的數據集用於訓練能夠在任意語言對之間的翻譯模型。
  • 吳恩達授課,斯坦福CS230深度學習課程資源開放
    你將在醫療、自動駕駛、手語識別、音樂生成和自然語言處理等領域中進行案例研究。你不僅能掌握理論,還能看到深度學習如何應用到產業中。我們將需要使用 Python 和 TensorFlow 來實現所有的項目,課程中也會教這一部分。完成這門課程後,你將能以創新的方式將深度學習應用到你的工作中。該課程是以翻轉課堂的形式教學的。
  • 在NLP中結合文本和數字特徵進行機器學習
    應用於自然語言處理的機器學習數據通常包含文本和數字輸入。例如,當您通過twitter或新聞構建一個模型來預測產品未來的銷售時,在考慮文本的同時考慮過去的銷售數據、訪問者數量、市場趨勢等將會更有效。您不會僅僅根據新聞情緒來預測股價的波動,而是會利用它來補充基於經濟指標和歷史價格的模型。
  • 今日Paper|縮放神經網絡;形變的LSTM;知識圖譜複雜問答;陰影著色等
    目錄ZoomNet:用於3D對象檢測的部分感知自適應縮放神經網絡ForecastNet:一種用於多步超前時間序列預測的時變深度前饋神經網絡結構形變的LSTM基於消息傳遞的知識圖譜複雜問答ForecastNet:一種用於多步超前時間序列預測的時變深度前饋神經網絡結構論文名稱:ForecastNet: A Time-Variant Deep Feed-Forward Neural Network Architecture for Multi-Step-Ahead Time-Series Forecasting
  • 想用深度學習譜寫自己的音樂嗎?這篇指南來幫你!(附代碼)
    直到我遇到了深度學習,這一切都成了過去。使用某些技術和框架,我能夠在不了解任何樂理的情況下創作自己的原創音樂樂譜!這是我最喜歡的專業項目之一。我結合了兩個愛好——音樂和深度學習——創建了一個自動的音樂生成模型。夢想成真了!我很高興與你分享我的方法,包括使你也能夠生成原創音樂的全部代碼!
  • 今日Paper|RevealNet;時間序列預測;無監督問答;實時語義立體匹配等
    目錄F, B, Alpha Matting使用一種基於符號化方法的LSTM網絡進行時間序列預測RevealNet:窺探RGB-D掃描場景中的每個物體BERT還不足以稱之為知識庫:無監督問答任務中BERT對事實性的知識和基於名稱的推理學習能力對比
  • 香港科技大學施行健:深度學習用於短臨降雨預報的一個基準和一個新...
    他的主要研究方向為深度學習,時空序列分析和計算機視覺。他是apache/mxnet的開發成員,同時是DMLC協會會員。視頻回放連結:http://www.mooc.ai/open/course/369分享主題:深度學習用於短臨降雨預報:一個基準和一個新模型
  • 序列模型簡介——RNN, Bidirectional RNN, LSTM, GRU
    既然我們已經有了前饋網絡和CNN,為什麼我們還需要序列模型呢?這些模型的問題在於,當給定一系列的數據時,它們表現的性能很差。序列數據的一個例子是音頻的剪輯,其中包含一系列的人說過的話。另一個例子是英文句子,它包含一系列的單詞。前饋網絡和CNN採用一個固定長度作為輸入,但是,當你看這些句子的時候,並非所有的句子都有相同的長度。