循环神经网络(RNN)的基本原理及LSTM的基本结构

2023-11-17

来源于课上实验,结果清晰,遂上传于此

实验环境TensorFlow1.14

该课件仅用于教学,请勿用于其他用途。

一、实验目的

学习掌握循环神经网络(RNN)的基本原理及LSTM的基本结构;

掌握利用LSTM神经元构造循环神经网络进行训练和预测时间序列。

二、实验内容

通过PC上位机连接服务器,登陆SimpleAI平台,利用python语言搭建基于LSTMRNN模型。利用RNN模型对正线曲线或余弦曲线的数值变化进行预测。所用到的数据集由学生自己利用python编写代码采样生成。目标是利用正弦曲线或者余弦曲线的前10个点的数值预测下一个点的数值。

三、实验环境

硬件:x86_64 Centos 3.10.0服务器/GPU服务器、GPUPC上位机

软件:SimpleAI实验平台、DockerUbuntu16.04镜像、python3.5tensorflow1.7, numpy1.12.1

四、实验原理

RNN是一种用于处理时序数据的神经网络模型。在传统神经网络中,模型不会关注上一时刻的处理会有什么信息可以用于下一时刻,每一次都只会关注当前时刻的处理。举个例子来说,我们想对一部影片中每一刻出现的事件进行分类,如果我们知道电影前面的事件信息,那么对当前时刻事件的分类就会非常容易。实际上,传统神经网络没有记忆功能,所以它对每一刻出现的事件进行分类时不会用到影片已经出现的信息。基于对这种时间序列关注的需求,循环神经网络应运而生。递归神经网络的结果与传统神经网络有一些不同,它带有一个指向自身的环,用来表示它可以传递当前时刻处理的息给下一时刻使用,结构如下:

其中,X_tspacer.gifuploading.4e448015.gif转存失败重新上传取消http://10.134.171.240/plugin/ueditor/themes/default/images/spacer.gif时间节点的输入,A 为模型处理部分,h_t t 时间节点的输出。为了更好地说明RNN的工作原理,可以将上图的循环网络结构展开,得到:

这样的一条链状神经网络代表了一个递归神经网络,可以认为它是对相同神经网络的多重复制,每一时刻的神经网络会传递信息给下一时刻。在本次试验中可以认为 X_i 为当前 i 时的正线曲线值,h_i 为预测的 i+1 时刻的正弦曲线值。

   不过RNN也有它自己的问题,即在当预测点与依赖的相关信息距离比较远的时候,就难以学到该相关信息。为了解决这类问题,人们发明了Long Short Term MemoryLSTM)。其结构与普通的循环神经网络的神经元结构对比如下:

 

 

 

理解LSTMs的关键就是下面的矩形方框,被称为memory block(记忆块),主要包含了三个门(forget gateinput gateoutput gate)与一个记忆单元(cell)。方框内上方的那条水平线,被称为cell state(单元状态),它就像一个传送带,可以控制信息传递给下一时刻。

下面来逐步了解LSTM的工作原理。LSTM第一步是用来决定什么信息可以通过cell state。这个决定由“forget gate”层通过sigmoid来控制,它会根据上一时刻的输出 h_(t-1) 和当前输入 x_t 来产生一个01 f_t 值,来决定是否让上一时刻学到的信息 C_(t-1) 通过或部分通过。如下:

举个例子来说就是,我们在之前的句子中学到了很多东西,一些东西对当前来讲是没用的,可以对它进行选择性地过滤。

第二步是产生我们需要更新的新信息。这一步包含两部分,第一个是一个“input gate”层通过sigmoid来决定哪些值用来更新,第二个是一个tanh层用来生成新的候选值 C_t,它作为当前层产生的候选值可能会添加到cell state中。我们会把这两部分产生的值结合来进行更新。

最后一步是决定模型的输出,首先是通过sigmoid层来得到一个初始输出,然后使用tanh C_t 值缩放到-11间,再与sigmoid得到的输出逐对相乘,从而得到模型的输出。

实验步骤

 

提示:实验步骤中给出的代码不是按照代码顺序给出,请结合代码截图中的行号进行实验。

1、启动jupyter

2、新建子目录log/sin文件夹和log/cos文件夹。这两个文件夹将用于存储训练好的RNN模型目录结构如下图所示:

3、新建python文件,rnnPredict.py进行模型编写,引入需要的包

4、定义主函数,首先进行数据集的创建,首先利用numpy工具包进行正弦值或者余弦值序列的生成,并划分训练集和测试集的范围。

5、编写采样函数对正弦曲线值或者余弦曲线值进行采样。每11个采样点为一组数据,其中前10个为输入数据(x),最后一个为预测数据(label)。

同时定义辅助函数用于获取数据以及计算MSE

随后在主函数中调用采样函数生成训练集(x,y)对和测试集(x,y)对。

6、编写RNN模型,首先对超参数进行定于。在三个参数分别代表超参数变量名称、默认值、参数含义描述。需要特别注意的两个参数是model_statedebuggingmodel_state控制模型是训练状态还是预测状态,训练状态将进行反向传播进行优化,预测状态只会前向传播进行预测。debugging参数用于控制是否删除当前保存的模型,debuggingTrue即为重新训练,为False则读取原有模型继续训练。

7、创建模型类,名为RNN,编写初始化函数。定义输入x和真实标签y

8、编写RNN模型定义函数。

9、编写优化操作,用于模型训练。

10、编写模型创建函数,该函数为class对外界的接口,用于创建模型图对象。

11、至此RNN模型定义完毕,回到主函数定义模型训练过程。首先创建RNN对象实体并调用build_net函数构建模型图。

12、创建session对象。

13、定义训练过程和预测过程。主要区别是在sess.run函数中,预测阶段不需要调用rnn_model.train_op这个operation,即无需优化损失函数。

将模式改为训练,运行程序

训练过程输出如下图所示,每10次优化输出一次当前损失函数值,当损失函数值不再下降时则应停止训练。

再将参数改为预测运行程序

预测阶段输出如下图所示将显示预测结果的平均MSE值。

最后也可以将预测结果可视化。查看预测效果。示范预测结果如下图所示,蓝色线为真实值,红色线为预测值。

为了真切的看到差别,将曲线图放大,如下所示,可以看到虽然预测的很接近,但还是存在一定的偏差。

六、扩展实验

以上是利用单层RNN使用10个连续的正弦函数值或者余弦函数值来预测第11个值的实验。在扩展实验中,(1)使用GRU网络与LSTM网络进行比较。(2)使用多层RNN来进行进行预测,将预测的MSE值结果与单层模型的MSE值进行对比分析。

import os
import shutil
import tensorflow as tf
import numpy as np
from sklearn.utils import shuffle
import matplotlib.pyplot as plt

FLAGS = tf.flags.FLAGS

tf.app.flags.DEFINE_integer("train_samples_num", 1000, "number of point in the train dataset")
tf.app.flags.DEFINE_float("sample_gap", 0.01, "the interval of sampling")
tf.app.flags.DEFINE_integer("layer_num", 3, "number of lstm layer")
tf.app.flags.DEFINE_integer("test_samples_num", 1000, "number of point in the test dataset")
tf.app.flags.DEFINE_integer("units_num", 128, "number of hidden units of lstm")
tf.app.flags.DEFINE_integer("epoch", 50, "epoch of training step")
tf.app.flags.DEFINE_integer("batch_size", 64, "mini_batch_size")
tf.app.flags.DEFINE_integer("max_len", 10, "use ten point to predict the value of 11th")
tf.app.flags.DEFINE_enum("model_state", "predict", ["train", "predict"], "model state")
tf.app.flags.DEFINE_boolean("debugging", False, "delete log or not")
tf.app.flags.DEFINE_float("lr", 0.01, "learning rate")
tf.app.flags.DEFINE_enum("function", "cos", ["sin", "cos"], "select sin function or cosing function")

class RNN(object):
    def __init__(self):
        self.x = tf.placeholder(dtype=tf.float32, shape=[None, FLAGS.max_len])
        self.y_ = tf.placeholder(dtype=tf.float32, shape=[None])
        self.global_step = tf.train.create_global_step()
        self.input = tf.expand_dims(input=self.x, axis=-1)      # [batch_size, seq_len, dim_size]

    def build_rnn(self):
        with tf.variable_scope("lstm_layer"):
            cells = tf.contrib.rnn.MultiRNNCell(
                [tf.contrib.rnn.BasicLSTMCell(FLAGS.units_num) for _ in range(FLAGS.layer_num)])
            # cells = tf.contrib.rnn.MultiRNNCell(
            #     [tf.contrib.rnn.GRUCell(FLAGS.units_num) for _ in range(FLAGS.layer_num)])

            outputs, final_states = tf.nn.dynamic_rnn(cell=cells, inputs=self.input, dtype=np.float32)
            self.outputs = outputs[:, -1]

        with tf.variable_scope("output_layer"):
            self.predicts = tf.contrib.layers.fully_connected(self.outputs, 1, activation_fn=None)
            self.predicts = tf.reshape(tensor=self.predicts, shape=[-1])

    def build_train_op(self):
        with tf.variable_scope("train_op_layer"):
            self.loss = tf.reduce_sum(tf.square(self.y_ - self.predicts))
            tf.summary.scalar(name="loss", tensor=self.loss)
            optimizer = tf.train.AdamOptimizer(learning_rate=FLAGS.lr)
            self.train_op = optimizer.minimize(self.loss, self.global_step)

    def build_net(self):
        self.build_rnn()
        self.build_train_op()
        self.merged_summary = tf.summary.merge_all()


def generate_date(seq):
    x = []
    y = []
    for i in range(len(seq) - FLAGS.max_len):
        x.append(seq[i:i + FLAGS.max_len])
        y.append(seq[i + FLAGS.max_len])
    return np.array(x, dtype=np.float32), np.array(y, dtype=np.float32)


def get_batches(X, y):
    batch_size = FLAGS.batch_size
    for i in range(0, len(X), batch_size):
        begin_i = i
        end_i = i + batch_size if (i+batch_size) < len(X) else len(X)
        yield X[begin_i:end_i], y[begin_i:end_i]


def average_mse(real, predict):
    predict = np.array(predict)
    mse = np.mean(np.square(real - predict))
    return mse


if __name__ == "__main__":
    tf.logging.set_verbosity(tf.logging.INFO)
    if FLAGS.function == "sin":
        func = lambda x: np.sin(x)
        log_dir = "log/sin/"
    else:
        func = lambda x: np.cos(x)
        log_dir = "log/cos/"
    test_start = FLAGS.train_samples_num * FLAGS.sample_gap
    test_end = (FLAGS.train_samples_num + FLAGS.test_samples_num) * FLAGS.sample_gap
    train_x, train_y = generate_date(func(np.linspace(0, test_start, FLAGS.train_samples_num, dtype=np.float32)))
    tf.logging.info(
        "train dataset has been prepared, train_x shape:{};train_y shape:{} ".format(train_x.shape, train_y.shape))
    test_x, test_y = generate_date(func(np.linspace(test_start, test_end, FLAGS.test_samples_num, dtype=np.float32)))
    tf.logging.info(
        "test dataset has been prepared, test_x shape:{};test_y shape:{} ".format(test_x.shape, test_y.shape))
    rnn_model = RNN()
    rnn_model.build_net()
    if FLAGS.debugging:
        if os.path.exists(log_dir):
            print("remove: " + log_dir)
            shutil.rmtree(log_dir)

    if FLAGS.model_state == "train":
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

    saver = tf.train.Saver()
    sv = tf.train.Supervisor(logdir=log_dir, is_chief=True, saver=saver, summary_op=None, save_summaries_secs=None,
                             save_model_secs=60, global_step=rnn_model.global_step)
    tf.logging.info("preparing or waiting for session..")
    sess_context_manager = sv.prepare_or_wait_for_session()
    tf.logging.info("Created session")
    minLoss = 1000

    with sess_context_manager as sess:
        if FLAGS.model_state == "train":
            print("----------------Enter train model----------------")
            summary_writer = tf.summary.FileWriter(log_dir)
            for e in range(FLAGS.epoch):
                train_x, train_y = shuffle(train_x, train_y)
                for xs, ys in get_batches(train_x, train_y):
                    feed_dict = {rnn_model.x: xs, rnn_model.y_: ys}
                    _, loss, step, merged_summary = sess.run(
                        [rnn_model.train_op, rnn_model.loss, rnn_model.global_step, rnn_model.merged_summary], feed_dict=feed_dict)
                    if step % 10 == 0:
                        tf.logging.info("epoch->{} step->{} loss:{}".format(e, step, loss))
                        summary_writer.add_summary(merged_summary, step)
                        if loss < minLoss:
                            minLoss = loss
                            saver.save(sess=sess, save_path=log_dir, global_step=step)

        if FLAGS.model_state == "predict":
            print("-------------------Enter train model---------------")
            results = []

            for xs, ys in get_batches(test_x, test_y):
                feed_dict = {rnn_model.x: xs, rnn_model.y_: ys}
                predicts = sess.run(rnn_model.predicts, feed_dict=feed_dict)
                results.extend(predicts.tolist())

            print(average_mse(test_y, results))
            plt.plot(test_y, color="green", label="train")
            plt.plot(results, color="red", label="test")
            plt.show()

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

循环神经网络(RNN)的基本原理及LSTM的基本结构 的相关文章

随机推荐

  • 【详解】指令系统中跳转指令与OF,SF,CF,ZF的关系

    目录 无符号跳转表示法 有符号跳转表示法 无符号跳转表示法详解 有符号跳转表示法详解 无符号跳转表示法 小于 大于等于 小于等于 大于 有符号跳转表示法 小于 大于等于 小于等于 大于 无符号跳转表示法详解 我在学习这部分的最大的困惑点就是
  • TensorboardX和Tensorboard的介绍及使用

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 一 Tensorboard是什么 conda环境安装 二 Tensorboard可供显示的内容 三 Tensorboard使用步骤 1 标量SCALARS 2 图片
  • Dubbo和Spring Cloud微服务架构对比

    Dubbo和Spring Cloud微服务架构对比 微服务架构是互联网很热门的话题 是互联网技术发展的必然结果 它提倡将单一应用程序划分成一组小的服务 服务之间互相协调 互相配合 为用户提供最终价值 虽然微服务架构没有公认的技术标准和规范或
  • 动态代理模式(实例化详解)

    简介 代理模式通常用于达到对原有系统功能进行扩充的目的 比如 你刚接手一个别人没有完成的项目 这是你不想动别人原理的代码 还需要添加新功能 这时代理模式 这时代理模式 这时代理模式会很好的帮助解决问题 代理模式分为两种 静态代理模式 动态代
  • 蓝桥杯2021年第十二届真题第一场-砝码称重

    题目 题目链接 题解 动态规划 状态定义 dp i j 表示前i个砝码是否能称出重量为j的物品 状态转移 对于第i个砝码 选和不选两种情况 对于选又可以分为放在左边和放在右边 看样例 存在加和减的情况 也就是放在左边和右边的情况 我们规定放
  • 爬虫日常-12306自动购票程序

    文章目录 前言 页面分析 代码设计 前言 hello兄弟们 最近在钻研新鲜知识 一不留神没想起来更新 今天我们顺着前面几篇文章完整的写出一篇12306的自动购票软件 首先把我们已经写完的前期步骤代码再顺一遍 from selenium we
  • IDEA常用快捷键集合(详解)

    keymap中定义的快捷键实在是太多了 全部记住几乎不可能 但在项目开发或调试的工程中 快捷键是绝对的效率工具 查询快捷键 CTRL N 查找类 CTRL SHIFT N 查找文件 CTRL SHIFT ALT N 查 找类中的方法或变量
  • msvcp140.dll缺失重新安装的方法【msvcp140.dll修复工具下载安装】

    如果您在使用某些应用程序或游戏时遇到了 msvcp140 dll丢失 的错误提示 那么您需要采取一些措施来解决这个问题 以下是几种解决msvcp140 dll丢失的方法 msvcp140 dll解决方法一 1 在浏览器顶部网页搜索 dll修
  • 【vue】实现首屏加载等待动画 避免首次加载白屏尴尬

    原文链接 在线体验 width 100 height 443 src jsfiddle net kajweb qrno8s0g 9 embedded html css result allowfullscreen allowfullscre
  • a foreign key constraint fails

    可能由两种原因导致 1 设置的外键和对应的另一个表的主键值不匹配 解决方法 找出不匹配的值修改 或者清空两表数据 2 字符集和排序规则的差异引起 如果确认外键和主键一致 使用如下方式解决 代码前段插入 SET OLD CHARACTER S
  • iOS 15 越狱情报

    关注后回复 进群 拉你进程序员交流群 作者丨小集 来源丨小集 ID zsxjtip iOS 15 正式版本已经发布了 而 iOS 15 1 beta 版本也在近期发布 在普通用户和开发者追更各个 beta 版和正式版时 另一个神秘群体也没有
  • 架构 但服务多租户_华为以AI和混合云实现多租户数据中心架构转型

    华为采用全球直播的方式以 你好 智能世界 为主题举办行业数字化转型大会 把原计划在巴塞罗那现场举办的活动时间不变 2月24日 27日 搬到线上 针对互联网服务行业数字化 专门举办的MTDC 多租户数据中心论坛 于北京时间27日开启全球线上直
  • 外包干了2个月,技术退步明显...

    先说一下自己的情况 大专生 18年通过校招进入湖南某软件公司 干了接近4年的功能测试 今年年初 感觉自己不能够在这样下去了 长时间呆在一个舒适的环境会让一个人堕落 而我已经在一个企业干了四年的功能测试 已经让我变得不思进取 谈了2年的女朋友
  • 调用halcon函数时的错误处理

    注 以下材料来自halcon帮助文档 因水平有限 难免有误 欢迎指正 0 概述 在遇到一个运行时错误时 HALCON C 会以默认的方式给出错误信息 并终止程序 然而 在某些情况下 我们并不希望按照这样的规则来处理错误 例如 当一个程序允许
  • centos7.8从卸载python2,安装python3

    因为目前所有环境都是python2 7 5 但是项目上使用的是python3 7 5 迫切需要使用python3 7 5验证 安装遇到困难 记录一下 首先卸载python2 如果不想卸载python2的可以跳过 这里卸载python2和其依
  • 信息图:iOS 7开发者需要知道的事

    如果你想为iOS 设备开发app 你需要知道如何与软件交互 如何设计 你还要知道苹果独特的开发理念和开发工具 真正的能力还需要成功地从其他行业领域借鉴核心概念 最后把所有这些东西糅合进你的信息库中 所以我们画了一张iOS 7开发者应该的知识
  • iOS开发:使用大图+脚本,生成各种size的app icon和图片素材

    美术UI在公司是宝贵的资源 集各种项目宠爱于一身 为了努力完成好老板的进度需求 不给UI添麻烦 程序员开始忙活了 在iOS里面 我们使用image assert来管理素材和app icon 为什么呢 因为方便 按照image assert要
  • 怎样在前端遍历后端服务器传递来的json字符串中的集合?

    怎样在前端遍历后端服务器传递来的json字符串中的集合 后端把一个List类型的集合先转换成json字符串然后返回给通过ajax返回给前端 如下图 后端服务器中的代码如下图 紧着着前端页面遍历 后端传递来的json字符串中的集合数据 先来看
  • 读论文(二) - BERT

    Introduction 预训练的语言模型 在改进自然语言处理任务方面非常有效 包括句子级别的任务 自然语言推理和释义 也包括分词级别的任务 NER和问答 将预训练的语言表示应用于下游任务有两种现有策略 基于特征 feature based
  • 循环神经网络(RNN)的基本原理及LSTM的基本结构

    来源于课上实验 结果清晰 遂上传于此 实验环境TensorFlow1 14 该课件仅用于教学 请勿用于其他用途 详细参考 实验笔记 实验视频 一 实验目的 学习掌握循环神经网络 RNN 的基本原理及LSTM的基本结构 掌握利用LSTM神经元