lstm原理_TF2.0SimpleRNN,LSTM长短期记忆网络,GRU网络的原理,实践:股价预测

引言&目录

引言:

    在 TF2.0-RNN原理和实践:循环核→循环神经网络【循环核按时间步骤打开】+字母预测实践【one-hot或Embedding】中,我们了解到了传统RNN的基本原理和组成,使用的是tf.keras.layers.SimpleRNN(),提出了SimpleRNN,tf.keras还给我们提供了另外两个可用循环层:

LSTM 

GRU 问题一:SimpleRNN的弊端在哪里?

        我们知道ht,即循环核的状态ht,表征短期记忆,他是按照时刻更新的,从理论上来说,在时刻t,它应该能够记住许多时间步之前见过的信息,但实际上是不可能学到这种长期依赖。simpleRNN可以通过记忆体实现短期长短记忆进行连续数据的预测,但是当连续数据的序列变长时,会使展开时间步过长, 在反向传播更新参数时,梯度要按照时间步连续相乘,会导致梯度消失!

    于是在1997年Hochereiter和Schmidhuber提出了LSTM长短期记忆网络——LSTM[ Long Short-Term Memory],这是研究梯度消失问题的重要成果。2014年有学者在LSTM的基础上发展出了GRU。 问题二:LSTM的原理是什么?—Ⅲ

问题三:GRU的原理是什么?—Ⅳ

ps:

本文结合股票开盘价格预测实践使用了SimpleRNN,LSTM,GRU,因此先介绍实践背景

,因为只是model发生了改变,也先介绍数据的处理。

目录:

Ⅰ.实践背景介绍——股票价格预测 Ⅱ.数据处理部分——以SimpleRNN搭建模型 Ⅲ.LSTM长短期记忆网络的原理,及实验结果 Ⅳ.GRU的原理,及实验结果

    【数据获取和代码在文中partⅡ全有,后续只需修改model】

一、实践背景介绍——股票价格预测

实践目标:预测股票开盘价

实践数据:茅台股票2426天的开盘价(即open)数据

数据获取:直接通过第三方接口获取

# 通过Tushare获得股票价格数据,存到csv文件中import tushare as tsimport matplotlib.pyplot as pltdf1 = ts.get_k_data('600519',ktype='D',start='2010-04-26',end='2020-04-26')datapath1 = './SH600519.csv'df1.to_csv(datapath1)

数据概况:

e37984f8ea78ec7e337eb07ed10632d8.png

...

24ce653c1b3c3af97e6e10305345a84f.png

实践方式:共2426天的数据,

   ①划分训练集和测试集

      训练集trainning_set:前(2426-300)个样本

      测试集test_set:后300个样本

   ②使用前60天的开盘价预测第61天的开盘价

      对于测试集:就有 2126-60 =2066组训练数据

      对于训练集:就有 300-60 = 240组训练数据

   ③定义模型,进行训练,可视化

实践使用模型:

      传统循环网络    ——SimpleRNN

      长短期记忆网络 ——LSTM

      简化了的LSTM  ——GRU

实践结果:

c957f5f2e157ba2276e7d452d913e859.png

二.实验数据的预处理等内容——以SimpleRNN为例子,后不再单独写SimpleRNN

 1.获得数据

# 通过Tushare获得股票价格数据,存到csv文件中import tushare as tsimport matplotlib.pyplot as pltdf1 = ts.get_k_data('600519',ktype='D',start='2010-04-26',end='2020-04-26')datapath1 = './SH600519.csv'df1.to_csv(datapath1)

938a5064cd18b5fb53ae3dcca0397b6a.png

2.训练集和测试集归一化和划分等处理:

# 共2427行,2426个样本,只使用每天开盘价格第[2:3]列# 将前(2426-300)个样本作为训练集# 后300个样本做测试集training_set = maotai.iloc[0:2426 - 300, 2:3].valuestest_set = maotai.iloc[2426 - 300:, 2:3].values# 归一化# 定义归一化:归一化到(0,1)之间sc = MinMaxScaler(feature_range=(0, 1))# 求得训练集的固定属性:最大值,最小值。并对训练集进行归一化#fit_transform是fit和transform的组合,既包括了训练又包含了转换。#transform()和fit_transform()二者的功能都是对数据进行某种统一处理#(比如标准化~N(0,1),将数据缩放(映射)到某个固定区间,归一化,正则化等)training_set_scaled = sc.fit_transform(training_set) # 用定义的归一化和训练集的属性对测试集也进行归一化test_set = sc.transform(test_set)# 建立空列表分别用于接收训练集输入特征,训练集标签,测试集输入特征,测试集标签x_train = []y_train = []x_test = []y_test = []# 训练集和测试集划分# 上面的到训练集:csv表格中的前2126天的数据 # 第61天的数据作为对应标签y_train,# 一共生成 2126-60 = 2066组训练数据# 遍历整个训练数据,每连续60天数据作为输入特征x_train,使用的是已经for i in range(60, len(training_set_scaled)):     # 每60天作为训练数据x_train    x_train.append(training_set_scaled[i - 60:i, 0])     # 第61天数据作为对应标签y_train    y_train.append(training_set_scaled[i, 0])#打乱x_trainnp.random.seed(7)np.random.shuffle(x_train)np.random.seed(7)np.random.shuffle(y_train)tf.random.set_seed(7)# 将列表格式转换为arrayx_train, y_train = np.array(x_train), np.array(y_train)#RNN所需格式#[样本个数,循环核时间展开步数,每个时间步输入特征个数]# 样本个数:每次输入的是60天的,x_train中有2066组,# 循环核时间展开步数:输入60天即60时间步# 每个时间步输入特征个数:只输入开盘价 为1x_train = np.reshape(x_train, (x_train.shape[0], 60, 1))# 测试集:300-60 =240组for i in range(60, len(test_set)):    x_test.append(test_set[i - 60:i, 0])    y_test.append(test_set[i, 0])x_test, y_test = np.array(x_test), np.array(y_test)x_test = np.reshape(x_test, (x_test.shape[0], 60, 1))

3.建模:以SimpleRNN为例子

# 建模model = tf.keras.Sequential([    # 第一层循环计算层:记忆体80个,每个时间步推送ht给下一层    SimpleRNN(80,return_sequences = True),    Dropout(0.2),    # 最后一个循环计算层 都用False ,其之前的每一个都设置为T    SimpleRNN(100),    Dropout(0.2),    # 因输出值是第61天的开盘价,只有一个值,所以Dense是1    Dense(1)])

4.训练,模型存储,参数存储:

# 优化器adam ,损失函数:均方误差[回归常用]# 该应用只关注Loss值,不关注准确值,所以没有输入metrics选项,只显示loss值model.compile(optimizer=tf.keras.optimizers.Adam(0.001),              loss='mean_squared_error')              checkpoint_save_path = "./checkpoint/rnn_stock.ckpt"if os.path.exists(checkpoint_save_path + '.index'):    print('-------------加载模型----------------')    model.load_weights(checkpoint_save_path)    cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,                                                 save_weights_only=True,                                                 save_best_only=True,                                                 monitor='val_loss')history = model.fit(x_train, y_train, batch_size=64, epochs=50, validation_data=(x_test, y_test), validation_freq=1,                    callbacks=[cp_callback])model.summary()# 参数提取file = open('./weights.txt', 'w')  for v in model.trainable_variables:    file.write(str(v.name) + '\n')    file.write(str(v.shape) + '\n')    file.write(str(v.numpy()) + '\n')file.close()

8713acd29d3cfd4feb08c0880e6fcb4b.png

5.loss可视化

plt.rcParams['font.sans-serif'] = ['SimHei']loss = history.history['loss']val_loss = history.history['val_loss']plt.plot(loss, label='训练集损失')plt.plot(val_loss, label='测试集损失')plt.title('训练集和测试集的损失')plt.legend()plt.show()

65d700e1d58bb690343e33c4ad302377.png

6.预测——归一化还原

# 预测# 测试集输入模型进行预测predicted_stock_price = model.predict(x_test)# 对预测数据还原---从(0,1)反归一化到原始范围predicted_stock_price = sc.inverse_transform(predicted_stock_price)# 对真实数据还原---从(0,1)反归一化到原始范围real_stock_price = sc.inverse_transform(test_set[60:])# 画出真实数据和预测数据的对比曲线plt.plot(real_stock_price, color='red', label='茅台股票价格')plt.plot(predicted_stock_price, color='blue', label='预测出的茅台股票价格')plt.title('茅台股票价格预测')plt.xlabel('时间')plt.ylabel('茅台股票价格')plt.legend()plt.show()

e5c6bd72c15d575c4695da37b51c6763.png

7.评价——误差

# 评价:误差越小越好# MSE 均方误差 ---> E[(预测值-真实值)^2] (预测值减真实值求平方后求均值)mse = mean_squared_error(predicted_stock_price, real_stock_price)# RMSE 均方根误差--->sqrt[MSE]    (对均方误差开方)rmse = math.sqrt(mean_squared_error(predicted_stock_price, real_stock_price))#  MAE 平均绝对误差----->E[|预测值-真实值|](预测值减真实值求绝对值后求均值)mae = mean_absolute_error(predicted_stock_price, real_stock_price)print('均方误差: %.6f' % mse)print('均方根误差: %.6f' % rmse)print('平均绝对误差: %.6f' % mae)

8de4e50d5c51e65a176fb3113be00e9a.png

3.LSTM的原理与实现

 1997年提出了长短记忆网络LSTM: 通过门控单元改善了RNN长期依赖问题 一.原理: 提出了三个 门限 :       输入门it,遗忘门ft,输出门ot 引入了 表征长期记忆 细胞态 :     Ct 引入了 等待存入长期记忆 候选态 :     Ct~ 

0d3fde02071267504ba855d384022148.png

①三个门限:

都是当前时刻的输入特征xt和上一个时刻的短期记忆ht-1的函数。 Wi,Wf,Wo是待训练参数矩阵,bi,bf,bo是待训练偏置项。 都经过sigmoid激活函数,使得门限的范围在0~1之间

②细胞态Ct:表示长期记忆

等于 上个时期的长期记忆* 遗忘门ft,加上当前时刻归纳出的新知识*输入门

③记忆体ht:表示短期记忆

长期记忆的一部分,是 细胞态经tanh激活函数* 输入门的结果

④候选态:表示归纳出的带存入细胞态的新知识

当前的输入特征xt上个时刻的短期记忆ht-1的函数,Wc是带训练参数矩阵,bc是待训练偏置项

ok,我们可以这么理解: 

 假设, 今天我学了10页PPT的内容,从第1页到第10页,此时此我正在学习第10页。我假设我学习一页PPT代表一个时刻,学到第10页,我的长期记忆C10:第1页到第10页PPT的内容。这个长期记忆由两部分组成:

b434484231c76395bf2aa1a547ebab23.png

  ①一部分是:PPT第1页到第9页的内容,就是上一时刻长期记忆C9细胞态,我不可能一字不差的记住了前9页的内容,我会不自觉的忘掉一些知识,所以这时候遗忘门就是对我的记住的知识打了个折扣,上一时刻我的长期记忆C9*遗忘门ft,C9*ft:就表示过去真正我能记住的9页PPT里内容的知识。 ②另一部分是:我现在看的第10页PPT是新知识,是即将存在我脑中的现在的记忆,现在的记忆由两部分组成,看下图候选态公式,:1)正在看的第10页PPT,就是当前时刻输入x10 ,2)第9页PPT的短期记忆留存h9。我的大脑将会把当前时刻的输入xt和上一时刻的短期记忆h9,归纳形成即将存入我脑中的现在的记忆C10~。现在的记忆C10~*输入门it:C10~*it。 5875622583f9e59dd73e2983decc231e.png 现在的记忆*输入门+过去的记忆→一同存储为长期记忆

当我把今天学习到的知识,分享给别的同学的时候,我就在输出了!我肯定不能做到一字不落的讲出来,我讲的东西一定是我的长期记忆C10经过输出门Ot筛选后的内容,就好比我在写文章总结内容给同学分享。这就是记忆体的输出h10。

e5c5ff006c08aeeb6cef238aae2efbe8.png

当我们有多层循环网络的输出时,第二层循环网络的输入x2就是第一层循环网络的输出h1,输入给第二层网络的是第一层网络提取出的精华,可以认为:我看的PPT就是第一层循环网络,每一页PPT都是老师从一篇论文和教材中提取出来的精华,我作为第二层循环网络,接收到的知识是老师的长期记忆经过tanh激活函数*输出门提取出的短期记忆h1。 这个例子很形象,第一遍不会太懂,可以多阅览几遍。 二.TF2.0实现:
tf.keras.layers.LSTM(记忆体个数,return_sequence =是否返回输出)
股票预测实例中,只修改了Model即可
model = tf.keras.Sequential([    LSTM(80, return_sequences=True),    Dropout(0.2),    LSTM(100),    Dropout(0.2),    Dense(1)])
实验结果:

1b0a468f9c530e2ca08210a94192f8a3.png

29f9e9503f79f483f0abd2c1da09c576.png

528b0e57a2c86c6767a4d80ffb869d58.png

460eccd683e9ff34560334302272dad9.png

4.GRU-简化了的LSTM结构

一.原理:

          GRU使记忆体ht融合了长期记忆和短期记忆

    更新门:zt

    重置门:rt

    两个门限的取值范围:0~1

    记忆体:ht =(1-zt)*ht-1 + zt*ht~

    ht包含了过去记忆ht-1和现在信息ht~

    现在信息ht~:是过去信息ht-1过重置门rt与当前输入xt共同决定、过激活函数tanh

二.TF2.0实现:

tf.keras.layers.GRU(记忆体个数,return_sequence =是否返回输出)

股票预测实例中,只修改了Model即可:

7033f476f132412d987d8db52ae65ea0.png

56b1602b145a41d740e18496790fc980.png

ebff76e4f2b39a97fb7dda896cd27819.png

aabb1fa59a57fa174044835b8c3f98e9.png


谢谢阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值