北科資工二多媒體技術與應用 第八次團隊作業 - 使用 google colab 與 LSTM 進行期貨價格預測

筆記說明

此筆記用途在於台北科技大學資訊工程系大二下多媒體技術與應用作業紀錄
並非所有人都適用,部分對我而言稍加容易的內容並不會寫在此內。
這是學習後心得的筆記,可能不太適用會未來的學生

由於我沒有學習過裡面的理論,因此這是資工大二學生透過網路與自身理解的筆記,學習價值並不高、且可能擁有大量錯誤。

訓練的資料是從 FinMind Api 取得,謝謝他們的無私奉獻,讓我們可以輕鬆讀取資料。

專案說明

如紅色線條上方說明文字

此文章的目的是紀錄如何透過 LSTM 與 google colab 來進行期貨價格預測

Long Short-Term Memory(LSTM) 模型說明

LSTM 主要是透過 cell 組成,cell 由輸入門、遺忘門、輸出門、單元狀態組成。

  • 輸入門:決定當下輸入的資料有多少要保留到此 cell
  • 遺忘門:決定前一個 cell 給我們的資料要保留多少
  • 輸出門:決定有多少資料要輸出給下一個 cell

詳細的講解可以看這篇,解釋得很好,Keras关于LSTM的units参数,还是不理解? by lonlon ago

LSTM 訓練流層

  • 讀取資料、資料前處理
  • 將資料處理成 train_dataset、test_dataset
  • 建立 LSTM 神經網路模型,設定模型內的神經網路
  • 將資料送入網路進行訓練
  • 使用訓練好的模型進行預測

使用 google colab 進行期貨價格預測

如果不知道 colab 如何打開,可以看看 使用 google colab 與進行 yolo 訓練 by 大衞的筆記

import package

第一步先 import 資料

1
2
3
4
5
6
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM

從 Findmind API 獲取期貨資料

Findmind API 是蒐集了主要大國投資商品的資料,包括台股、期貨….。

我們只需要 call API,就可以獲得大量的資料,是非常方便的工具。

謝謝 Findmind 團隊們用心支援且有免費的項目可讓學生順利用來測試。

接下來我們 call api,獲得資料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
import pandas as pd
url = "https://api.finmindtrade.com/api/v4/data"
parameter = {
"dataset": "TaiwanFuturesDaily",
"data_id": "TX",
"start_date": "2021-05-01",
"end_date": "2021-05-29",
"token": "", # 參考登入,獲取金鑰
}
resp = requests.get(url, params=parameter)
data = resp.json()
data = pd.DataFrame(data["data"])
print(data.head())
data = data.set_index("date")
print(data)

其完成後主要如下,雖然我覺得 google colab 會隱藏資訊不是很好…。但是他提供強大運算,超讚的拉!

畫出趨勢圖

我們先畫出趨勢圖,檢查這份資料是否有異常的情況

1
2
3
4
5
6
#劃出趨勢圖
def get_picture(data = data):
data['close'].plot()
plt.figure(figsize=(100, 50)) #figsize 設定寬度、長度
plt.show()
get_picture(data)

趨勢圖大概如下

將 dataframe 的 date 轉換為時間軸,好讓 LSTM 認清楚新舊資料

於是我們將資料進行轉換

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#轉換序列
def processing(data=data, long=11): #long 是我們的記憶長度,也就是我們通常用 11 筆來預測預估一筆資料
#將資料型態轉換為 float,怕資料讀取時 dataframe 誤以為字串
data["close"] = data["close"].astype(float)
sample_size = len(data) - long + 1 #計算樣本長度
print("共有{}個樣本".format(sample_size))

data_sample = [] #新增 list 用來儲存
for i in range(sample_size):
data_sample.append(data["close"][i:i+long]) #將前 11 筆資料,一同放入 data_sample
#注意:python dataframe [i:i+3],最後一筆資料是不會抓的
#舉例:df[1:3] py 只抓兩筆資料

data_sample = np.array(data_sample) #將 list 轉換為 num array
return data_sample

processing(data)

完成後大概如下

建立 LSTM 模型

此 function 則是建立且訓練 LSTM 網路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def stock_LSTM(input_data=None): #input_data 要訓練的資料
scaler_x = MinMaxScaler() #將原先的資料數值分布改分散至 0~1 區間,稱為歸一化
scaler_y = MinMaxScaler() #同上
x = input_data[:, :-1] # x 軸為所有期貨資料
y = input_data[:, -1] #y 軸則是最後一筆期貨資料
x = scaler_x.fit_transform(x) #資料進行歸一化,使用方法為找出轉換資料規則
y = scaler_y.fit_transform(np.reshape(y, (len(y), 1))) #將資料進行 reshape
spilt = int(len(y) * 0.8) #0.8 為訓練集 0.2 為測試集
x_train = x[:spilt] #py dataframe 切資料
x_test = x[spilt:]
y_train = y[:spilt]
y_test = y[spilt:] #以上
print(x_train.shape[0], x_train.shape[1])
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1)) #將資料 reshape
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1)) #將資料 reshape

model = Sequential() #初始化 Sequentail 模型,序列模型
#加入 LSTM 深度學習,使用 50 個維度,並輸入資料
model.add(LSTM(50, input_shape=(x_train.shape[1],1), return_sequences=True))
#model.add(LSTM(100)) 如果使用 100 個維度就使用這個,越多維度理論上會越精準,但要小心 overfitting

#加入 dense 激勵函數,主要是判定權重用
model.add(Dense(1, activation="linear"))
model.compile(loss="mse", optimizer="rmsprop") #進行訓練,選擇遺失函數的方法、與 optimizer 方法
print("訓練中...")
#開始進行模型擬和,batch_size 的大小,epochs 疊代大小,
#validation_split 將訓連集資料一部份用於模型測試
history = model.fit(x_train, y_train, batch_size=8, epochs=300, validation_split=0.1)

#繪製多圖,row 1 column 2
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4.5))

#劃出 train_loss,這個資料的不確定姓
ax1.set_title("train_loss")
ax1.set_ylabel("loss")
ax1.set_xlabel("Epoch")
ax1.plot(history.history["loss"])

#劃出預測圖
predict = model.predict(x_test)
#將原本進行規一化的資料,反轉為原始數據
y_test = scaler_y.inverse_transform(np.reshape(y_test, (len(y_test), 1)))
#將原本進行規一化的資料,反轉為原始數據
predict = scaler_y.inverse_transform(predict)

#劃出預測圖
ax2.set_title("stock predict result")
ax2.set_ylabel("price")
ax2.set_xlabel("time")
ax2.plot(predict, "g:")
ax2.plot(y_test, "r-")
fig.show()

必須看到疊代跑到 300 才表示 LSTM 完成,接下來則會看到兩張圖
train_loss 表示資料的不確定性、stock predict result 的綠色折線圖則是原始的歷史價格走勢、紅色則是 LSTM 的預測價格走勢,可以發現 LSTM 其實理論上蠻準的,用於預測趨勢是可行的!

參考連結

北科資工大二下 多媒體技術與應用 L10 課程
實作:透過LSTM預測股票 by nthu
Day 05:Keras 模型、函數及參數使用說明 by I code so I am
Keras 中文文檔
Keras Optimizers
tensorflow中model.fit()用法 by yunfeather
python 可视化:fig, ax = plt.subplots()画多表图的3中常见样例 & 自定义图表格式 by htuhxf
inverse_transform()的用法 by bebr
开始使用 Keras Sequential 顺序模型 by Keras 中文文檔
RMSprop by Keras 中文文檔
数据归一化 - MinMaxScaler()/MaxAbsScaler() - Python代码 by 黄大侠aa

心得

謝謝助教與老師!這是我很有收穫的一次!

上次的 yolo 其實也大有收穫,但是 yolo 太多我不懂的問題了,讓我在突破的時候充滿痛苦感QQ,但是這次的 LSTM 就不會很有痛苦感,而且可以用於我感興趣的。

這次助教的 code 給的很詳細,然後我在寫 blog 時就可以將一些在寫 code 沒有注意到的事項補足、加強,這樣我就可以將應用 LSTM 用的在更好些。

希望我可以應用看看股票預測。

也要謝謝力瑋告訴我 finMind API 可以讓我獲得資料,這是非常好用的 API,也要謝謝力瑋可以在 6/1 01:04 時還可以解釋我的問題。

嗚嗚,我的資工導師QQ。

  • 版權聲明: 本部落格所有文章除有特別聲明外,均採用 Apache License 2.0 許可協議。轉載請註明出處!
  • © 2020-2024 John Doe
  • Powered by Hexo Theme Ayer
  • PV: UV: