柚子快報(bào)激活碼778899分享:rnn LSTM預(yù)測(cè)股票走勢(shì)
柚子快報(bào)激活碼778899分享:rnn LSTM預(yù)測(cè)股票走勢(shì)
前提:數(shù)據(jù)集還是之前幾篇文章的那個(gè)數(shù)據(jù)集
LSTM的應(yīng)用現(xiàn)狀
長(zhǎng)短期記憶神經(jīng)網(wǎng)絡(luò)(LSTM)是一種特殊的循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)。原始的RNN在訓(xùn)練中,隨著訓(xùn)練時(shí)間的加長(zhǎng)以及網(wǎng)絡(luò)層數(shù)的增多,很容易出現(xiàn)梯度爆炸或者梯度消失的問題,導(dǎo)致無法處理較長(zhǎng)序列數(shù)據(jù),從而無法獲取長(zhǎng)距離數(shù)據(jù)的信息。
LSTM應(yīng)用的領(lǐng)域包括:文本生成、機(jī)器翻譯、語音識(shí)別、生成圖像描述和視頻標(biāo)記等。
LSTM預(yù)測(cè)股票收盤價(jià)格
提取數(shù)據(jù)
from keras.models import Sequential
from keras.layers import LSTM, Dense
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import numpy as np
# 讀取平安銀行股票數(shù)據(jù)并將date日期作為索引
data = pd.read_csv('./000001.XSHE.csv',index_col='trade_date')
data
?
# 提取訓(xùn)練數(shù)據(jù)
new_data = data['close'] # 我們預(yù)測(cè)的是收盤價(jià),所以單獨(dú)提取出close收盤價(jià)數(shù)據(jù)
train_data = new_data[:2500] # 將股票的百分之70作為訓(xùn)練數(shù)據(jù)
#把訓(xùn)練數(shù)據(jù)轉(zhuǎn)化為列向量
train_prices = train_data.values.reshape(-1, 1)
train_prices
?
數(shù)據(jù)歸一化
歸一化的意義?
避免特征間的量綱不同帶來的影響: 當(dāng)特征的取值范圍不同時(shí),某些機(jī)器學(xué)習(xí)算法可能會(huì)因?yàn)樘卣髦档牟町惗憩F(xiàn)不佳。歸一化可以將所有特征的值都縮放到相似的范圍內(nèi),使得各個(gè)特征對(duì)模型的影響權(quán)重基本相同。
加速模型收斂: 對(duì)數(shù)據(jù)進(jìn)行歸一化可以使得優(yōu)化算法(如梯度下降法)更快收斂,因?yàn)樘卣髦迪嗨品秶鷥?nèi)的數(shù)據(jù)更容易找到全局最優(yōu)解或局部最優(yōu)解。
提高模型的精度和穩(wěn)定性: 歸一化可以減少數(shù)據(jù)范圍對(duì)模型訓(xùn)練過程的影響,提高模型的泛化能力和穩(wěn)定性。
# 數(shù)據(jù)歸一化
#Step 1: 初始化歸一化器
#feature_range=(0, 1) 參數(shù)指定了將數(shù)據(jù)縮放到 [0, 1] 的范圍內(nèi)。
scaler = MinMaxScaler(feature_range=(0, 1))
#對(duì)訓(xùn)練數(shù)據(jù)進(jìn)行擬合和轉(zhuǎn)換
#scaler.fit(train_prices): 這一步是擬合歸一化器,計(jì)算訓(xùn)練數(shù)據(jù) train_prices 的最小值和最大值。
#scaler.transform(train_prices): 接著,transform 方法將 train_prices 數(shù)據(jù)根據(jù)已計(jì)算的最小值和最大值進(jìn)行縮放轉(zhuǎn)換
train_scaled = scaler.fit_transform(train_prices)
train_scaled
?
創(chuàng)建訓(xùn)練數(shù)據(jù)集
# 創(chuàng)建訓(xùn)練數(shù)據(jù)集
X_train = []
y_train = []
#個(gè)樣本將由過去 30 個(gè)時(shí)間步的數(shù)據(jù)組成作為特征輸入。
timesteps = 30 # 時(shí)間步長(zhǎng)(指定了每個(gè)訓(xùn)練樣本(或者說每個(gè)輸入序列)包含的時(shí)間步數(shù)量)
for i in range(timesteps, len(train_scaled)):
#對(duì)于每個(gè) i,將 train_scaled 中從 i-timesteps 到 i-1 的數(shù)據(jù)切片取出,即過去 timesteps 個(gè)時(shí)間步的數(shù)據(jù)。
#這個(gè)數(shù)據(jù)是列向量的數(shù)據(jù),保證每個(gè)x都有timesteps 個(gè)時(shí)間步的數(shù)據(jù)
X_train.append(train_scaled[i - timesteps:i, 0])
#對(duì)于每個(gè) i,將 train_scaled 中第 i 個(gè)時(shí)間步的第一個(gè)特征值(即下一個(gè)時(shí)間步的數(shù)據(jù))添加到 y_train 中。
#這些值將作為對(duì)應(yīng)訓(xùn)練樣本的目標(biāo)輸出。
y_train.append(train_scaled[i, 0])
# 將訓(xùn)練數(shù)據(jù)轉(zhuǎn)為數(shù)組形式
X_train, y_train = np.array(X_train), np.array(y_train)
# 調(diào)整輸入數(shù)據(jù)的維度
"""
在使用 RNN 或者 LSTM 等模型時(shí),輸入數(shù)據(jù)的形狀應(yīng)為 (samples, timesteps, features)。
X_train.shape[0] 是樣本數(shù)量,X_train.shape[1] 是時(shí)間步數(shù)。
np.reshape 用來將 X_train 的形狀調(diào)整為 (samples, timesteps, 1),其中 1 表示每個(gè)時(shí)間步只有一個(gè)特征(單變量時(shí)間序列預(yù)測(cè)
"""
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
X_train
?
構(gòu)建LSTM模型
from keras.callbacks import EarlyStopping
# 構(gòu)建LSTM模型
#創(chuàng)建一個(gè)序貫?zāi)P?,即層的線性堆疊
model = Sequential()
#添加一個(gè)具有 50 個(gè) LSTM 單元的層。return_sequences=True 表示該層將返回完整的輸出序列而不僅僅是最后一個(gè)時(shí)間步的輸出。
#input_shape=(X_train.shape[1], 1) 指定輸入數(shù)據(jù)的形狀,其中 X_train.shape[1] 對(duì)應(yīng)于每個(gè)樣本的特征數(shù),這里是時(shí)間步數(shù)(timesteps),1 是每個(gè)時(shí)間步的特征數(shù)。
model.add(LSTM(50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
#添加第二個(gè)具有 50 個(gè) LSTM 單元的層,這一層默認(rèn)的 return_sequences 為 False,即默認(rèn)只返回最后一個(gè)時(shí)間步的輸出。
model.add(LSTM(50))
#Dense(1) 添加一個(gè)全連接層,輸出維度為 1,用于預(yù)測(cè)單一數(shù)值。
model.add(Dense(1))
# 編譯模型
#loss='mean_squared_error' 指定損失函數(shù)為均方誤差,適合回歸問題,用于衡量預(yù)測(cè)值與實(shí)際值之間的差距。
#optimizer='adam' 指定優(yōu)化器為 Adam,這是一種常用的隨機(jī)優(yōu)化算法,適合大多數(shù)情況。
model.compile(loss='mean_squared_error', optimizer='adam')
# 創(chuàng)建一個(gè)早停法的回調(diào)函數(shù)
#早停法(Early Stopping)是一種常用的正則化技術(shù),它的作用是幫助防止模型在訓(xùn)練過程中過擬合。早停法通過監(jiān)控驗(yàn)證集(或測(cè)試集)的性能指標(biāo),當(dāng)模型在驗(yàn)證集上的性能不再提升或開始下降時(shí),停止模型的訓(xùn)練,從而避免模型在訓(xùn)練數(shù)據(jù)上過度擬合
early_stop = EarlyStopping(monitor='val_loss', patience=10, verbose=1)
# 擬合模型
#epochs=100 指定訓(xùn)練輪數(shù),即整個(gè)數(shù)據(jù)集將被訓(xùn)練 100 次。
#batch_size=32 指定每次訓(xùn)練的樣本數(shù)目,每次更新模型的參數(shù)(權(quán)重)時(shí)使用的樣本數(shù)。
#validation_split=0.2 表示將訓(xùn)練數(shù)據(jù)的 20% 用作驗(yàn)證集。這種方法適用于沒有單獨(dú)驗(yàn)證集的情況。
history = model.fit(X_train, y_train, epochs=100, batch_size=32, validation_split=0.2, callbacks=[early_stop])
?
繪制損失曲線觀察模型是否過擬合
1. 觀察訓(xùn)練集和驗(yàn)證集損失的趨勢(shì)?
訓(xùn)練集損失和驗(yàn)證集損失的比較: 訓(xùn)練集損失:它衡量了模型在訓(xùn)練數(shù)據(jù)上的擬合情況。隨著訓(xùn)練的進(jìn)行,訓(xùn)練集損失應(yīng)該逐漸減少,直到收斂到一個(gè)穩(wěn)定的水平。 驗(yàn)證集損失:它衡量了模型在沒有見過的驗(yàn)證數(shù)據(jù)上的泛化能力。如果模型過擬合,驗(yàn)證集損失會(huì)在某個(gè)點(diǎn)開始上升,而不是繼續(xù)下降或保持穩(wěn)定。
2. 查看損失曲線圖
繪制訓(xùn)練集和驗(yàn)證集的損失曲線: 如果模型在訓(xùn)練集上表現(xiàn)良好但在驗(yàn)證集上表現(xiàn)不佳,可能存在過擬合問題。 如果兩條曲線的趨勢(shì)基本一致且損失都在減小,可能表明模型正在有效地學(xué)習(xí)。
import matplotlib.pyplot as plt
# 繪制訓(xùn)練過程中的損失曲線
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='validation')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()
?
預(yù)測(cè)分析
# 提取測(cè)試數(shù)據(jù)
test_data = new_data[2500:] # 百分之30作為測(cè)試數(shù)據(jù)
test_prices = test_data.values.reshape(-1, 1)
# 數(shù)據(jù)歸一化
test_scaled = scaler.transform(test_prices)
# 創(chuàng)建測(cè)試數(shù)據(jù)集
x_test = []
y_test = []
for i in range(timesteps, len(test_scaled)):
x_test.append(test_scaled[i - timesteps:i, 0])
y_test.append(test_scaled[i, 0])
# 將測(cè)試數(shù)據(jù)轉(zhuǎn)為數(shù)組形式
x_test, y_test = np.array(x_test), np.array(y_test)
# 調(diào)整輸入數(shù)據(jù)的維度
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
x_test
# 使用模型進(jìn)行預(yù)測(cè)
predicted_prices = model.predict(X_test)
predicted_prices
結(jié)果可視化
# 預(yù)測(cè)結(jié)果可視化
import seaborn as sns
sns.set(font='SimHei')
plt.rcParams['font.sans-serif'] = ['SimHei'] #解決中文顯示
plt.rcParams['axes.unicode_minus'] = False #解決符號(hào)無法顯示
# 反歸一化訓(xùn)練集和測(cè)試集的價(jià)格數(shù)據(jù)
#把他變化原來數(shù)字的區(qū)間
train_prices_scaled = scaler.inverse_transform(train_scaled)
test_prices_scaled = scaler.inverse_transform(test_scaled)
# 反歸一化預(yù)測(cè)結(jié)果
predicted_prices_scaled = scaler.inverse_transform(predicted_prices)
# 創(chuàng)建日期索引
test_dates = pd.to_datetime(test_data.index[timesteps:])
plt.figure(figsize=(15, 7))
plt.plot(test_dates, test_prices_scaled[timesteps:], label='平安櫻銀行股票收盤價(jià)-測(cè)試數(shù)據(jù)')
plt.plot(test_dates, predicted_prices_scaled, label='LSTM預(yù)測(cè)收盤價(jià)格')
plt.legend()
plt.show()
?總結(jié)
總的來看預(yù)測(cè)結(jié)果還是要比arima要好的。
柚子快報(bào)激活碼778899分享:rnn LSTM預(yù)測(cè)股票走勢(shì)
相關(guān)閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。