在金融領域,預測股票價格走勢一直是眾多投資者和研究者關注的焦點。今天,我們將利用深度學習中的循環神經網絡(RNN)來構建一個簡單的股票價格預測模型,并詳細介紹從數據加載、預處理、模型搭建、訓練到最終結果可視化的全過程。
一、項目概述
本項目旨在通過歷史股票價格數據,訓練一個 RNN 模型,使其能夠對未來股票價格進行一定程度的預測。我們將使用 Python 作為主要編程語言,結合 NumPy、PyTorch 以及 Scikit-learn 等強大的庫來實現這一目標。
二、數據準備
- 加載數據:首先,我們使用?
np.loadtxt
?函數從 CSV 文件(假設名為?data-02-stock_daily.csv
)中讀取股票價格數據。這里需要注意指定正確的分隔符,通常股票數據 CSV 文件是以逗號分隔的,所以我們傳入?delimiter=','
。讀取到的數據是一個二維數組,每一行代表一天的股票相關信息,如開盤價、收盤價、最高價、最低價等。為了讓數據按照時間順序排列,方便后續處理,我們使用切片操作?data = data[::-1]
?將數據反轉。 - 歸一化處理:不同特征的數值范圍可能差異很大,這會影響模型訓練的效率和效果。因此,我們引入?
MinMaxScaler
?類進行歸一化處理。它會將數據的每一個特征都映射到 0 到 1 的區間內,具體操作是通過?data = MinMaxScaler().fit_transform(data)
?實現。經過這一步,數據的分布更加規整,有助于模型更快更好地收斂。 - 構建輸入輸出序列:為了讓 RNN 模型能夠學習到股票價格的時間序列特征,我們需要設置一個時間步長?
c
(這里設為 7)。通過循環遍歷歸一化后的數據,構建輸入序列?x
?和對應的輸出序列?y
。對于輸入序列,我們將連續?c
?天的數據作為一個樣本,即?x.append(data[i:i + c])
;而輸出序列則是第?c + 1
?天的股票價格,也就是?y.append(data[i + c][-1])
。最后,將?x
?和?y
?轉換為 PyTorch 張量,方便后續在深度學習框架中使用,使用?x = torch.tensor(x, dtype=torch.float)
?和?y = torch.tensor(y, dtype=torch.float)
?完成轉換。 - 劃分數據集:使用?
sklearn
?的?train_test_split
?函數將數據集劃分為訓練集和測試集。為了保證實驗的可重復性,我們指定?test_size=0.2
,表示測試集占總數據集的 20%,以及?random_state=42
?作為隨機種子。通過?x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
?得到劃分后的數據集,并打印出訓練集的形狀,以便了解數據的維度信息,用于后續模型參數的設置。
三、模型搭建
我們定義了一個自定義的 RNN 模型類,繼承自?torch.nn.Module
。在?__init__
?方法中:
- 首先調用父類的初始化方法?
super().__init__()
,確保模型的基礎結構正確初始化。 - 接著創建兩個 RNN 層,第一個?
self.rnn1
?的輸入大小根據訓練數據的特征維度確定,即?input_size=x_train.shape[2]
,這里?x_train.shape[2]
?表示輸入數據的特征數量,隱藏層大小設為 128,并且設置?batch_first=True
,使輸入張量的批次維度在第一維,方便與后續的數據加載器等組件配合;第二個?self.rnn2
?的輸入大小為第一個 RNN 層的隱藏層大小 128,隱藏層大小設為 256,同樣設置?batch_first=True
。 - 最后定義一個線性層?
self.linear
,將第二個 RNN 層的輸出映射到預測的股票價格維度,其輸入特征數量為 256,輸出特征數量為 1。
在?forward
?方法中:
- 輸入數據?
x
?首先經過第一個 RNN 層?self.rnn1
,得到輸出?x
?和隱藏狀態?y
,由于在這個預測場景中我們不需要關注隱藏狀態,所以直接忽略?y
,即?x, _ = self.rnn1(x)
。 - 接著?
x
?再經過第二個 RNN 層?self.rnn2
,同樣忽略隱藏狀態,x, _ = self.rnn2(x)
。 - 最后將經過兩層 RNN 處理后的?
x
?的最后一個時間步的輸出(也就是?x[:, -1, :]
)傳入線性層?self.linear
,得到最終的預測結果并返回。
四、模型訓練
- 實例化模型:創建?
RNN
?模型的實例,即?model = RNN()
。 - 定義損失函數:選用均方誤差損失函數(MSELoss)來衡量模型預測值與真實值之間的差異,
loss_fn = torch.nn.MSELoss()
。這是因為在預測股票價格這種連續值的任務中,均方誤差能夠很好地反映預測的準確性。 - 定義優化器:使用 Adam 優化器來更新模型的參數,指定學習率為 0.01,通過?
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
?完成定義。Adam 優化器在實際應用中表現出良好的收斂性能,能夠自適應地調整學習率,使得模型訓練更加高效。 - 訓練循環:設置訓練的輪數為 1000,在每一輪訓練中:
- 首先使用?
optimizer.zero_grad()
?清空上一輪訓練的梯度信息,確保每一輪的梯度計算都是基于當前輪次的輸入數據。 - 然后將訓練數據?
x_train
?傳入模型,得到預測輸出?h = model(x_train)
,并使用?loss_fn
?計算預測值與真實值?y_train
?之間的損失。 - 接著調用?
loss.backward()
?進行反向傳播,計算模型參數的梯度。 - 最后使用?
optimizer.step()
?根據計算得到的梯度更新模型參數,并將當前輪次的損失值添加到損失列表?loss_list
?中。為了便于觀察訓練過程,每 100 個輪次打印一次損失值,如?if (epoch + 1) % 100 == 0: print(f'Epoch [{epoch + 1}/{num_epoch00}, Loss: {loss.item():.4f}')
。
- 首先使用?
五、模型預測與可視化
- 預測測試集:訓練完成后,將測試集數據?
x_test
?傳入模型,得到預測結果?predictions = model(x_test).squeeze()
,這里的?squeeze
?操作是為了去除可能存在的多余維度,使預測結果的維度與真實值?y_test
?相匹配。 - 繪制預測結果:使用?
matplotlib
?庫繪制預測結果和真實結果的對比圖。首先創建一個新的繪圖窗口,設置合適的圖幅大小,如?plt.figure(figsize=(10, 6))
。然后分別繪制預測值和真實值的折線圖,用紅色表示預測值?plt.plot(predictions.detach().numpy(), c='r', label='Prediction')
,綠色表示真實值?plt.plot(y_test.detach().numpy(), c='g', label='Actual')
,并添加標題、坐標軸標簽以及圖例,最后通過?plt.show()
?展示繪圖結果。這使得我們能夠直觀地看到模型預測的股票價格與實際價格的接近程度,評估模型的性能。 - 繪制損失曲線:為了進一步了解模型訓練過程中的收斂情況,我們還繪制了訓練損失隨輪次變化的曲線。同樣創建一個新的繪圖窗口,繪制損失列表?
loss_list
?中的值,用藍色表示訓練損失?plt.plot(loss_list, c='b', label='Training Loss')
,添加相應的標題、坐標軸標簽和圖例,最后展示繪圖結果。通過觀察損失曲線,我們可以判斷模型是否收斂,以及收斂的速度如何,為后續模型的優化提供參考。
通過以上完整的步驟,我們成功地利用 RNN 模型對股票價格進行了預測,并通過可視化手段直觀地展示了預測結果和訓練過程。當然,這只是一個簡單的示例,在實際應用中,還可以進一步優化模型結構、調整參數、增加更多的數據特征等,以提高預測的準確性。希望這個項目能夠為你在深度學習應用于金融領域的探索中提供一些幫助!