【theano-windows】学习笔记二十——LSTM理论及实现

前言

上一篇学习了RNN,也知道了在沿着时间线对上下文权重求梯度的时候,可能会导致梯度消失或者梯度爆炸,然后我们就得学习一波比较常见的优化方法之LSTM

国际惯例,参考网址:

LSTM Networks for Sentiment Analysis

Understanding LSTM Networks

简介

传统的循环神经网络RNN在梯度反传阶段,梯度信号经常被上下文连接权重矩阵乘很多次(与时间戳的数目一直),这就意味着转移矩阵的权重大小对学习过程有很大的影响。

如果权重很小(权重矩阵的最大特征值小于1),就会导致梯度消失,梯度信号变得很小,学习就会变得很慢或者停止学习了。这使得对具有长时依赖数据的学习变得困难。反之,如果权重很大(权重值大于1),就会导致梯度信号很大,造成学习发散,这通常称为梯度爆炸。

LSTM模型主要就是引入了记忆单元来减轻这些问题,一个记忆单元包含四个主要成分:输入门,自连接,遗忘门,输出门。自连接权重是1,不受任何外部干扰,记忆单元的状态从一个时间戳到另一个时间戳保持常量。门是为了模拟记忆单元间自身与环境的交互。输入门允许输入信改变记忆单元的状态或者阻止它。输出门允许记忆单元的状态影响到其它单元或者是组织它。遗忘门模拟记忆单元自身的循环连接,允许单元记住或者忘记之前的状态。

理论

下图对比的是传统RNN与具有记忆单元的LSTM的拓扑结构:

这里写图片描述
可以发现LSTM与RNN的区别在于后者多了一条线,上行线是记忆信息按时间传递,下行线是与RNN相同的隐层信息按时间传递。

这个记忆细胞的连接看着挺复杂的,虽然暂时看到记住了,但是过段时间肯定忘记,这个得理解性记忆,看看每一部分都代表什么吧,看样子这个记忆单元主要包含三个连接部分,如下图红圈所示:

这里写图片描述

接下来就对这些红圈分别理解,接下来的博文是对第二篇参考博客的翻译与理解,看原文请直接戳前言。

  • 第一部分
    决定即将通过记忆单元的信息是什么,通过一个由sigmoid层构成的遗忘门决定,此门接收的输入包含原始数据的输入与上一时刻的隐状态,计算结果即:

    ft=σ(Wfxt+Ufht1+bf)ft=σ(Wfxt+Ufht−1+bf)

    比如语言建模中,想基于之前所有的状态预测下一个词,记忆状态可能包括主语的性别,这样才能使用正确的代词(他/她),当新的主语出现,我们可能要忘记之前的主语性别。

  • 第二部分
    决定什么信息可以被存储在记忆单元中,分为两个部分:
    ①一个sigmoid层称为输入门决定将更新什么值;

    it=σ(Wixt+Uiht1+bi)it=σ(Wixt+Uiht−1+bi)

    tanh层计算新的候选值向量Ct^Ct^,这个值可以被加到状态中。下一步就是将这两个值结合起来更新状态
    Ct^=tanh(Wcxt+Ucht1+bc)Ct^=tanh⁡(Wcxt+Ucht−1+bc)

    如果按照语言建模的例子,这部分做的就是,我们想将新的主语性别加入到单元状态中,去替代想忘记的旧的主语的性别。

  • 结合第一部分和第二部分
    我们已经计算了想传递什么,以及是否去忘记它,怎么去更新状态。
    假设旧的记忆状态是Ct1Ct−1,想要更新到CtCt,之前我们已经计算了去做什么,现在我们只需要做它就行了,方法就是将ftft与旧状态相乘即可忘记那些早想忘记的事情。
    之后将it×Ct^it×Ct^加进去,这是新的候选值,并且依据对于每个状态我们所决定的更新量去缩放它。

    Ct=itCt^+ft×Ct1Ct=it∗Ct^+ft×Ct−1

    这就相当于在语言模型中,我们确实丢失了旧主语的性别信息,并且新增了我们在上一步已经决定添加的新信息。

  • 第三部分
    最后就是决定我们要输出啥。这个输出单元状态,但是需要被过滤一下。首先使用sigmoid决定哪一部分单元状态需要被输出,然后将单元状态通过tanh(将值归一化到-1至1),使用sigmoid遗忘门的输出乘以它,因此就仅仅会输出我们想要的那部分。

    otht=σ(Woxt+Uoht1+bo)=ot×tanh(Ct)ot=σ(Woxt+Uoht−1+bo)ht=ot×tanh⁡(Ct)

    还是语言建模的例子,一旦见到一个主语,就想输出相关的动词相关的信息,比如是单数还是复数,这样我们可以知道所连接 的动词形式。

总结一波,假如面试的时候,面试官让你画LSTM的结构图,怎么下手?

①首先一个框,竖着两条线分别代表输入输出,再横着两条线,一条是隐层的自连接,一条是记忆单元的信息传递。就相当于先画个RNN,然后横着添一条记忆线就行。

这里写图片描述

②画第一个单元:决定需要传递的信息,连接输入和隐层,使用sigmoid激活

这里写图片描述

③画第二个单元:更新记忆单元状态,连接输入和隐层,分别使用sigmoidtanh激活

这里写图片描述

④连接第一二个单元:第一个单元的输出与历史细胞状态做乘积,第二个单元的sigmoidtanh做乘积,然后与前一个单元做加和

这里写图片描述

⑤画第三个单元:确定输出,依旧是连接输入和隐层,使用sigmoid激活得到otot,将第一二部分更新的状态值使用tanh归一化一下与otot相乘即可得到隐层输出。

这里写图片描述

其实整个流程就是:决定更新啥,更新状态,确定输出。

实例

主要有官方提供的两个实例以及自己修改的将LSTM套入到上一篇RNN博客的序列预测中。官方实例戳这里,基本无需配置,下载那几个文件就能用了,文末我也会放网盘。

另一个实例是我自己将上一篇RNN的博客中代码替换成LSTM的理论进行序列预测,原始的Elman-RNN的循环代码如下:

def step(x_t,h_tm1):h_t=self.activation(T.dot(x_t,self.W_in)+ T.dot(h_tm1,self.W)+self.bh)y_t=T.dot(h_t,self.W_out)+self.byreturn h_t,y_t
[self.h,self.y_pred],_=theano.scan(step,sequences=self.input,outputs_info=[self.h0,None])

改成LSTM就是:

 #针对LSTM对RNN做相关改进def step(x_t,h_tm1,C_tm1):preact=T.dot(x_t,self.W_in)+ T.dot(h_tm1,self.W)+self.bhf_t=T.nnet.sigmoid(preact)i_t=T.nnet.sigmoid(preact)hatC_t=T.tanh(preact)C_t=i_t*hatC_t+f_t*C_tm1            o_t=T.nnet.sigmoid(preact)h_t=o_t*T.tanh(C_t)y_t=T.dot(h_t,self.W_out)+self.byreturn h_t,C_t,y_t        [self.h,self.C_t,self.y_pred],_=theano.scan(step,sequences=self.input,outputs_info=[self.h0,self.C0,None])

但是比较奇怪的是,实验效果竟然比RNN差点,不知道为什么,难道还要改其它地方?或者此处改的有问题,python渣躲墙角持续检查代码.png

这里写图片描述

后记

没啥说的,贴代码吧:

官方代码链接:https://pan.baidu.com/s/1cxTyVWBVM9L3iuGz_OkLZQ 密码:ntp0

本博文代码:链接:https://pan.baidu.com/s/1IBy8ue8lT3cjXOEnQUf_8Q 密码:k0zw

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246613.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

刚体运动学——欧拉角、四元数、旋转矩阵

前言 刚体运动旋转一般用:欧拉角、四元数、轴角对等表示,在对某个坐标旋转的时候,只需将欧拉角或四元数转换为旋转矩阵,并与原始坐标相乘,便可得到旋转以后的坐标。这里主要看看欧拉角、四元数和旋转矩阵。 国际惯例…

刚体运动学-四元数插值

前言 之前对写了一篇关于刚体运动学相关知识博客:刚体运动学——欧拉角、四元数、旋转矩阵,本篇博客就举例来说明,如何在运动捕捉数据中进行四元数插值。 国际惯例,参考博客: 探讨:向量(方向…

【TensorFlow-windows】学习笔记一——基础理解

前言 因为Theano已经停止更新了,所以在前面学完Theano搭建RBM,CNN,RNN相关结构以后,还是得选择一个主流框架的,由于我自身的学习最终是向强化学习靠近,可能用到的仿真环境是openai gym,所以选择了继续学习TensorFlow&…

【TensorFlow-windows】学习笔记二——低级API

前言 上一篇博客初步了解了tensorflow中建立机器学习模型的方法:可以使用eager execution和graph execution两种模式,可以使用高级API estimator中已经封装好的模型,也可以自己创建estimator,更重要的是我们也可以使用低级API自行…

【TensorFlow-windows】学习笔记三——实战准备

前言 因为学习TensorFlow的内容较多,如果只看API会很无聊,可以结合实例去学习。但是在构建基本的模型之前,需要学一些准备知识:数据读取、预处理、优化器、损失函数 国际惯例,参考网址: TensorFlow中文社…

【TensorFlow-windows】学习笔记四——模型构建、保存与使用

前言 上一章研究了一些基本的构建神经网络所需的结构:层、激活函数、损失函数、优化器之类的,这一篇就解决上一章遗留的问题:使用CNN构建手写数字识别网络、保存模型参数、单张图片的识别 国际惯例,参考博客: tenso…

【TensorFlow-windows】学习笔记五——自编码器

前言 上一篇博客介绍的是构建简单的CNN去识别手写数字,这一篇博客折腾一下自编码,理论很简单,就是实现对输入数据的重构,具体理论可以看我前面的【theano-windows】学习笔记十三——去噪自编码器 国际惯例,参考博客&…

【TensorFlow-windows】学习笔记六——变分自编码器

#前言 对理论没兴趣的直接看代码吧,理论一堆,而且还有点复杂,我自己的描述也不一定准确,但是代码就两三句话搞定了。 国际惯例,参考博文 论文:Tutorial on Variational Autoencoders 【干货】一文读懂…

【TensorFlow-windows】学习笔记七——生成对抗网络

前言 既然学习了变分自编码(VAE),那也必须来一波生成对抗网络(GAN)。 国际惯例,参考网址: 论文: Generative Adversarial Nets PPT:Generative Adversarial Networks (GANs) Generative Adversarial Nets in TensorFlow GAN原理学习笔记…

Openpose——windows编译(炒鸡简单)

前言 最近准备看看rtpose的代码,发现已经由openpose这个项目维护着了,由于经常在windows下调试代码,所以尝试了一下如何在windows下编译openpose源码,整体来说非常简单的。 国际惯例,参考博客: [OpenPos…

【TensorFlow-windows】学习笔记八——简化网络书写

前言 之前写代码的时候都要预先初始化权重,还得担心变量是否会出现被重复定义的错误,但是看网上有直接用tf.layers构建网络,很简洁的方法。 这里主要尝试了不预定义权重,是否能够实现正常训练、模型保存和调用,事实证…

强化学习——Qlearning

前言 在控制决策领域里面强化学习还是占很重比例的,最近出了几篇角色控制的论文需要研究,其中部分涉及到强化学习,都有开源,有兴趣可以点开看看: A Deep Learning Framework For Character Motion Synthesis and Edit…

【TensorFlow-windows】keras接口学习——线性回归与简单的分类

前言 之前有写过几篇TensorFlow相关文章,但是用的比较底层的写法,比如tf.nn和tf.layers,也写了部分基本模型如自编码和对抗网络等,感觉写起来不太舒服,最近看官方文档发现它的教程基本都使用的keras API,这…

【TensorFlow-windows】keras接口——卷积手写数字识别,模型保存和调用

前言 上一节学习了以TensorFlow为底端的keras接口最简单的使用,这里就继续学习怎么写卷积分类模型和各种保存方法(仅保存权重、权重和网络结构同时保存) 国际惯例,参考博客: 官方教程 【注】其实不用看博客,直接翻到文末看我的c…

【TensorFlow-windows】keras接口——BatchNorm和ResNet

前言 之前学习利用Keras简单地堆叠卷积网络去构建分类模型的方法,但是对于很深的网络结构很难保证梯度在各层能够正常传播,经常发生梯度消失、梯度爆炸或者其它奇奇怪怪的问题。为了解决这类问题,大佬们想了各种办法,比如最原始的…

【TensorFlow-windows】keras接口——卷积核可视化

前言 在机器之心上看到了关于卷积核可视化相关理论,但是作者的源代码是基于fastai写的,而fastai的底层是pytorch,本来准备自己用Keras复现一遍的,但是尴尬地发现Keras还没玩熟练,随后发现了一个keras-vis包可以用于做…

【TensorFlow-windows】投影变换

前言 没什么重要的,就是想测试一下tensorflow的投影变换函数tf.contrib.image.transform中每个参数的含义 国际惯例,参考文档 官方文档 描述 调用方法与默认参数: tf.contrib.image.transform(images,transforms,interpolationNEAREST,…

【TensorFlow-windows】扩展层之STN

前言 读TensorFlow相关代码看到了STN的应用,搜索以后发现可替代池化,增强网络对图像变换(旋转、缩放、偏移等)的抗干扰能力,简单说就是提高卷积神经网络的空间不变性。 国际惯例,参考博客: 理解Spatial Transformer…

【TensorFlow-windows】部分损失函数测试

前言 在TensorFlow中提供了挺多损失函数的,这里主要测试一下均方差与交叉熵相关的几个函数的计算流程。主要是测试来自于tf.nn与tf.losses的mean_square_error、sigmoid_cross_entry、softmax_cross_entry、sparse_softmax_cross_entry 国际惯例,参考博…

RS编码-Python工具包使用

前言 最近学习二维码相关知识,遇到了ReedSolomon编码,简称RS编码,中文名里德所罗门编码。遇到的问题是使用的工具包返回的编码是bytearray类型,而二维码是二进制01编码,所以本博客主要验证,如何将bytearra…