原文鏈接和代碼在這裏:教你使用簡單神經網絡和LSTM進行時間序列預測(附代碼)
但是在測試的過程中,原代碼出現一些問題,直接運行原文中的代碼是行不通的。大部分的代碼解釋原文寫的很明白,這裏只做補充。
本文測試環境:Python3.6 Jupyter Notebook,TensorFlow+Keras
這篇文章採用人工神經網絡(Artificial Neural Network ,ANN)和長短期記憶循環神經網絡(Long Short-Term Memory Recurrent Neural Network ,LSTM RNN)對時間序列數據建立模型,目標是採用ANN和LSTM來預測波動性標準普爾500時間序列。
可以從這裏(https://ca.finance.yahoo.com/quote/%5Evix/history?ltr=1)下載波動性標準普爾500數據集,可以選擇你要下載的數據集的時間範圍。
開始敲代碼吧。首先是ANN模型
import pandas as pd
import numpy as np
%matplotlib inline
#在Jupyter Notebook要PLOT出圖像,必須加這個
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import r2_score
from keras.models import Sequential
from keras.layers import Dense
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from keras.layers import LSTM
#並將數據加載到Pandas 的dataframe中。
df = pd.read_csv("E:\data\VIX.csv")
#我們可以快速瀏覽前幾行。
print(df.head())
#刪除不需要的列,然後將“日期”列轉換爲時間數據類型,並將“日期”列設置爲索引。
df.drop(['Open', 'High', 'Low', 'Close', 'Volume'], axis=1, inplace=True)
df['Date'] = pd.to_datetime(df['Date'])
df = df.set_index(['Date'], drop=True)
df.head(10)
Out[1]:
Out[2]:
(我們只用Adj Close這個數據)
#我們繪製一個時間序列線圖。
plt.figure(figsize=(10, 6))
df['Adj Close'].plot();
#按日期“2018–09–20”將數據拆分爲訓練集和測試集
split_date = pd.Timestamp('2018-09-20')
df = df['Adj Close']
train = df.loc[:split_date]
test = df.loc[split_date:]
plt.figure(figsize=(10, 6))
ax = train.plot()
test.plot(ax=ax)
plt.legend(['train', 'test']);
Out:
#將訓練和測試數據縮放爲[-1,1]。
train=np.array(train).reshape(-1,1)
test=np.array(test).reshape(-1,1)
scaler = MinMaxScaler(feature_range=(-1, 1))
train_sc = scaler.fit_transform(train)
test_sc = scaler.fit_transform(test)
對之前的歸一化還原:
origin_data=scaler.inverse_transform(y_pred_test)‘‘’
最後會加上對數據還原的部分
#獲取訓練和測試數據。
X_train = train_sc[:-1]
y_train = train_sc[1:]
X_test = test_sc[:-1]
y_test = test_sc[1:]
#獲取訓練和測試數據。
X_train = train_sc[:-1]
y_train = train_sc[1:]
X_test = test_sc[:-1]
y_test = test_sc[1:]
解釋,序列預測a=np.array([2,3,4,5,6,7])
print(a[:-1]) #去掉最後一個元素
print(a[1:]) #從第二個元素開始
Out:
[2 3 4 5 6]
[3 4 5 6 7]
輸入x=[2 3 4 5 6]
對應的Label y=[3 4 5 6 7] (遞進預測下一個)‘‘’
#用於時間序列預測的簡單人工神經網絡ANN
ann=Sequential()
ann.add(Dense(12, input_dim=1, activation='relu'))
ann.add(Dense(1))
ann.compile(loss='mean_squared_error', optimizer='adam')
early_stop = EarlyStopping(monitor='loss', patience=2, verbose=1)
history= ann.fit(X_train, y_train, epochs=100, batch_size=1, verbose=1, callbacks=[early_stop], shuffle=False)
#進行預測
y_pred_test = ann.predict(X_test)
y_train_pred =ann.predict(X_train)
print("The R2 score on the Train set is:\t{:0.3f}".format(r2_score(y_train, y_train_pred)))
print("The R2 score on the Test set is:\t{:0.3f}".format(r2_score(y_test, y_pred_test)))
Out:
The R2 score on the Train set is: 0.851
The R2 score on the Test set is: 0.823
補充:
R2 決定係數(擬合優度)
模型越好:r2→1
模型越差:r2→0
#顯示6項數據
print('顯示數據:')
print(y_test[:6].reshape([1,6]))
print(y_pred_test[:6].reshape([1,6]))
#將歸一化數據還原
y_test_pred_origin=scaler.inverse_transform(y_pred_test)
y_test_origin=scaler.inverse_transform(y_test)
print('數據還原:')
print('真實值:'+'%s'%y_test_origin[:6].reshape([1,6]))
print('預測值:'+'%s'%y_test_pred_origin[:6].reshape([1,6]))
Out: (後面有預測和真實的評估指標MSE)
#顯示TEST真實值和預測值的對比圖
plt.figure(figsize=(10, 6))
plt.plot(y_test, label='True')
plt.plot(y_pred_test, label='NN')
plt.title("NN's Prediction")
plt.xlabel('Observation')
plt.ylabel('Adj Close Scaled')
plt.legend()
plt.show();
OUT:
LSTM 模型
x_train=X_train.reshape(1509,1,1)#注意input x_train 的shape
lstm_model = Sequential()
lstm_model.add(LSTM(7,activation='relu', kernel_initializer='lecun_uniform', return_sequences=False))
lstm_model.add(Dense(1))
lstm_model.compile(loss='mean_squared_error', optimizer='adam')
early_stop = EarlyStopping(monitor='loss', patience=2, verbose=1)
history_lstm_model = lstm_model.fit(x_train, y_train, epochs=100, batch_size=1, verbose=1, shuffle=False, callbacks=[early_stop])
LSTM模型輸入的shape和ANN有差別,所以要先對X_train 進行變換,後面的X_test也是如此。
OUT:
進行預測
x_test=X_test.reshape(251,1,1) #251 is the length of X_test
y_pred_test_lstm = lstm_model.predict(x_test)
y_train_pred_lstm = lstm_model.predict(x_train)
print("The R2 score on the Train set is:t{:0.3f}".format(r2_score(y_train, y_train_pred_lstm)))
print("The R2 score on the Test set is:t{:0.3f}".format(r2_score(y_test, y_pred_test_lstm)))
OUT:
#顯示TEST真實值和預測值的對比圖
plt.figure(figsize=(10, 6))
plt.plot(y_test, label='True')
plt.plot(y_pred_test_lstm, label='LSTM')
plt.title("LSTM's Prediction")
plt.xlabel('Observation')
plt.ylabel('Adj Close scaled')
plt.legend()
plt.show()
OUT:
#比較了兩種模型的測試MSE
ann_test_mse = ann.evaluate(X_test, y_test, batch_size=1)
lstm_test_mse = lstm_model.evaluate(x_test, y_test, batch_size=1)
print('ANN: %f'%ann_test_mse)
print('LSTM: %f'%lstm_test_mse)
Out:
小結:
其實要修改的地方不是很多,這是一個比較簡單的例子,不熟悉的話可能會費時間,對numpy和pandas要多加學習和練習。