Python深度学习05——Keras循环神经网络实现股价预测

 参考书目:陈允杰.TensorFlow与Keras——Python深度学习应用实战.北京:中国水利水电出版社,2021

本系列基本不讲数学原理,只从代码角度去让读者们利用最简洁的Python代码实现深度学习方法。


循环神经网络最初是用来处理文本数据的,自然语言都是时序数据,股价也是。循环神经网络可以专门用来预测时间序列数据,虽然股价预测是很难在实际中去应用,预测的也是不太准,因为股市的数据波动超级大,波动因素也不确定(还有一些别的原因下面数据处理时会介绍).....但是对于具有固定规律的时间序列数据预测还是不错的,比如天气,用电量负荷等等,本次采用Google股价数据作为循环神经网络的案例演示,别的时间序列数据也是通用。由于是预测价格,相当于是回归问题。文本数据处理起来有点麻烦,因为涉及到词向量之类,文本要处理成矩阵才能送入神经网络运算,之后会介绍文本的情感分类问题。本次就当时间序列数据的回归问题案例。

循环神经网络最经典的就是RNN,LSTM,GRU三种,三种其实用法一样,下面都会介绍。

一般来说预测效果是LSTM>=GRU>RNN。


使用循环神经网络预测Google股价

Google股价可以在雅虎财经下载,或者去同花顺亿牛网东方财富网等随便下一支A股股价数据都行,一样用。

导入包,读取数据,查看数据长什么样子

import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, Dropout,LSTM,SimpleRNN,GRU

np.random.seed(10)  # 指定乱数种子  
# 载入Google股价的训练数据集 
df_train = pd.read_csv("GOOG_Stock_Price_Train.csv",index_col="Date",parse_dates=True)
df_train

 有每天的开盘价,最高价,最低价,收盘价,除权价,成交量,我们一般采用收盘价作为股价,本次使用调整的收盘价,也就是Adj Close

数据标准化,然后分割X和y,训练集和测试集(X是前60天股价,y是第61天股价,然后滑动窗口,得到所有的X和y)

X_train_set = df_train.iloc[:,4:5].values  # Adj Close欄位
#特征标准化 - 正规化 
sc = MinMaxScaler() 
X_train_set = sc.fit_transform(X_train_set)

#取出几天前股价来建立成特征和标签数据集
def create_dataset(ds, look_back=1):
    X_data, Y_data = [],[]
    for i in range(len(ds)-look_back):
        X_data.append(ds[i:(i+look_back), 0])
        Y_data.append(ds[i+look_back, 0])
    return np.array(X_data), np.array(Y_data)
look_back = 60
print("回看天数:", look_back)

# 分割成特征数据和标签数据
X_train, Y_train = create_dataset(X_train_set, look_back)

print(X_train)

可以直接查看一下X和y的形状。由于是循环神经网络,要三维的数据输入,下面把X改为三维张量,查看形状。

# 转换成(样本数, 时步, 特征)张量  
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
print("X_train.shape: ", X_train.shape)
print("Y_train.shape: ", Y_train.shape)

 

1198为样本个数,60是时间步长,1是一个特征,即单变量,只有股价一个特征变量。预测就相当于是前60天股价预测第61天股价。


定义RNN模型

 首先使用最普通的循环神经网络——RNN

# 定义模型 
model = Sequential()
model.add(SimpleRNN(50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
model.add(Dropout(0.2))
model.add(SimpleRNN(50))
model.add(Dropout(0.2))
model.add(Dense(1))
model.summary()   # 显示模型摘要资讯  
#编译模型
model.compile(loss="mse", optimizer="adam")

#训练模型
model.fit(X_train, Y_train, epochs=100, batch_size=32)

这里堆叠了两层的RNN,每层50个神经元,训练100轮 

 RNN训练起来特别慢,下面使用LSTM(如果想用GRU,直接把所有的LSTM改成GRU就行,其他的位置不需要任何改动,很方便)

定义LSTM(GRU)模型

# 定义模型 
model = Sequential()
model.add(LSTM(50, return_sequences=True, 
               input_shape=(X_train.shape[1], 1)))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(50))
model.add(Dropout(0.2))
model.add(Dense(1))
model.summary()   # 显示模型摘要资讯  
#编译模型
model.compile(loss="mse", optimizer="adam")

#训练模型
model.fit(X_train, Y_train, epochs=100, batch_size=32)

这里堆叠了3层LSTM层,训练结果如下

 只看损失感觉很小,进一步和真实值对比

# 使用模型预测股价 - 2017年1~3月预测 4 月份股价
df_test = pd.read_csv("GOOG_Stock_Price_Test.csv")
X_test_set = df_test.iloc[:,4:5].values

# 产生标签数据
_, Y_test = create_dataset(X_test_set, look_back)

#特征数据和标准化
X_test_s = sc.transform(X_test_set)
X_test,_ = create_dataset(X_test_s, look_back)

# 转换成(样本数, 时步, 特征)张量
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
X_test_pred = model.predict(X_test)

#  将预测值转换回股价
X_test_pred_price = sc.inverse_transform(X_test_pred)

画图查看对比

#  绘出股价图表  
import matplotlib.pyplot as plt
plt.plot(Y_test, color="red", label="Real Stock Price")
plt.plot(X_test_pred_price, color="blue", label="Predicted Stock Price")
plt.title("2017 Google Stock Price Prediction")
plt.xlabel("Time")
plt.ylabel("Google Time Price")
plt.legend()
plt.show()

 看上去还不错.....但其实差的有点远,股价预测840,和真实值的830差的不多,但是真的实盘操作这10块很致命,可能就是赚钱和亏损的区别。

而且最严重的问题是,这是单步预测,即采用前60天的真实数据去预测61天的数据,下一个样本X也是用的真实数据。也就是说如果不知道真实数据的话,只能预测一步,只能预测到明天的价格,不能预测后天的价格。

当然解决办法是把预测出来的y作为下一个X放进去然后再预测,但是预测出出来的值和真实值是有差异的,X有误差了,那么估计的y也会有误差,并且滑动窗口越多,误差会累计得越来越大.....所以做长期的预测不准确的原因在这里。

当然,对于具有明显的周期性或者是趋势性的时间序列数据来说,循环神经网络的效果还是不错的,股价预测也只能是当案例看看了,只靠这种单一的价格模型去预测股价是很困难的。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阡之尘埃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值