iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0

LSTM、GRU如何實作?

今天我們要來實作LSTM以及GRU。

前置作業

我們使用Colab來當作我們的實作平台,並使用Keras來完成。

資料集

我們使用Google stock price來當作我們的資料集。
訓練集:2012年到2016年(共1258天)
測試集:2017年1月(共20天)
訓練集下載處
測試集下載處

前處理

首先要把我們的資料scale到0~1之間。

from keras.layers import Input, Dense, Conv1D, Conv2D, MaxPooling1D,\
    MaxPooling2D, UpSampling1D, UpSampling2D, Dropout, Lambda, Convolution2D,\
    Reshape, Activation, Flatten, add, concatenate, BatchNormalization,LSTM
from keras.models import Model, Sequential
import numpy as np
import keras
import csv


train_set=np.array([])
# 開啟 CSV 檔案
with open(os.path.join(workspace_dir, 'Train.csv'), newline='') as csvfile:
  rows = csv.reader(csvfile)
  for row in rows:
    train_set=np.append(train_set,row[1])
train_set=train_set[1:]
train_set=train_set.astype(float)
train_set=train_set.reshape((-1,1))

from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range = (0, 1))
x_train = sc.fit_transform(train_set)

接著設定Timestep。

X_train = []   #預測點的前N天的資料
y_train = []   #預測點
N=60#Timestep數量
for i in range(N, len(x_train)):  # 1258 是訓練集總數
    X_train.append(x_train[i-N:i, 0]) # 取出預測點的前N天放進訓練集
    y_train.append(x_train[i, 0]) # 取出預測點放進label
X_train, y_train = np.array(X_train), np.array(y_train) 
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))

模型

# model
input_shape=(X_train.shape[1], 1)

input = Input(input_shape, name='input')
layer=LSTM(units = 100, return_sequences = True)(input)
layer = Dropout(0.15)(layer)

layer=LSTM(units = 80, return_sequences = True)(layer)
layer = Dropout(0.15)(layer)

layer=LSTM(units = 60, return_sequences = True)(layer)
layer = Dropout(0.15)(layer)

layer=LSTM(units = 60)(layer)
layer = Dropout(0.15)(layer)
output=Dense(1)(layer)
model = Model(inputs=[input], outputs=[output])
model.summary()
model.compile(optimizer = 'adam', loss = 'MSE')

要注意的一點為 連接Output的地方return_sequences=false。

GRU也設一樣。

# model
input_shape=(X_train.shape[1], 1)

input = Input(input_shape, name='input')
layer=GRU(units = 100, return_sequences = True)(input)
layer = Dropout(0.15)(layer)

layer=GRU(units = 80, return_sequences = True)(layer)
layer = Dropout(0.15)(layer)

layer=GRU(units = 60, return_sequences = True)(layer)
layer = Dropout(0.15)(layer)

layer=GRU(units = 60)(layer)
layer = Dropout(0.15)(layer)
output=Dense(1)(layer)
model = Model(inputs=[input], outputs=[output])
model.summary()
model.compile(optimizer = 'adam', loss = 'MSE')

訓練

有了模型以後,就可以進行訓練了。

# 進行訓練
tag = 'LSTM0916_{}'.format(0)
h5_weight_path = os.path.join(WEIGHT_DIR, './' + tag + '.h5')
model.fit(X_train, y_train, epochs = 100, batch_size = 30)
#儲存權重
model.save_weights(os.path.join(WEIGHT_DIR, tag + ".h5"))

測試

訓練完畢後,記得先把測試資料集也先scale。

test_set=np.array([])
# 開啟 CSV 檔案
with open(os.path.join(workspace_dir, 'Test.csv'), newline='') as csvfile:
  rows = csv.reader(csvfile)
  for row in rows:
    test_set=np.append(test_set,row[1])
test_set=test_set[1:]
test_set=test_set.astype(float)
test_set=test_set.reshape((-1,1))

predict_dataset=np.append(train_set,test_set)
predict_dataset=predict_dataset[len(predict_dataset) - len(test_set) - N:]# timesteps為N:N+20 先前的N天資料+2017年的20天資料
predict_dataset=predict_dataset.reshape(-1,1)
predict_dataset=sc.transform(predict_dataset)

X_test = []
for i in range(N, len(predict_dataset)):
  X_test.append(predict_dataset[i-N:i, 0])
X_test = np.array(X_test)
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1)) 

值得一提的是這邊轉換是用sc.transform,而不是sc.fit_transform
通常會對train data 使用fit_transform,test data再使用sc.transform

轉完後,就可以測試啦XD

predicted_stock_price = model.predict(X_test)
predicted_stock_price = sc.inverse_transform(predicted_stock_price)

因為要畫出圖形,所以要把轉換的資料再轉換回去。

畫出結果

# Visualising the results
import matplotlib.pyplot as plt 
plt.plot(test_set, color = 'red', label = 'True Google Stock Price')  # 紅線表示真實股價
plt.plot(Grudata, color = 'k', label = 'Predicted Google Stock Price by GRU') 
plt.plot(predicted_stock_price, color = 'blue', label = 'Predicted Google Stock Price by LSTM') 
plt.title('Google Stock Price Prediction')
plt.xlabel('Day')
plt.ylabel('Google Stock Price')
plt.legend()
plt.savefig("./123.png",dpi=1000)
plt.show()

結論

今天我們實作了LSTM以及GRU,並且結果與真實結果的走勢是差不多的,且GRU較LSTM還好了一點,但是我們可以發現價格上來說還是有落差,因此還是不要相信此模型去買股票喔(誤。

參考資料

[實戰系列] 使用 Keras 搭建一個 LSTM 魔法陣(模型)
fit_transform,fit,transform區別和作用詳解!!!!!!


上一篇
Day 23 RNN和LSTM 和GRU
下一篇
Day25 機器學習會遇到的問題整理
系列文
Machine Learning與軟工是否搞錯了什麼?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言