【TensorFlow实战】LSTM原理及实现,进行海表温度及股价预测

本文简单介绍了LSTM网络原理,并展示了LSTM网络的TensorFlow实现,进行了海表温度及股价预测的实验。源代码见https://github.com/Su-Lemon/lstm-master

获取更多内容,请访问博主的个人博客 爱吃猫的小鱼干的Blog

一 引言

LSTM 是一种RNN特殊的类型, 可以避免常规RNN的梯度消失问题,用来处理长序列的数据。LSTM 通过刻意的设计来避免长期依赖问题。

二 LSTM模型结构

2.1 整体结构

LSTM模型结构示意如下图所示。
LSTM结构图
每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。方框中的圆圈代表运算操作( 如向量的和) ,而中间的方框就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。

这种结构的核心思想是引入了一个叫做细胞状态的连接,这个细胞状态用来存放想要记忆的东西。

  • 忘记门:决定什么时候需要把以前的状态忘记;
  • 输入门:决定什么时候加入新的状态;
  • 输出门:决定什么时候需要把状态和输入放在一起输出。

从字面意思可以看出,简单RNN 只是把上一次的状态当成本次的输入一起输出。而LSTM 在状态的更新和状态是否参与输入都做了灵活的选择, 具体选什么,则一起交给神经网络的训练机制来训练。

2.2 忘记门

忘记门
忘记门,是控制是否遗忘的,在LSTM中即以一定的概率控制是否遗忘上一层的隐藏细胞状态。

图中输入的有上一序列的隐藏状态 h t − 1 h_{t-1} ht1和本序列数据 x t x_{t} xt,通过一个激活函数,一般是sigmoid,得到忘记门的输出 f t f_{t} ft。由于sigmoid的输出 f t f_{t} ft [ 0 , 1 ] [0,1] [0,1]之间,因此这里的输出 f t f_{t} ft代表了忘记上一层隐藏细胞状态的概率。用数学表达式即为上图右侧所示。其中 W f W_{f} Wf, U f U_{f} Uf, b f b_{f} bf为线性关系的系数和偏置, σ σ σ为sigmoid激活函数。

2.3 输入门

输入门
输入门,负责处理当前序列位置的输入。

从图中可以看到输入门由两部分组成,第一部分使用了sigmoid激活函数,输出为 i t i_{t} it第二部分使用了tanh激活函数,输出为 a t a_{t} at,两者的结果后面会相乘再去更新细胞状态。用数学表达式即为上图右侧所示。

2.4 输出门

输出门
从图中可以看出,隐藏状态 h t h_{t} ht的更新由两部分组成,第一部分是 o t o_{t} ot,它由上一序列的隐藏状态 h t − 1 h_{t-1} ht1和本序列数据 x t x_{t} xt,以及激活函数sigmoid得到,第二部分由隐藏状态 C t C_{t} Ct和tanh激活函数组成, 用数学表达式即为上图右侧所示。

三 TensorFlow搭建LSTM网络

下面展示了利用TensorFlow创建Encoder-Decoder 框架的LSTM网络的过程。完整的实验源码请前往https://github.com/Su-Lemon/lstm-master下载。

import tensorflow as tf
import numpy as np
import pandas as pd

from ..configs import config as cfg
pd.options.mode.chained_assignment = None  # default='warn'


class Net(object):
    def __init__(self):
        self.encoder_input = []
        self.expected_output = []
        self.decode_input = []
        self.losses = {}

        self.tcells = []
        self.Mcell = []
        self.reshaped_outputs = []

    def createNet(self, sess):
        for i in range(cfg.FLAGS.seq_len):
            self.encoder_input.append(
                tf.placeholder(tf.float32, shape=(None, cfg.FLAGS.input_dim)))
            self.expected_output.append(
                tf.placeholder(tf.float32, shape=(None, cfg.FLAGS.output_dim)))
            self.decode_input.append(
                tf.placeholder(tf.float32, shape=(None, cfg.FLAGS.input_dim)))

        # Create LSTM(GRU)
        for i in range(cfg.FLAGS.layers_num):
            self.tcells.append(tf.contrib.rnn.GRUCell(cfg.FLAGS.hidden_dim))
        self.Mcell = tf.contrib.rnn.MultiRNNCell(self.tcells)

        # Connected by Encoder-Decoder
        dec_outputs, dec_memory = tf.contrib.legacy_seq2seq.basic_rnn_seq2seq(
            self.encoder_input, self.decode_input, self.Mcell)

        # Create output leyer
        for ii in dec_outputs:
            self.reshaped_outputs.append(
                tf.contrib.layers.fully_connected(ii, cfg.FLAGS.output_dim,
                                                  activation_fn=None))
        # L2 loss
        output_loss = 0
        for _y, _Y in zip(self.reshaped_outputs, self.expected_output):
            output_loss += tf.reduce_mean(tf.pow(_y - _Y, 2))
        self.losses['output_loss'] = output_loss

        # generalization capacity
        reg_loss = 0
        for tf_var in tf.trainable_variables():
            if not ("fully_connected" in tf_var.name):
                # print(tf_var.name)
                reg_loss += tf.reduce_mean(tf.nn.l2_loss(tf_var))
        self.losses['reg_loss'] = reg_loss

        loss = output_loss + cfg.FLAGS.lambda_l2_reg * reg_loss
        self.losses['loss'] = loss
        return self.losses

    def trainer(self, sess, dataset, train_op, isTrain):
        X, Y = dataset.generateData(isTrain=True)
        feed_dict = {self.encoder_input[t]: X[t] for t in range(len(self.encoder_input))}
        feed_dict.update({self.expected_output[t]: Y[t] for t in range(len(self.expected_output))})

        c = np.concatenate(([np.zeros_like(Y[0])], Y[:-1]), axis=0)
        feed_dict.update({self.decode_input[t]: c[t] for t in range(len(c))})

        if isTrain:
            _, loss_t = sess.run([train_op, self.losses['loss']], feed_dict)
            return loss_t
        else:
            output_lossv, reg_lossv, loss_t = sess.run(
                [self.losses['output_loss'], self.losses['reg_loss'],
                 self.losses['loss']],
                feed_dict)
            print("-----------------")
            print(output_lossv, reg_lossv)
            return loss_t


    def demo(self, sess, dataset):
        X, Y = dataset.generateData(isTrain=False)
        feed_dict = {self.encoder_input[t]: X[t] for t in range(cfg.FLAGS.seq_len)}
        c = np.concatenate(
            ([np.zeros_like(Y[0])], Y[0:cfg.FLAGS.seq_len - 1]), axis=0)
        feed_dict.update(
            {self.decode_input[t]: c[t] for t in range(len(c))})
        outputs = np.array(sess.run([self.reshaped_outputs], feed_dict)[0])
        return outputs

部分地区海表温度预测结果:
在这里插入图片描述
2018全球海表温度热力图:
在这里插入图片描述

获取更多内容,请访问博主的个人博客 爱吃猫的小鱼干的Blog

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您介绍如何使用Tensorflow实现LSTM溶解氧预测。 首先,您需要准备数据集。数据集应该包含时间序列数据和对应的溶解氧值。您可以使用历史数据集进行训练和验证,也可以使用实时数据进行预测。确保数据集已经被处理成适合LSTM模型的格式。 接下来,您需要导入Tensorflow库并定义模型。在这种情况下,我们将使用LSTM模型进行预测。以下是一个基本的LSTM模型示例: ```python import tensorflow as tf model = tf.keras.Sequential([ tf.keras.layers.LSTM(64, input_shape=(time_steps, features)), tf.keras.layers.Dense(1) ]) ``` 在这里,我们定义了一个具有一个LSTM层和一个密集层的序列模型。LSTM层的输出形状为(batch_size,64),输入形状为(time_steps,features),其中time_steps是时间步长,features是特征数。密集层有一个神经元,用于输出预测值。 接下来,我们需要编译模型并设置损失函数和优化器: ```python model.compile(loss='mse', optimizer='adam') ``` 在这里,我们使用均方误差(MSE)作为损失函数,并使用Adam优化器进行优化。 接下来,我们可以使用fit方法训练模型: ```python model.fit(X_train, y_train, epochs=100, validation_data=(X_val, y_val)) ``` 在这里,我们将训练数据集(X_train,y_train)用于模型训练,并使用验证数据集(X_val,y_val)进行验证。 最后,我们可以使用predict方法进行预测: ```python y_pred = model.predict(X_test) ``` 在这里,我们使用测试数据集进行预测,并将预测结果存储在y_pred中。 这就是使用Tensorflow实现LSTM溶解氧预测的基本步骤。请注意,这只是一个基本示例,您可以根据需要进行更改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值