基于LSTM的時(shí)間序列數(shù)據(jù)(多步)預(yù)測(cè)

LSTM原理

LSTM結(jié)構(gòu)

LSTM的原理,這里不做多余描述,具體可以參照這幾個(gè)博客,介紹的很好。
blog1:Understanding LSTM Networks
blog2:Long Short-Term Memory Units (LSTMs)
blog3:LSTM詳解 反向傳播公式推導(dǎo)
blog4:LSTM詳解

數(shù)據(jù)集

構(gòu)造數(shù)據(jù)集

數(shù)據(jù)為單變量數(shù)據(jù),上圖顯示的是,如何構(gòu)造sequence to sequece。有點(diǎn)滑動(dòng)窗口的思想。
網(wǎng)絡(luò)博客上面,大多參照這篇文章Time Series Prediction with LSTM Recurrent Neural Networks in Python with Keras.這位博主,有很多時(shí)間方面預(yù)測(cè)的文章,可以去他博客里面學(xué)習(xí)。這是中文版的Time Series Prediction with LSTM Recurrent Neural Networks in Python with Keras(博客里面有數(shù)據(jù)集)
在學(xué)習(xí)上述博客,以及上述博客的中文翻譯基礎(chǔ)上,對(duì)我的時(shí)間序列數(shù)據(jù)進(jìn)行多步預(yù)測(cè)。

代碼

本案例主要是,我自己做項(xiàng)目練習(xí)多步預(yù)測(cè)使用,具體公司數(shù)據(jù)集,不能提供。想要做練習(xí),大家可以參照我給的連接,去他們的博客中學(xué)習(xí)。
這個(gè)代碼部分可以不用細(xì)看。主要有幾個(gè)地方希望初學(xué)者理解。
第一個(gè):如何構(gòu)造sequence to sequence,請(qǐng)參照上圖;
第二個(gè):多步預(yù)測(cè)的時(shí)候,這里面采用的事循環(huán)預(yù)測(cè)的方式。即上次預(yù)測(cè)的值y,添加到數(shù)據(jù)集中當(dāng)做X,然后在預(yù)測(cè)新的y。如此往復(fù),直到達(dá)到預(yù)測(cè)數(shù)據(jù)為止。
第三個(gè):注意keras中,輸入的維度關(guān)系。這篇文章介紹的比較好Keras中的LSTM
第四個(gè):下面代碼的測(cè)試集被省去了。可以參照上面的博客,一樣可以學(xué)習(xí)。


import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error

#讀取數(shù)據(jù)
data = pd.read_csv("./data/data_complete.csv")[['sump']]
dataf = data.values[0:-288]
def create_dataset(dataset, timesteps=36,predict_size=6):#構(gòu)造數(shù)據(jù)集
    datax=[]#構(gòu)造x
    datay=[]#構(gòu)造y
    for each in range(len(dataset)-timesteps - predict_steps):
        x = dataset[each:each+timesteps,0]
        y = dataset[each+timesteps:each+timesteps+predict_steps,0]
        datax.append(x)
        datay.append(y)
    return datax, datay#np.array(datax),np.array(datay)
#構(gòu)造train and predict
scaler = MinMaxScaler(feature_range=(0,1))
dataf = scaler.fit_transform(dataf)
train = dataf.copy()
timesteps = 72#構(gòu)造x,為72個(gè)數(shù)據(jù),表示每次用前72個(gè)數(shù)據(jù)作為一段
predict_steps = 12#構(gòu)造y,為12個(gè)數(shù)據(jù),表示用后12個(gè)數(shù)據(jù)作為一段
length = 288#預(yù)測(cè)多步,預(yù)測(cè)288個(gè)數(shù)據(jù),每次預(yù)測(cè)12個(gè),想想要怎么構(gòu)造預(yù)測(cè)才能滿足288?
trainx, trainy = create_dataset(train, timesteps, predict_steps)
trainx = np.array(trainx)
trainy = np.array(trainy)

#變換
trainx = np.reshape(trainx,(trainx.shape[0],timesteps,1))#變換shape,以滿足keras
#lstm training
model = Sequential()
model.add(LSTM(128,input_shape=(timesteps,1),return_sequences= True))
model.add(Dropout(0.5))
model.add(LSTM(128,return_sequences=True))
#model.add(Dropout(0.3))
model.add(LSTM(64,return_sequences=False))
#model.add(Dropout(0.2))
model.add(Dense(predict_steps))
model.compile(loss="mean_squared_error",optimizer="adam")
model.fit(trainx,trainy, epochs= 50, batch_size=200)
#predict
#因?yàn)槊看沃荒茴A(yù)測(cè)12個(gè)數(shù)據(jù),但是我要預(yù)測(cè)288個(gè)數(shù)據(jù),所以采用的就是循環(huán)預(yù)測(cè)的思路。每次預(yù)測(cè)的12個(gè)數(shù)據(jù),添加到數(shù)據(jù)集中充當(dāng)預(yù)測(cè)x,然后在預(yù)測(cè)新的12個(gè)y,再添加到預(yù)測(cè)x列表中,如此往復(fù)。最終預(yù)測(cè)出288個(gè)點(diǎn)。
predict_xlist = []#添加預(yù)測(cè)x列表
predict_y = []#添加預(yù)測(cè)y列表
predict_xlist.extend(dataf[dataf.shape[0]-timesteps:dataf.shape[0],0].tolist())#已經(jīng)存在的最后timesteps個(gè)數(shù)據(jù)添加進(jìn)列表,預(yù)測(cè)新值(比如已經(jīng)有的數(shù)據(jù)從1,2,3到288?,F(xiàn)在要預(yù)測(cè)后面的數(shù)據(jù),所以將216到288的72個(gè)數(shù)據(jù)添加到列表中,預(yù)測(cè)新的值即288以后的數(shù)據(jù))
while len(predict_y) < length:
    predictx = np.array(predict_xlist[-timesteps:])#從最新的predict_xlist取出timesteps個(gè)數(shù)據(jù),預(yù)測(cè)新的predict_steps個(gè)數(shù)據(jù)(因?yàn)槊看晤A(yù)測(cè)的y會(huì)添加到predict_xlist列表中,為了預(yù)測(cè)將來(lái)的值,所以每次構(gòu)造的x要取這個(gè)列表中最后的timesteps個(gè)數(shù)據(jù)詞啊性)
    predictx = np.reshape(predictx,(1,timesteps,1))#變換格式,適應(yīng)LSTM模型
    #print("predictx"),print(predictx),print(predictx.shape)
    #預(yù)測(cè)新值
    lstm_predict = model.predict(predictx)
    #predict_list.append(train_predict)#新值y添加進(jìn)列表,做x
    #滾動(dòng)預(yù)測(cè)
    #print("lstm_predict"),print(lstm_predict[0])
    predict_xlist.extend(lstm_predict[0])#將新預(yù)測(cè)出來(lái)的predict_steps個(gè)數(shù)據(jù),加入predict_xlist列表,用于下次預(yù)測(cè)
    # invert
    lstm_predict = scaler.inverse_transform(lstm_predict)
    predict_y.extend(lstm_predict[0])#預(yù)測(cè)的結(jié)果y,每次預(yù)測(cè)的12個(gè)數(shù)據(jù),添加進(jìn)去,直到預(yù)測(cè)288個(gè)為止
    #print("xlist", predict_xlist, len(predict_xlist))
    #print(lstm_predict, len(lstm_predict))
    #print(predict_y, len(predict_y))
#error

y_ture = np.array(data.values[-288:])
train_score = np.sqrt(mean_squared_error(y_ture,predict_y))
print("train score RMSE: %.2f"% train_score)
y_predict = pd.DataFrame(predict_y,columns=["predict"])
y_predict.to_csv("y_predict_LSTM.csv",index=False)
#plot
#plt.plot(y_ture,c="g")
#plt.plot(predict_y, c="r")
#plt.show()

結(jié)果

預(yù)測(cè)結(jié)果

預(yù)測(cè)的效果不好。涉及的構(gòu)建數(shù)據(jù)的X和y的長(zhǎng)度,以及搭建的網(wǎng)絡(luò)等等原因。
還在學(xué)習(xí)中,歡迎指教下我。

參考文獻(xiàn)

多步預(yù)測(cè)
多變量預(yù)測(cè)
多變量預(yù)測(cè)2
多層LSTM預(yù)測(cè)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容