av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

使用LSTM對銷售額預(yù)測(Python代碼)

大家經(jīng)常會遇到一些需要預(yù)測的場景,比如預(yù)測品牌銷售額,預(yù)測產(chǎn)品銷量。

目前成都創(chuàng)新互聯(lián)已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計、鄒平網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

今天給大家分享一波使用 LSTM 進行端到端時間序列預(yù)測的完整代碼和詳細解釋。

我們先來了解兩個主題:

  •  什么是時間序列分析?
  •  什么是 LSTM?

時間序列分析:時間序列表示基于時間順序的一系列數(shù)據(jù)。它可以是秒、分鐘、小時、天、周、月、年。未來的數(shù)據(jù)將取決于它以前的值。

在現(xiàn)實世界的案例中,我們主要有兩種類型的時間序列分析:

  •  單變量時間序列
  •  多元時間序列

對于單變量時間序列數(shù)據(jù),我們將使用單列進行預(yù)測。

正如我們所見,只有一列,因此即將到來的未來值將僅取決于它之前的值。

但是在多元時間序列數(shù)據(jù)的情況下,將有不同類型的特征值并且目標數(shù)據(jù)將依賴于這些特征。

正如在圖片中看到的,在多元變量中將有多個列來對目標值進行預(yù)測。(上圖中“count”為目標值)

在上面的數(shù)據(jù)中,count不僅取決于它以前的值,還取決于其他特征。因此,要預(yù)測即將到來的count值,我們必須考慮包括目標列在內(nèi)的所有列來對目標值進行預(yù)測。

在執(zhí)行多元時間序列分析時必須記住一件事,我們需要使用多個特征預(yù)測當前的目標,讓我們通過一個例子來理解:

在訓練時,如果我們使用 5 列 [feature1, feature2, feature3, feature4, target] 來訓練模型,我們需要為即將到來的預(yù)測日提供 4 列 [feature1, feature2, feature3, feature4]。

LSTM

本文中不打算詳細討論LSTM。所以只提供一些簡單的描述,如果你對LSTM沒有太多的了解,可以參考我們以前發(fā)布的文章。

LSTM基本上是一個循環(huán)神經(jīng)網(wǎng)絡(luò),能夠處理長期依賴關(guān)系。

假設(shè)你在看一部電影。所以當電影中發(fā)生任何情況時,你都已經(jīng)知道之前發(fā)生了什么,并且可以理解因為過去發(fā)生的事情所以才會有新的情況發(fā)生。RNN也是以同樣的方式工作,它們記住過去的信息并使用它來處理當前的輸入。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”是這里的目標列。

讓我們看一下數(shù)據(jù)的形狀:

df.shape
(5203,5)

現(xià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ù)測下一個目標值時將在過去查看的步驟數(shù)。

這里使用30,意味著將使用過去的30個值(包括目標列在內(nèi)的所有特性)來預(yù)測第31個目標值。

因此,在trainX中我們會有所有的特征值,而在trainY中我們只有目標值。

讓我們分解for循環(huán)的每一部分:

對于訓練,dataset = df_for_training_scaled, n_past=30

當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] 相當于 [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中進行訓練。

我們來看看形狀。

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 中,我們都有下一個目標值來訓練模型。

讓我們看一下包含來自 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ù)測下一個目標值。

讓我們用一種簡單的格式來解釋這一切:

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)在讓我們訓練模型,我使用 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("prediction\n", prediction)
print("\nPrediction Shape-",prediction.shape)

testY 和 prediction 的長度是一樣的。現(xiàn)在可以將 testY 與預(yù)測進行比較。

但是我們一開始就對數(shù)據(jù)進行了縮放,所以首先我們必須做一些逆縮放過程。

scaler.inverse_transform(prediction)

報錯了,這是因為在縮放數(shù)據(jù)時,我們每行有 5 列,現(xiàn)在我們只有 1 列是目標列。

所以我們必須改變形狀來使用 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]

但是逆變換后的第一列是我們需要的,所以我們在最后使用了 → [:,0]。

現(xiàn)在將這個 pred 值與 testY 進行比較,但是 testY 也是按比例縮放的,也需要使用與上述相同的代碼進行逆變換。

original_copies_array = np.repeat(testY,5, axis=-1)
original=scaler.inverse_transform(np.reshape(original_copies_array,(len(testY),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()

看樣子還不錯,到目前為止,我們訓練了模型并用測試值檢查了該模型。現(xiàn)在讓我們預(yù)測一些未來值。

從主 df 數(shù)據(jù)集中獲取我們在開始時加載的最后 30 個值[為什么是 30?因為這是我們想要的過去值的數(shù)量,來預(yù)測第 31 個值]

df_30_days_past=df.iloc[-30:,:]
df_30_days_past.tail()

可以看到有包括目標列(“Open”)在內(nèi)的所有列?,F(xiàn)在讓我們預(yù)測未來的 30 個值。

在多元時間序列預(yù)測中,需要通過使用不同的特征來預(yù)測單列,所以在進行預(yù)測時我們需要使用特征值(目標列除外)來進行即將到來的預(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 個值,當 for 循環(huán)第一次運行時它會檢查前 30 個值并預(yù)測第 31 個“Open”數(shù)據(jù)。

當?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)

這樣一個完整的流程就已經(jīng)跑通了。

如果你想看完整的代碼,可以在這里查看:

??https://github.com/sksujan58/Multivariate-time-series-forecasting-using-LSTM??


本文題目:使用LSTM對銷售額預(yù)測(Python代碼)
當前路徑:http://uogjgqi.cn/article/cdhdgis.html
掃二維碼與項目經(jīng)理溝通

我們在微信上24小時期待你的聲音

解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流