TensorFlow深度學習!構建神經網路預測股票價格!⛵
- 2022 年 11 月 12 日
- 筆記
- TensorFlow, 人工智慧, 循環神經網路, 深度學習, 深度學習實戰通關指南 ⛵ 頂級「煉丹師」案例驅動成長之路, 神經網路, 長短時記憶網路
💡 作者:韓信子@ShowMeAI
📘 深度學習實戰系列://www.showmeai.tech/tutorials/42
📘 TensorFlow 實戰系列://www.showmeai.tech/tutorials/43
📘 本文地址://www.showmeai.tech/article-detail/327
📢 聲明:版權所有,轉載請聯繫平台與作者並註明出處
📢 收藏ShowMeAI查看更多精彩內容
股票價格數據是一個時間序列形態的數據,誠然,股市的漲落和各種利好利空消息更相關,更多體現的是人們的信心狀況,但是它的形態下,時序前後是有一定的相關性的,我們可以使用一種特殊類型的神經網路『循環神經網路 (RNN)』來對這種時序相關的數據進行建模和學習。
在本篇內容中,ShowMeAI將給大家演示,如何構建訓練神經網路並將其應用在股票數據上進行預測。
對於循環神經網路的詳細資訊講解,大家可以閱讀ShowMeAI整理的系列教程和文章詳細了解:
💡 數據獲取
在實際建模與訓練之前,我們需要先獲取股票數據。下面的程式碼使用 Ameritrade API 獲取並生成數據,也可以使用其他來源。
import matplotlib.pyplot as plt
import mplfinance as mpl
import pandas as pd
td_consumer_key = 'YOUR-KEY-HERE'
# 美國航空股票
ticker = 'AAL'
##periodType - day, month, year, ytd
##period - number of periods to show
##frequencyTYpe - type of frequency for each candle - day, month, year, ytd
##frequency - the number of the frequency type in each candle - minute, daily, weekly
endpoint = '//api.tdameritrade.com/v1/marketdata/{stock_ticker}/pricehistory?periodType={periodType}&period={period}&frequencyType={frequencyType}&frequency={frequency}'
# 獲取數據
full_url = endpoint.format(stock_ticker=ticker,periodType='year',period=10,frequencyType='daily',frequency=1)
page = requests.get(url=full_url,params={'apikey' : td_consumer_key})
content = json.loads(page.content)
# 轉成pandas可處理格式
df = pd.json_normalize(content['candles'])
# 設置時間戳為索引
df['timestamp'] = pd.to_datetime(df.datetime, unit='ms')
df = df.set_index("timestamp")
# 繪製數據
plt.figure(figsize=(15, 6), dpi=80)
plt.plot(df['close'])
plt.legend(['Closing Price'])
plt.show()
# 存儲前一天的數據
df["previous_close"] = df["close"].shift(1)
df = df.dropna() # 刪除缺失值
# 存儲
df.to_csv('../data/stock_'+ticker+'.csv', mode='w', index=True, header=True)
上面的程式碼查詢 Ameritrade API 並返回 10 年的股價數據,例子中的股票為『美國航空公司』。 數據繪圖結果如下所示:
💡 數據處理
我們載入剛才下載的數據文件,並開始處理預測。
# 讀取數據
ticker = 'AAL'
df = pd.read_csv("../data/stock_"+ticker+".csv")
# 設置索引
df['DateIndex'] = pd.to_datetime(df['timestamp'], format="%Y/%m/%d")
df = df.set_index('DateIndex')
下面我們對數據進幅度縮放,以便更好地送入神經網路和訓練。(神經網路是一種對於輸入數據幅度敏感的模型,不同欄位較大的幅度差異,會影響網路的訓練收斂速度和精度。)
# 幅度縮放
df2 = df
cols = ['close', 'volume', 'previous_close']
features = df2[cols]
scaler = MinMaxScaler(feature_range=(0, 1)).fit(features.values)
features = scaler.transform(features.values)
df2[cols] = features
在這裡,我們重點處理了收盤價、成交量和前幾天收盤價列。
💡 數據切分
接下來我們將數據拆分為訓練和測試數據集。
# 收盤價設為目標欄位
X = df2.drop(['close','timestamp'], axis =1)
y = df2['close']
import math
# 計算切分點(以80%的訓練數據為例)
train_percentage = 0.8
split_point = math.floor(len(X) * train_percentage)
# 時序切分
train_x, train_y = X[:split_point], y[:split_point]
test_x, test_y = X[split_point:], y[split_point:]
接下來,我們對數據進行處理,構建滑窗數據,沿時間序列創建數據樣本。(因為我們需要基於歷史資訊對未來的數值進行預測)
# 構建滑窗數據
import numpy.lib
from numpy.lib.stride_tricks import sliding_window_view
def genWindows(X_in, y_in, window_size):
X_out = []
y_out = []
length = X_in.shape[0]
for i in range(window_size, length):
X_out.append(X_in[i-window_size:i, 0:4])
y_out.append(y_in[i-1])
return np.array(X_out), np.array(y_out)
# 窗口大小為5
window_size = 5
X_train_win, y_train_win = genWindows(np.array(train_x), np.array(train_y), window_size)
X_test_win, y_test_win = genWindows(np.array(test_x), np.array(test_y), window_size)
💡 模型構建&訓練
構建完數據之後,我們就要構建 RNN 模型了,具體的程式碼如下所示。注意到下面使用了1個回調函數,模型會在驗證集性能沒有改善的情況下提前停止訓練,防止模型過擬合影響泛化能力。
from tensorflow.keras import callbacks
# 早停止 回調函數
callback_early_stopping = callbacks.EarlyStopping(
monitor="loss",
patience=10,#look at last 10 epochs
min_delta=0.0001,#loss must improve by this amount
restore_best_weights=True,
)
from tensorflow import keras
from tensorflow.keras import layers
from keras.models import Sequential
# 構建RNN模型,結構為 輸入-RNN-RNN-連續值輸出
input_shape=(X_train_win.shape[1],X_train_win.shape[2])
print(input_shape)
model = Sequential(
[
layers.Input(shape=input_shape),
layers.SimpleRNN(units=128, return_sequences=True),
layers.SimpleRNN(64, return_sequences=False),
layers.Dense(1, activation="linear"),
]
)
# 優化器
optimizer = keras.optimizers.Nadam(learning_rate=0.0001)
model.compile(optimizer=optimizer, loss="mse")
# 模型結構總結
model.summary()
# 模型訓練
batch_size = 20
epochs = 50
history = model.fit(X_train_win, y_train_win,
batch_size=batch_size, epochs=epochs,
callbacks=[
callback_early_stopping
])
模型訓練過程的損失函數(訓練集上)的變化如下圖所示。隨著訓練過程推進,模型損失不斷優化,初期的優化和loss減小速度很快,後逐漸趨於平穩。
大約 10 個 epoch 後達到了最佳結果,訓練好的模型就可以用於後續預測了,我們可以先對訓練集進行預測,驗證一下在訓練集上學習的效果。
# 訓練集預測
pred_train_y = model.predict(X_train_win)
# 繪圖
plt.figure(figsize=(15, 6), dpi=80)
plt.plot(np.array(train_y))
plt.plot(pred_train_y)
plt.legend(['Actual', 'Predictions'])
plt.show()
模型在訓練集上學習的效果還不錯,大家可以看到預測結果和真實值對比繪圖如下:
💡 模型預測&應用
我們要評估模型的真實表現,需要在它沒有見過的測試數據上評估,大家記得我們在數據切分的時候預留了 20% 的數據,下面我們用模型在這部分數據上預測並評估。
# 測試集預測
pred_test_y = model.predict(X_test_win)
# 預測結果繪製
plt.figure(figsize=(15, 6), dpi=80)
plt.plot(np.array(test_y))
plt.plot(pred_test_y)
plt.legend(['Actual', 'Predictions'])
plt.show()
相對訓練集來說,大家看到測試集上的效果稍有偏差,但是總體趨勢還是預測得不錯。
我們要考察這個模型對於時間序列預測的泛化能力,可以進行更嚴格一點的建模預測,比如將訓練得到的模型應用與另一支完全沒見過的股票上進行預測。如下為我們訓練得到的模型對 Microsoft/微軟股票價格的預測:
我們從圖上可以看到,模型表現良好(預測存在一定程度的噪音,但它對總體趨勢的預測比較準確)。
參考資料
- 📘 深度學習教程:吳恩達專項課程 · 全套筆記解讀://www.showmeai.tech/tutorials/35
- 📘 自然語言處理教程:斯坦福CS224n課程 · 課程帶學與全套筆記解讀://www.showmeai.tech/tutorials/36
- 📘 深度學習教程 | 序列模型與RNN網路://www.showmeai.tech/article-detail/225
- 📘 NLP教程(5) – 語言模型、RNN、GRU與LSTM://www.showmeai.tech/article-detail/239