眾所周知,Python的功能是比較的強大的,除了可以用來對其進行查詢數(shù)據(jù)之外,還可以使用Python LSTM來預(yù)測銷售額,那么,預(yù)測的方法繁瑣嗎?下面小編就給大家做一個詳細(xì)介紹。
大家經(jīng)常會遇到一些需要預(yù)測的場景,比如預(yù)測品牌銷售額,預(yù)測產(chǎn)品銷量。
今天給大家分享一波使用LSTM進行端到端時間序列預(yù)測的完整代碼和詳細(xì)解釋。
我們先來了解兩個主題:
什么是時間序列分析?
什么是LSTM?
時間序列分析:時間序列表示基于時間順序的一系列數(shù)據(jù)。它可以是秒、分鐘、小時、天、周、月、年。未來的數(shù)據(jù)將取決于它以前的值。
在現(xiàn)實世界的案例中,我們主要有兩種類型的時間序列分析:
單變量時間序列
多元時間序列
對于單變量時間序列數(shù)據(jù),我們將使用單列進行預(yù)測。
正如我們所見,只有一列,因此即將到來的未來值將僅取決于它之前的值。
但是在多元時間序列數(shù)據(jù)的情況下,將有不同類型的特征值并且目標(biāo)數(shù)據(jù)將依賴于這些特征。
正如在圖片中看到的,在多元變量中將有多個列來對目標(biāo)值進行預(yù)測。(上圖中“count”為目標(biāo)值)
在上面的數(shù)據(jù)中,count不僅取決于它以前的值,還取決于其他特征。因此,要預(yù)測即將到來的count值,我們必須考慮包括目標(biāo)列在內(nèi)的所有列來對目標(biāo)值進行預(yù)測。
在執(zhí)行多元時間序列分析時必須記住一件事,我們需要使用多個特征預(yù)測當(dāng)前的目標(biāo),讓我們通過一個例子來理解:
在訓(xùn)練時,如果我們使用5列[feature1,feature2,feature3,feature4,target]來訓(xùn)練模型,我們需要為即將到來的預(yù)測日提供4列[feature1,feature2,feature3,feature4]。
LSTM
本文中不打算詳細(xì)討論LSTM。所以只提供一些簡單的描述,如果你對LSTM沒有太多的了解,可以參考我們以前發(fā)布的文章。
LSTM基本上是一個循環(huán)神經(jīng)網(wǎng)絡(luò),能夠處理長期依賴關(guān)系。
假設(shè)你在看一部電影。所以當(dāng)電影中發(fā)生任何情況時,你都已經(jīng)知道之前發(fā)生了什么,并且可以理解因為過去發(fā)生的事情所以才會有新的情況發(fā)生。RNN也是以同樣的方式工作,它們記住過去的信息并使用它來處理當(dāng)前的輸入。RNN的問題是,由于漸變消失,它們不能記住長期依賴關(guān)系。因此為了避免長期依賴問題設(shè)計了lstm。
現(xiàn)在我們討論了時間序列預(yù)測和LSTM理論部分。讓我們開始編碼。
讓我們首先導(dǎo)入進行預(yù)測所需的庫:
import numpy as np import pandas as pd from matplotlib import pyplot as plt from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM from tensorflow.keras.layers import Dense,Dropout from sklearn.preprocessing import MinMaxScaler from keras.wrappers.scikit_learn import KerasRegressor from sklearn.model_selection import GridSearchCV
加載數(shù)據(jù),并檢查輸出:
df=pd.read_csv("train.csv",parse_dates=["Date"],index_col=[0]) df.head() df.tail()
現(xiàn)在讓我們花點時間看看數(shù)據(jù):csv文件中包含了谷歌從2001-01-25到2021-09-29的股票數(shù)據(jù),數(shù)據(jù)是按照天數(shù)頻率的。
[如果您愿意,您可以將頻率轉(zhuǎn)換為“B”[工作日]或“D”,因為我們不會使用日期,我只是保持它的現(xiàn)狀。]
這里我們試圖預(yù)測“Open”列的未來值,因此“Open”是這里的目標(biāo)列。
讓我們看一下數(shù)據(jù)的形狀:
df.shape (5203,5)
現(xiàn)在讓我們進行訓(xùn)練測試拆分。這里我們不能打亂數(shù)據(jù),因為在時間序列中必須是順序的。
test_split=round(len(df)*0.20) df_for_training=df[:-1041] df_for_testing=df[-1041:] print(df_for_training.shape) print(df_for_testing.shape) (4162,5) (1041,5)
可以注意到數(shù)據(jù)范圍非常大,并且它們沒有在相同的范圍內(nèi)縮放,因此為了避免預(yù)測錯誤,讓我們先使用MinMaxScaler縮放數(shù)據(jù)。(也可以使用StandardScaler)
scaler=MinMaxScaler(feature_range=(0,1)) df_for_training_scaled=scaler.fit_transform(df_for_training) df_for_testing_scaled=scaler.transform(df_for_testing) df_for_training_scaled
將數(shù)據(jù)拆分為X和Y,這是最重要的部分,正確閱讀每一個步驟。
def createXY(dataset,n_past): dataX=[] dataY=[] for i in range(n_past,len(dataset)): dataX.append(dataset[i-n_past:i,0:dataset.shape[1]]) dataY.append(dataset[i,0]) return np.array(dataX),np.array(dataY) trainX,trainY=createXY(df_for_training_scaled,30) testX,testY=createXY(df_for_testing_scaled,30)
讓我們看看上面的代碼中做了什么:
N_past是我們在預(yù)測下一個目標(biāo)值時將在過去查看的步驟數(shù)。
這里使用30,意味著將使用過去的30個值(包括目標(biāo)列在內(nèi)的所有特性)來預(yù)測第31個目標(biāo)值。
因此,在trainX中我們會有所有的特征值,而在trainY中我們只有目標(biāo)值。
讓我們分解for循環(huán)的每一部分:
對于訓(xùn)練,dataset=df_for_training_scaled,n_past=30
當(dāng)i=30:
data_X.addend(df_for_training_scaled[i-n_past:i,0:df_for_training.shape[1]])
從n_past開始的范圍是30,所以第一次數(shù)據(jù)范圍將是-[30-30,30,0:5]相當(dāng)于[0:30,0:5]
因此在dataX列表中,df_for_training_scaled[0:30,0:5]數(shù)組將第一次出現(xiàn)。
現(xiàn)在,dataY.append(df_for_training_scaled[i,0])
i=30,所以它將只取第30行開始的open(因為在預(yù)測中,我們只需要open列,所以列范圍僅為0,表示open列)。
第一次在dataY列表中存儲df_for_training_scaled[30,0]值。
所以包含5列的前30行存儲在dataX中,只有open列的第31行存儲在dataY中。然后我們將dataX和dataY列表轉(zhuǎn)換為數(shù)組,它們以數(shù)組格式在LSTM中進行訓(xùn)練。
我們來看看形狀。
print("trainX Shape--",trainX.shape) print("trainY Shape--",trainY.shape) (4132,30,5) (4132,) print("testX Shape--",testX.shape) print("testY Shape--",testY.shape) (1011,30,5) (1011,)
4132是trainX中可用的數(shù)組總數(shù),每個數(shù)組共有30行和5列,在每個數(shù)組的trainY中,我們都有下一個目標(biāo)值來訓(xùn)練模型。
讓我們看一下包含來自trainX的(30,5)數(shù)據(jù)的數(shù)組之一和trainX數(shù)組的trainY值:
print("trainX[0]--n",trainX[0]) print("trainY[0]--",trainY[0])
如果查看trainX[1]值,會發(fā)現(xiàn)到它與trainX[0]中的數(shù)據(jù)相同(第一列除外),因為我們將看到前30個來預(yù)測第31列,在第一次預(yù)測之后它會自動移動到第2列并取下一個30值來預(yù)測下一個目標(biāo)值。
讓我們用一種簡單的格式來解釋這一切:
trainX——→trainY [0:30,0:5]→[30,0] [1:31,0:5]→[31,0] [2:32,0:5]→[32,0]
像這樣,每個數(shù)據(jù)都將保存在trainX和trainY中。
現(xiàn)在讓我們訓(xùn)練模型,我使用girdsearchCV進行一些超參數(shù)調(diào)整以找到基礎(chǔ)模型。
def build_model(optimizer): grid_model=Sequential() grid_model.add(LSTM(50,return_sequences=True,input_shape=(30,5))) grid_model.add(LSTM(50)) grid_model.add(Dropout(0.2)) grid_model.add(Dense(1)) grid_model.compile(loss='mse',optimizer=optimizer) return grid_modelgrid_model=KerasRegressor(build_fn=build_model,verbose=1,validation_data=(testX,testY)) parameters={'batch_size':[16,20], 'epochs':[8,10], 'optimizer':['adam','Adadelta']} grid_search=GridSearchCV(estimator=grid_model, param_grid=parameters, cv=2)
如果你想為你的模型做更多的超參數(shù)調(diào)整,也可以添加更多的層。但是如果數(shù)據(jù)集非常大建議增加LSTM模型中的時期和單位。
在第一個LSTM層中看到輸入形狀為(30,5)。它來自trainX形狀。
(trainX.shape[1],trainX.shape[2])→(30,5)
現(xiàn)在讓我們將模型擬合到trainX和trainY數(shù)據(jù)中。
grid_search=grid_search.fit(trainX,trainY)
由于進行了超參數(shù)搜索,所以這將需要一些時間來運行。
你可以看到損失會像這樣減少:
現(xiàn)在讓我們檢查模型的最佳參數(shù)。
grid_search.best_params_ {‘batch_size':20,‘epochs':10,‘optimizer':‘a(chǎn)dam'}
將最佳模型保存在my_model變量中。
my_model=grid_search.best_estimator_.model
現(xiàn)在可以用測試數(shù)據(jù)集測試模型。
prediction=my_model.predict(testX) print("predictionn",prediction) print("nPrediction Shape-",prediction.shape)
testY和prediction的長度是一樣的?,F(xiàn)在可以將testY與預(yù)測進行比較。
但是我們一開始就對數(shù)據(jù)進行了縮放,所以首先我們必須做一些逆縮放過程。
scaler.inverse_transform(prediction)
報錯了,這是因為在縮放數(shù)據(jù)時,我們每行有5列,現(xiàn)在我們只有1列是目標(biāo)列。
所以我們必須改變形狀來使用inverse_transform:
prediction_copies_array=np.repeat(prediction,5,axis=-1)
5列值是相似的,它只是將單個預(yù)測列復(fù)制了4次。所以現(xiàn)在我們有5列相同的值。
prediction_copies_array.shape (1011,5)
這樣就可以使用inverse_transform函數(shù)。
pred=scaler.inverse_transform(np.reshape(prediction_copies_array,(len(prediction),5)))[:,0]
現(xiàn)在讓我們看一下預(yù)測值和原始值:
print("Pred Values--",pred) print("nOriginal Values--",original)
最后繪制一個圖來對比我們的pred和原始數(shù)據(jù)。
plt.plot(original,color='red',label='Real Stock Price') plt.plot(pred,color='blue',label='Predicted Stock Price') plt.title('Stock Price Prediction') plt.xlabel('Time') plt.ylabel('Google Stock Price') plt.legend() plt.show()
看樣子還不錯,到目前為止,我們訓(xùn)練了模型并用測試值檢查了該模型?,F(xiàn)在讓我們預(yù)測一些未來值。
從主df數(shù)據(jù)集中獲取我們在開始時加載的最后30個值[為什么是30?因為這是我們想要的過去值的數(shù)量,來預(yù)測第31個值]
df_30_days_past=df.iloc[-30:,:] df_30_days_past.tail()
可以看到有包括目標(biāo)列(“Open”)在內(nèi)的所有列?,F(xiàn)在讓我們預(yù)測未來的30個值。
在多元時間序列預(yù)測中,需要通過使用不同的特征來預(yù)測單列,所以在進行預(yù)測時我們需要使用特征值(目標(biāo)列除外)來進行即將到來的預(yù)測。
這里我們需要“High”、“Low”、“Close”、“Adj Close”列的即將到來的30個值來對“Open”列進行預(yù)測。
df_30_days_future=pd.read_csv("test.csv",parse_dates=["Date"],index_col=[0]) df_30_days_future
剔除“Open”列后,使用模型進行預(yù)測之前還需要做以下的操作:
縮放數(shù)據(jù),因為刪除了‘Open’列,在縮放它之前,添加一個所有值都為“0”的Open列。
縮放后,將未來數(shù)據(jù)中的“Open”列值替換為“nan”
現(xiàn)在附加30天舊值和30天新值(其中最后30個“打開”值是nan)
df_30_days_future["Open"]=0 df_30_days_future=df_30_days_future[["Open","High","Low","Close","Adj Close"]] old_scaled_array=scaler.transform(df_30_days_past) new_scaled_array=scaler.transform(df_30_days_future) new_scaled_df=pd.DataFrame(new_scaled_array) new_scaled_df.iloc[:,0]=np.nan full_df=pd.concat([pd.DataFrame(old_scaled_array),new_scaled_df]).reset_index().drop(["index"],axis=1) full_df形狀是(60,5),最后第一列有30個nan值。
要進行預(yù)測必須再次使用for循環(huán),我們在拆分trainX和trainY中的數(shù)據(jù)時所做的。但是這次我們只有X,沒有Y值。
full_df_scaled_array=full_df.values all_data=[] time_step=30 for i in range(time_step,len(full_df_scaled_array)): data_x=[] data_x.append( full_df_scaled_array[i-time_step:i,0:full_df_scaled_array.shape[1]]) data_x=np.array(data_x) prediction=my_model.predict(data_x) all_data.append(prediction) full_df.iloc[i,0]=prediction
對于第一個預(yù)測,有之前的30個值,當(dāng)for循環(huán)第一次運行時它會檢查前30個值并預(yù)測第31個“Open”數(shù)據(jù)。
當(dāng)?shù)诙€for循環(huán)將嘗試運行時,它將跳過第一行并嘗試獲取下30個值[1:31]。這里會報錯錯誤因為Open列最后一行是“nan”,所以需要每次都用預(yù)測替換“nan”。
最后還需要對預(yù)測進行逆變換:
new_array=np.array(all_data) new_array=new_array.reshape(-1,1) prediction_copies_array=np.repeat(new_array,5,axis=-1) y_pred_future_30_days=scaler.inverse_transform(np.reshape(prediction_copies_array,(len(new_array),5)))[:,0] print(y_pred_future_30_days)
綜上所述,這篇文章就給大家介紹到這里了,希望可以給大家?guī)韼椭?/p>
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/128427.html
摘要:設(shè)計用于處理序列依賴性的強大類型的神經(jīng)網(wǎng)絡(luò)稱為復(fù)現(xiàn)神經(jīng)網(wǎng)絡(luò)。你會知道關(guān)于國際航空公司乘客時間序列預(yù)測問題。感謝所有指出這個問題的人和菲利普奧布萊恩幫助提出的解決方案。 段哥http://machinelearningmastery... Time Series Prediction with LSTM Recurrent Neural Networks in Python with K...
摘要:專門設(shè)計了一套針對時間序列預(yù)測問題的,目前提供三種預(yù)測模型。使用模型預(yù)測時間序列自回歸模型,可以簡稱為模型是統(tǒng)計學(xué)上處理時間序列模型的基本方法之一。使用模型訓(xùn)練驗證并進行時間序列預(yù)測的示例程序為。 前言如何用TensorFlow結(jié)合LSTM來做時間序列預(yù)測其實是一個很老的話題,然而卻一直沒有得到比較好的解決。如果在Github上搜索tensorflow time series,會發(fā)現(xiàn)star...
閱讀 1068·2023-01-14 11:38
閱讀 1064·2023-01-14 11:04
閱讀 905·2023-01-14 10:48
閱讀 2380·2023-01-14 10:34
閱讀 1148·2023-01-14 10:24
閱讀 1027·2023-01-14 10:18
閱讀 656·2023-01-14 10:09
閱讀 735·2023-01-14 10:02