精华内容
下载资源
问答
  • 在实际应用中,所谓深度神经网络DNN,往往融合了多种已知结构,包括卷积层或是LSTM单元。但是就题主意思来看,这里DNN应该特指全连接神经元结构,并不包含卷积单元或是时间,上关联。因此,题主一定要将...
    5c86e196887a34c63bedc750db9172fa.gif首先,我感觉不必像@李Shawn同学-样认为DNN、CNN、RNN完全不能相提并论。从广义上来说,NN (或是更美的DNN)确实可以认为包含了CNN、RNN这些具体的变种形式。在实际应用中,所谓的深度神经网络DNN,往往融合了多种已知的结构,包括卷积层或是LSTM单元。但是就题主的意思来看,这里的DNN应该特指全连接的神经元结构,并不包含卷积单元或是时间,上的关联。因此,题主一定要将DNN、CNN、RNN等进行对比,也未尝不可。其实,如果我们顺着神经网络技术发展的脉络,就很容易弄清这几种网络结构发明的初衷,和他们之间本质的区别,希望对题主有所帮助。其实,如果我们顺着神经网络技术发展的脉络,就很容易弄清这几种网络结构发明的初衷,和他们之间本质的区别,希望对各位有所帮助。
    神经网络技术起源于上世纪五、六十年代,当时叫感知机(perceptron) ,拥有输入层、输出层和一个隐含层。输入的特征向量通过隐含层变换达到输出层,在输出层得到分类结果。早期感知机的推动者是Rosenblatt。(扯一 个不相关的:由于计算技术的落后,当时感知器传输函数是用线拉动变阻器改变电阻的方法机械实现的,脑补一下科学家们扯着密密麻麻导线的样...)但是,Rosenblatt的 单层感知机有一个严重得不能再严重的问题,即它对稍复杂一些的函数都无能为力(比如最为典型的“异或” 操作)。连异或都不能拟合,你还能指望这货有什么实际用途么随着数学的发展,这个缺点直到上世纪八十年代才被Rumelhart、Williams、 Hinton、 LeCun等人(反正就是一票大牛) 发明的多层感知机(multilayer perceptron)克服。多层感知机,顾名思义,就是有多个隐含层的感知机(废话.....)好好,我们看一下多层感知机的结构:60099995a66d5b8583abcd8714d74ee9.png图1上下层神经元全部相连的神经网络——多层感知机多层感知机可以摆脱早期离散传输函数的束缚,使用sigmoid或tanh等连续函数模拟神经元对激励的响应,在训练算法上则使用Werbos发明的反向传播BP算法。对,这货就是我们现在所说的神经网络NN——神经网络听起来不知道比感知机高端到哪里去了!这再次告诉我们起一个好听的名字对于研(zhuang) 究(bi) 很重要!多层感知机解决了之前无法模拟异或逻辑的缺陷,同时更多的层数也让网络更能够刻画现实世界中的复杂情形。相信年轻如Hinton当时一定是春风得意。多层感知机给我们带来的启示是,神经网络的层数直接决定了它对现实的刻画能力一利用每层更少的神经元拟合更加复杂的函数。(Bengio如是说: functions that can be compactly represented by a depth k architecture might require an exponential number of computational elements to be represented by a depth k - 1 architecture.)即便大牛们早就预料到神经网络需要变得更深,但是有一个梦魇总是萦绕左右。随着神经网络层数的加深,优化函数越来越容易陷入局部最优解,并且这个“陷阱”越来越偏离真正的全局最优。利用有限数据训练的深层网络,性能还不如较浅层网络。同时,另一个不可忽略的问题是随着网络层数增加,“梯度消失”现象更加严重。具体来说,我们常常使用sigmoid作为神经元的输入输出函数。对于幅度为1的信号,在BP反向传播梯度时,每传递一层,梯度衰减为原来的0.25。层数一多,梯度指数衰减后低层基本.上接受不到有效的训练信号。2006年,Hinton利用预训练方法缓解了局部最优解问题,将隐含层推动到了7层,神经网络真正意义上有了"深度",由此揭开了深度学习的热潮。这里的"深度”并没有固定的定义一在语音识别中4层网络就能够被认为是"较深的",而在图像识别中20层以上的网络屡见不鲜。为了克服梯度消失,ReLU、 maxout等传输函数代替了sigmoid,形成了如今DNN的基本形式。单从结构上来说,全连接的DNN和图1的多层感知机是没有任何区别的值得一提的是, 今年出现的高速公路网络(highway network)和深度残差学习(deep residual .learning)进一步避免了梯度消失,网络层数达到了前所未有的一百多层(深度残差学习: 152层)[3,4]!具体结构题主可自行搜索了解。如果你之前在怀疑是不是有很多方法打上了"深度学习"的噱头,这个结果真是深得让人心服口服。a40036ffe7b24301748057b093c32bbb.png图2缩减版的深度残差学习网络,仅有34层,终极版有152层,自行感受一下如图1所示,我们看到全连接DNN的结构里下层神经元和所有.上层神经元都能够形成连接,带来的潜在问题是参数数量的膨胀。假设输入的是- -幅像素为1K*1K的图像,隐含层有1M个节点,光这一层就有10^12个权重需要训练,这不仅容易过拟合,而且极容易陷入局部最优。另外,图像中有固有的局部模式(比如轮廓、边界,人的眼睛、鼻子、嘴等)可以利用,显然应该将图像处理中的概念和神经网络技术相结合。此时我们可以祭出题主所说的卷积神经网络CNN。对于CNN来说,并不是所有上下层神经元都能直接相连,而是通过"卷积核"作为中介。同一个卷积核在所有图像内是共享的,图像通过卷积操作后仍然保留原先的位置关系。两层之间的卷积传输的示意图如下: 3df450dcdb812331e277906ecf9b59fe.png图3卷积神经网络隐含层(摘自Theano教程)通过一个例子简单说明卷积神经网络的结构。假设图3中m-1=1是输入层,我们需要识别一幅彩色图像,这幅图像具有四个通道ARGB (透明度和红绿蓝,对应了四幅相同大小的图像),假设卷积核大小为100*100,共使用100个卷积核w1到w100 (从直觉来看,每个卷积核应该学习到不同的结构特征)。用w1在ARGB图像上进行卷积操作,可以得到隐含层的第一幅图像;这幅隐含层图像左上角第-个像素是四幅输入图像左上角100*100区域内像素的加权求和,以此类推。同理,算上其他卷积核,隐含层对应100幅"图像"。每幅图像对是对原始图像中不同特征的响应。按照这样的结构继续传递下去。CNN中还有max-pooling等操作进一步提高鲁棒性。2709312224f099351d3bfe3ec7ef635e.png图4一个典型的卷积神经网络结构,注意到最后一层实际上是一个全连接层(摘自Theano教程)在这个例子里,我们注意到输入层到隐含层的参数瞬间降低到了100*100*100=10^6个!这使得我们能够用已有的训练数据得到良好的模型。题主所说的适用于图像识别,正是由于CNN模型限制参数了个数并挖掘了局部结构的这个特点。顺着同样的思路,利用语音语谱结构中的局部信息,CNN照样能应用在语音识别中。全连接的DNN还存在着另一个问题一无法对时间序列. 上的变化进行建模。然而,样本出现的时间顺序对于自然语言处理、语音识别、手写体识别等应用非常重要。对了适应这种需求,就出现了题主所说的另一种神经网络结构——循环神经网络RNN。在普通的全连接网络或CNN中,每层神经元的信号只能向上一层传播,样本的处理在各个时刻独立,因此又被成为前向神经网络(Feed-forward Neural Networks)。而在RNN中,神经元的输出可以在下一个时间戳直接作用到自身,即第i层神经元在m时刻的输入,除了(i-1) 层神经元在该时刻的输出外,还包括其自身在(m-1) 时刻的输出!表示成图就是这样的:483df769663761ac406159455b089f7a.png图5 RNN网络结构我们可以看到在隐含层节点之间增加了互连。为了分析方便,我们常将RNN在时间上进行展开,得到如图6所示的结构:f97e901204f867178b421c6200ab6595.png图6 RNN在时间上进行展开Cool,(t+1)时刻网络的最终结果0(t+1)是该时刻输入和所有历史共同作用的结果!这就达到了对时间序列建模的目的。不知题主是否发现,RNN可以看成一个在时间上传递的神经网络,它的深度是时间的长度!正如我们.上面所说,“梯度消失”现象又要出现了,只不过这次发生在时间轴上。对于t时刻来说,它产生的梯度在时间轴上向历史传播几层之后就消失了,根本就无法影响太遥远的过去。因此,之前说"所有历史"共同作用只是理想的情况,在实际中,这种影响也就只能维持若干个时间戳。为了解决时间上的梯度消失,机器学习领域发展出了长短时记忆单元LSTM,通过[门的开关实现时间上记忆功能,并防止梯度消失,一个LSTM单 元长这个样子:4de5dd321dbc347758786e9fe3595bfc.png图7 LSTM的模样除了题主疑惑的三种网络,和我之前提到的深度残差学习、LSTM外,深度学习还有许多其他的结构。举个例子,RNN既然能继承历史信息,是不是也能吸收点未来的信息呢?因为在序列信号分析中,如果我能预知未来,对识别一定也是有所帮助的。因此就有了双向RNN、双向LSTM,同时利用历史和未来的信息。ea467f4783c42e8d53bce6e7574a161f.png图8双向RNN事实上,不论是那种网络,他们在实际应用中常常都混合着使用,比如CNN和RNN在上层输出之前往往会接.上全连接层,很难说某个网络到底属于哪个类别。不难想象随着深度学习热度的延续,更灵活的组合方式、更多的网络结构将被发展出来。尽管看起来千变万化,但研究者们的出发点肯定都是为了解决特定的问题。题主如果想进行这方面的研究,不妨仔细分析一下这些结构各自的特点以及它们达成目标的手段。

    - END -

    71aa13fe5ba592f20659c47297f3b44e.png

    8d7564a5b324c07ee68af1f1ada88823.gif

    展开全文
  • 几种主要神经网络一、全连接神经网络二、前馈神经网络(Feedforward neural network,FNN)三、卷积神经网络(Convolutional Neural Network,CNN)四、循环神经网络(Recurrent neural network,RNN ) ...

    一、全连接神经网络

    顾名思义,全连接神经网络中,对n-1层和n层而言,n-1层的任意一个节点,都和第n层所有节点有连接。即第n层的每个节点在进行计算的时候,激活函数的输入是n-1层所有节点的加权,这个激活函数是非线性的。它的缺点就是权重太多了,计算量很大。
    它可作用于大多数场景。

    二、前馈神经网络(Feedforward neural network,FNN)

    前馈神经网络采用一种单向多层结构。其中每一层包含若干个神经元。在此种神经网络中,各神经元可以接收前一层神经元的信号,并产生输出到下一层。第0层叫输入层,最后一层叫输出层,其他中间层叫做隐含层(或隐藏层、隐层)。隐层可以是一层,也可以是多层。

    • 在前馈神经网络中,不同的神经元属于不同的层,每一层的神经元可以接受到前一层的神经元信号,并产生信号输出到下一层。第0层叫做输入层,最后一层叫做输出层,中间的叫做隐藏层,整个网络中无反馈,信号从输入层到输出层单向传播,可用一个有向无环图表示。在西瓜书5.2有提及。

    三、卷积神经网络(Convolutional Neural Network,CNN)

    卷积神经网络是一种具有局部连接,权重共享等特性的深层前馈神经网络。一般是由卷积层,汇聚层,全连接层交叉堆叠而成,使用反向传播算法进行训练。其有三个结构上的特征:局部连接,权重共享以及汇聚。这些特征使得卷积神经网络具有一定程度上的平移,缩放和旋转不变性。较前馈神经网络而言,其参数更少。

    卷积神经网络的输入为二维的像素整阵列,输出为这个图片的属性,当网络训练学习后,所输入的图片或许经过稍微的变换,但卷积神经网络还是可以通过识别图片局部的特征而将整个图片识别出来。

    • 数据输入层:该层要做的处理主要是对原始图像数据进行预处理,包括去均值(把输入数据各个维度都中心化为0,其目的就是把样本的中心拉回到坐标系原点上),归一化(幅度归一化到同样的范围);
      卷积计算层:相当于滤镜,将图片进行分块,对每一块进行特征处理,从而提取特征,这是最重要的一层。具体操作还未仔细学习。
      池化层:池化层夹在连续的卷积层中间, 用于压缩数据和参数的量,减小过拟合。通过对提取的高维特征进行降维,对于输入为图像的情况,这里最主要的作用应该就是压缩。
      全连接层:对空间排列的特征化成一维的向量。

    主要应用:计算机视觉,图像和视频分析的各种任务上,比如图像分类,人脸识别,物体识别,图像分割等,其准确率也远远超过了其他的人工神经网络。近年来,卷积神经网络也应用到自然语言处理和推荐系统等领域。

    四、循环神经网络(Recurrent neural network,RNN )

    • 循环神经网络是一类具有短期记忆能力的神经网络,在循环神经网络中,神经元不仅可以接受其他神经元的信息,还可以接受自身的信息,形成一个环路结构。在很多现实任务中,网络的输出不仅和当前的输入有关,也和过去一段时间的输出相关。

    从网络结构上,循环神经网络会记忆之前的信息,并利用之前的信息影响后面结点的输出。即:循环神经网络的隐藏层之间的结点是有连接的,**隐藏层的输入不仅包括输入层的输出,还包括上一时刻隐藏层的输出。**类似于机器学习西瓜书的5.5.5介绍的Elman网络

    常用于文本填充、时间序列、语音识别等序列数据。

    展开全文
  • rnn 循环神经网络

    2019-03-17 15:29:28
    rnn 循环神经网络 创建日期 星期四 10 一月 2019 rnn为 recurrent natural network, 递归神经网络 是一种基于序列的神经网络, 序列可以是时间,文本序列等,和普通的神经网络的不同是rnn不光在层之间有权值,同一个层...

    rnn 循环神经网络

    创建日期 星期四 10 一月 2019

    rnn为 recurrent natural network, 递归神经网络 是一种基于序列的神经网络,
    序列可以是时间,文本序列等,和普通的神经网络的不同是rnn不光在层之间有权值,同一个层中每个神经元之间也有权值;
    但是这个有个缺点是只能有短期记忆,过于长的文本之间的关系可能计算不好,这里就需要lstm;

    RNN是一种可以预测未来(在某种程度上)的神经网络,可以用来分析时间序列数据(比如分析股价,预测买入点和卖出点)。在自动驾驶中,可以预测路线来避免事故。更一般的,它可以任意序列长度作为输入,而不是我们之前模型使用的固定序列长度。例如RNN可以将句子、文档、语音作为输入,进行自动翻译、情感分析、语音转文字。此外,RNN还用于作曲(谷歌Magenta项目作出的the one)、作文、图片自动生成标题。

    14.1 周期神经元(Recurrent Neurons)
    此前介绍的大部分是前馈神经网络,激活流只有一个方向,从输入层流向输出层。RNN和前馈神经网络很相似,不过也会向后连接。我们来看一个最简单的RNN,只有一个神经元接受输入,只产生一个输出,然后再将输出传递给自己,如图14-1(左侧)。在每一个time step t(也叫做一帧),循环神经元接受输入x(t)和前一步的输出y(t−1)。可以将这一神经元随时间展开

     

    创建一层循环神经元也很简单,只不过在一个time step,输入和输出都是向量

    每个神经元都有两套权重:一个用于本层输入x(t),一个用于上层输出y(t−1)。我们分别记为wx和wy。

    一个循环神经元关于一个实例的输出:

    y(t)=ϕ(xT(t)⋅wx+yT(t−1)⋅wy+b)
    其中,b是偏置项,ϕ(⋅)是激活函数,比如ReLU(许多研究者更喜欢使用hyperbolic tangent (tanh)作为RNN的激活函数。例如,可以参考Vu Pham等人的Dropout Improves Recurrent Neural Networks for Handwriting Recognition。不过,基于ReLU的RNN也是可以的,比如Quoc V. Le等人的论文A Simple Way to Initialize Recurrent Networks of Rectified Linear Units。)。

    一层循环神经元关于整个mini-batch的输出:

    Y(t)=ϕ(XT(t)⋅Wx+YT(t−1)⋅Wy+b)=ϕ([X(t)Y(t)]⋅W+b)withW=[WxWy]
    Y(t)是一个m×nneurons矩阵,包含该层在time step t关于整个mini-batch实例的输出(m是mini-batch的实例数,nneurons是神经元数量)。
    X(t)是一个m×ninputs矩阵,包含该time step t所有实例的输入(ninputs是特征数)。
    Wx是一个ninputs×nneurons矩阵,包含当前time step输入到输出的连接权重。
    Wy是一个nneurons×nneurons矩阵,包含上个time step输出到当前time step输出的连接权重。
    W的形状是(ninputs+nneurons)×nneurons
    b是一个大小为nneurons的向量,包含所有神经元的偏置项。
    可以看到,Y(t)是关于X(t)和Y(t−1)的函数,Y(t−1)又是关于X(t−1)和Y(t−2)的函数,等等。这使得Y(t)其实是关于X(0),X(1),⋯,X(t)的函数。

     

    由于神经网络在第t个time step的输出是一个关于前t个time step所有输入的函数,这可以理解为一种形式的记忆(memory)。神经网络中保存前面时刻状态的部分称为memory cell(或者简单称为cell)。一个单独的周期神经元,或者一层周期神经元,就是一个很基础的cell。随后我们会看到更加复杂和强大的cell。

    一般一个cell在时刻t(姑且把time step称作时刻把,不然太麻烦)的状态,记做h(t)(“h”代表“hidden”),这是一个关于当前时刻输入和前一时刻状态的函数:h(t)=f(h(t−1),xt)。在t时刻的输出,记做y(t),这也是一个关于当前时刻输入和前一时刻状态的函数。在前面讨论的基本cell中,状态和输出是一致的,但在复杂的模型中这是不一致的
    输入和输出序列
    RNN可以一个序列作为输入,再同时输出一个序列(如图14-4左上)。该模型可用于股价预测,输入前N天的股价,输出每一天的股价,知道第N+1天。每增加一天的输入,就预测下一天的输出。

    此外,还可以序列作为输入,忽略除了最后一个之外所有的输出(如图右上)。例如用于情感分析,可以将电影评论作为输入,输出情感分值。

    相反的,也可以输入单一的样本,输出一个序列(如图左下)。例如,输入可以是一幅图像,输出是该图像的标题。

    最后,右下角的神经网络就是一个翻译系统了。这是序列到向量神经网络(称为encoder)和向量到序列神经网络(称为decoder)的组合。比如,输入可以是一种语言的一句话,encoder将这句话转换为向量表示,decoder再把这个向量表示转换成另一种语言的一句话。这是一个two-step模型,称为Encoder–Decoder,执行翻译任务时,效果比一个序列序列的神经网络好得多。因为原文的最后一个词可能会影响译文的第一个词,所以需要读完全句后再进行翻译。

     

    基本RNN的TensorFlow实现
    首先,我们来实现一个很简单的RNN模型,不使用TensorFlow的任何运算,以便了解底层原理。我们会创建一层有5个训练神经元的RNN(如图14-2),使用tanh激活函数。假设这一RNN有两个时刻,每一时刻的输入是大小为3的向量。下面的代码创建这一RNN,并随时间展开:

     

     

    n_inputs = 3
    n_neurons = 5
     
    X0 = tf.placeholder(tf.float32, [None, n_inputs])
    X1 = tf.placeholder(tf.float32, [None, n_inputs])
     
    Wx = tf.Variable(tf.random_normal(shape=[n_inputs, n_neurons],dtype=tf.float32))
    Wy = tf.Variable(tf.random_normal(shape=[n_neurons,n_neurons],dtype=tf.float32))
    b = tf.Variable(tf.zeros([1, n_neurons], dtype=tf.float32))
     
    Y0 = tf.tanh(tf.matmul(X0, Wx) + b)
    Y1 = tf.tanh(tf.matmul(Y0, Wy) + tf.matmul(X1, Wx) + b)
     
    init = tf.global_variables_initializer()
    
    
    
    #输入训练数据
    import numpy as np
     
    # Mini-batch:         instance 0,instance 1,instance 2,instance 3
    X0_batch = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]]) # t = 0
    X1_batch = np.array([[9, 8, 7], [0, 0, 0], [6, 5, 4], [3, 2, 1]]) # t = 1
     
    with tf.Session() as sess:
        init.run()
        Y0_val, Y1_val = sess.run([Y0, Y1], feed_dict={X0: X0_batch, X1: X1_batch})
    
    
    >>> print(Y0_val) # output at t = 0
    [[-0.2964572 0.82874775 -0.34216955 -0.75720584 0.19011548] # instance 0
    [-0.12842922 0.99981797 0.84704727 -0.99570125 0.38665548] # instance 1
    [ 0.04731077 0.99999976 0.99330056 -0.999933 0.55339795] # instance 2
    [ 0.70323634 0.99309105 0.99909431 -0.85363263 0.7472108 ]] # instance 3
    >>> print(Y1_val) # output at t = 1
    [[ 0.51955646 1. 0.99999022 -0.99984968 -0.24616946] # instance 0
    [-0.70553327 -0.11918639 0.48885304 0.08917919 -0.26579669] # instance 1
    [-0.32477224 0.99996376 0.99933046 -0.99711186 0.10981458] # instance 2
    [-0.43738723 0.91517633 0.97817528 -0.91763324 0.11047263]] # instance 3
    
    
    
    
    #我们来训练一个RNN对MNIST图片进行分类。虽然CNN更适合做图像分类,这里只是使用这个例子来熟悉RNN。可以将MNIST中的每一个图像都看作是28行的序列,每一行又有28个像素点。我们使用150个循环神经元,加上一个全连接层,与输出层连接。最后是softmax层
    
    from tensorflow.contrib.layers import fully_connected
     
    n_steps = 28
    n_inputs = 28
    n_neurons = 150
    n_outputs = 10
     
    learning_rate = 0.001
     
    X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
    y = tf.placeholder(tf.int32, [None])
     
    basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
    outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32)
     
    logits = fully_connected(states, n_outputs, activation_fn=None)
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
     
    loss = tf.reduce_mean(xentropy)
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
    training_op = optimizer.minimize(loss)
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
     
    init = tf.global_variables_initializer()
    
    
    from tensorflow.examples.tutorials.mnist import input_data
     
    mnist = input_data.read_data_sets("/tmp/data/")
    X_test = mnist.test.images.reshape((-1, n_steps, n_inputs))
    
    n_epochs = 100
    batch_size = 150
     
    with tf.Session() as sess:
        init.run()
        for epoch in range(n_epochs):
            for iteration in range(mnist.train.num_examples // batch_size):
                X_batch, y_batch = mnist.train.next_batch(batch_size)
                X_batch = X_batch.reshape((-1, n_steps, n_inputs))
                sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
            acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
            acc_test = accuracy.eval(feed_dict={X: X_test, y: y_test})
            print(epoch, "Train accuracy:", acc_train, "Test accuracy:", acc_test)
    

     

     

     

    深层双向RNN 与双向RNN相比,多了几个隐藏层,因为他的想法是很多信息记一次记不下来,比如你去考研,复习考研英语的时候,背英语单词一定不会就看一次就记住了所有要考的考研单词吧,你应该也是带着先前几次背过的单词,然后选择那些背过,但不熟的内容,或者没背过的单词来背吧。

    深层双向RNN就是基于这么一个想法,他的输入有两方面,第一就是前一时刻的隐藏层传过来的信息h→(i)t−1h→t−1(i),和当前时刻上一隐藏层传过来的信息h(i−1)t=[h→(i−1)t;h←(i−1)t]ht(i−1)=[h→t(i−1);h←t(i−1)],包括前向和后向的。 

    Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息。LSTM 由Hochreiter & Schmidhuber (1997)提出,并在近期被Alex Graves进行了改良和推广。在很多问题,LSTM 都取得相当巨大的成功,并得到了广泛的使用。
    LSTM 通过刻意的设计来避免长期依赖问题。记住长期的信息在实践中是 LSTM 的默认行为,而非需要付出很大代价才能获得的能力!
    所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构,例如一个 tanh 层。
    LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于单一神经网络层,这里是有四个,以一种非常特殊的方式进行交互。
    LSTM 中的重复模块包含四个交互的层;

    这里只是部分流行的 LSTM 变体。当然还有很多其他的,如Yao, et al. (2015) 提出的 Depth Gated RNN。还有用一些完全不同的观点来解决长期依赖的问题,如Koutnik, et al. (2014) 提出的 Clockwork RNN。
    要问哪个变体是最好的?其中的差异性真的重要吗?Greff, et al. (2015) 给出了流行变体的比较,结论是他们基本上是一样的。Jozefowicz, et al. (2015) 则在超过 1 万种 RNN 架构上进行了测试,发现一些架构在某些任务上也取得了比 LSTM 更好的结果。

     

     

    展开全文
  • 二、循环神经网络的结构 三、循环神经网络的前向传播与反向传播 (一)RNN前向传播   前向传播总结: (二)RNN反向传播 (三)RNN网络的缺点 四、长短时记忆...

    一、循环神经网络简介

    二、循环神经网络的结构

    三、循环神经网络的前向传播与反向传播

    (一)RNN前向传播

     

    前向传播总结:

    (二)RNN反向传播

    (三)RNN网络的缺点

    四、长短时记忆——LSTM结构

    (一)LSTM结构的引入

     

    在RNN模型里,每个序列索引位置t都有一个隐藏状态h(t)。如果我们略去每层都有的

    o(t)、L(t)y(t),则RNN的模型图一可以简化成如下图二的形式:隐藏状态h(t)由x(t)和h(t−1)得到。

    得到的h(t)一方面用于当前层的模型损失计算,另一方面用于计算下一层的h(t+1)

    由于RNN梯度消失的问题,大牛们对于序列索引位置t的隐藏结构做了改进,可以说通过一些技巧让隐藏结构复杂

    避免梯度消失的问题,这样的特殊RNN就是我们的LSTM。下面介绍最常见的LSTM,其结构图结构如下:

    (二)LSTM内部结构解析

     下面一步步对LSTM模型在每个序列索引位置t时刻的内部结构进行解析。

    1、LSTM模型的关键——细胞状态(Cell State)

    在每个序列索引位置t时刻向前传播的除了和RNN一样的隐藏状态h(t)还多了另一个隐藏状态,如图中上面的长横线。

    这个隐藏状态我们一般称为细胞状态(Cell State)记为C(t)。LSTM单元上面的这条直线代表了LSTM的状态(state),

    它会贯穿所有串联在一起的LSTM单元,从第一个LSTM单元一直流向最后一个LSTM单元,其中只有少量的线性干预与改变

    细胞状态(Cell State)类似于传送带,直接在整个链上运行,只有一些少量的线性交互,信息在上面流传保持不变很容易

     

    2、LSTM模型——门控结构(Gates)

     细胞状态(cell state)在这条隧道中传递时,LSTM单元可以对状态(state)添加或删除信息

    这些对信息流的修改操作由LSTM中的门控结构Gates控制

    这些门控结构Gates中包含了一个sigmoid层和一个按位做乘法的操作,这个sigmoid层的输出是0到1之间的值,

    它控制了信息传递的比例。如果为0代表:不允许信息传递;如果为1代表:让信息全部通过。

    每个LSTM单元包含了3个这样的(包含了一个sigmoid层和一个按位做乘法的操作门控结构Gates

    即:LSTM在在每个序列索引位置t的门一般包括三种,分别为:遗忘门,输入门和输出门用来维护和控制单元的状态信息。

    凭借着对状态信息的储存和修改,LSTM单元就可以实现长程记忆

    (1)遗忘门(forget gate)

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

    如语言模型中,细胞状态可能包含性别信息(“他”或者“她”),当我们看到新的代名词的时候,可以考虑忘记旧的数据。

     图中输入的有上一序列的隐藏状态h(t−1)和本序列数据x(t),通过一个激活函数,一般是sigmoid

    得到遗忘门的输出f(t)由于sigmoid的输出f(t)在[0,1]之间,因此输出f(t)代表了遗忘上一层隐藏细胞状态的概率。

    用数学表达式即为:
        

    其中Wf,Uf,bf为线性关系的系数和偏倚,和RNN中的类似,σ为sigmoid激活函数。

    (2)输入门(input gate)

    在循环神经网络”遗忘“了部分之前的状态后,还需要从当前的输入补充最新记忆

    输入门(input gate)负责处理当前序列位置的输入,它的子结构如下图:


    从图中可以看到输入门由两部分组成,第一部分使用了sigmoid激活函数输出为i(t),

    第二部分使用了tanh激活函数,输出为a(t), 两者的结果后面会相乘再去更新细胞状态

    用数学表达式即为:

    (3)细胞状态(ceil state)更新



    前面的遗忘门和输入门的结果都会作用于细胞状态C(t)。来看从细胞状态C(t−1)如何得到C(t)。如下图所示:

    (4)输出门

    (三)对于LSTM结构的另一种理解

    (四)LSTM结构的前向传播与反向传播

    1、LSTM前向传播

    2、LSTM反向传播

    五、循环神经网络的变形

    六、双向循环神经网络(Bi-RNN)

        Bi-RNN又叫双向RNN,采用了两个方向的RNN网络,RNN网络擅长的是对于连续数据的处理,不仅可以学习它的正向规律,还可以学习它的反向规律。这样将正向和反向结合的网络会比单向的循环神经网络有更高的拟合度,如:预测一个语句中缺失的词语,则需要根据上下文来进行预测。双向RNN处理过程就是在正向传播的基础上再进行一次反向传播,而且这两个都连接着一个输出层。这个结构提供给输出层输入序列中,每一个点完整的过去和未来的上下文信息。

         在按照时间正向运算完之后,网络又从时间的最后一项反向地运算一遍,即:把t3时刻的输入与默认值0一起生成反向的out3,再把反向out3当成t2时刻的输入与原来t2时刻输入一起生成反向地out2,以此类推,直到第一个时序数据。在大多数应用里面,基于时间序列与上下文有关的、类似NLP中自动回答类的问题,一般都是使用双向LSTM+LSTM/RNN横向扩展来实现的,效果非常好。

        注意:双向循环神经网络商务输出是2个,正向一个,反向一个,最终会把输出结果concat并联在一起,然后交给后边的层来处理,例如:数据输入[batch,nhidden],输出就会变成[batch,nhidden*2]。

    七、循环神经网络的dropout

    八、python实现LSTM代码

     

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    import numpy as np
    
    #输出单元激活函数
    def softmax(x):
        x = np.array(x)
        max_x = np.max(x)
        return np.exp(x-max_x)/np.sum(np.exp(x-max_x))
    
    #定义sigmoid函数
    def sigmoid(x):
        return 1./(1 + np.exp(-x))
    
    #定义sigmoid函数的导数
    def sigmoid_derivative(values):
        return values(1-values)
    
    #定义tanh函数的导数
    def tanh_derivative(values):
        return 1.- values**2
    
    class MyLSTM():
        def __init__(self,n,h):
            self.n = n  #n:输入样本特征维度数量(如:词向量维度n*1)
            self.h = h  #h:隐藏状态/隐藏层的神经元的维度(h*1)
    
            #初始化权重向量
            self.whf,self.wxf,self.bf = self.init_wh_wx_b()
            self.whi,self.wxi,self.bi = self.init_wh_wx_b()
            self.wha,self.wxa,self.ba = self.init_wh_wx_b()
            self.who,self.wxo,self.bo = self.init_wh_wx_b()
            self.wy,self.by = np.random.uniform(-np.sqrt(1.0/self.h),np.sqrt(1.0/self.h),
                                                (self.n,self.h)),\
                              np.random.uniform(-np.sqrt(1.0/self.h),np.sqrt(1.0/self.h),
                                                (self.n,1))
    
        #初始化wh,wx,b
        def init_wh_wx_b(self):
            wh = np.random.uniform(-np.sqrt(1.0/self.h),np.sqrt(1.0/self.h),
                                   (self.h,self.h))
            wx = np.random.uniform(-np.sqrt(1.0/self.n),np.sqrt(1.0/self.n),
                                   (self.h,self.n))
            b = np.random.uniform(-np.sqrt(1.0/self.n),np.sqrt(1.0/self.n),
                                  (self.h,1))
            return wh,wx,b
    
        # LSTM门控结构的状态初始化
        def init_state(self,T):
            #遗忘门
            ft = np.array([np.zeros((self.h, 1))] * (T + 1))
            #输入门
            it = np.array([np.zeros((self.h, 1))] * (T + 1))
            at = np.array([np.zeros((self.h, 1))] * (T + 1))
            #细胞状态
            ct = np.array([np.zeros((self.h, 1))] * (T + 1))
            #输出门
            ot = np.array([np.zeros((self.h, 1))] * (T + 1))
            ht = np.array([np.zeros((self.h, 1))] * (T + 1))
            #预测输出
            yt = np.array([np.zeros((self.n, 1))] * T)
    
            return {
                "ft":ft,"it":it,"at":at,"ct":ct,"ot":ot,"ht":ht,"yt":yt
            }
        #前向传播,单个x
        def forward_prop(self,x):
            #向量时间长度
            T = len(x)
            #初始化LSTM门控结构各个状态向量
            states = self.init_state(T)
    
            for t in range(T):
                #前一时刻的隐藏层状态
                ht_pre = np.array(states["ht"][t-1]).reshape(-1,1)
                #遗忘门
                states["ft"][t] = self.calcu_gate(self.whf,self.wxf,self.bf,ht_pre,x[t],sigmoid)
                #输入门
                states["it"][t] = self.calcu_gate(self.whi,self.wxi,self.bi,ht_pre,x[t],sigmoid)
                states["at"][t] = self.calcu_gate(self.wha,self.wxa,self.ba,ht_pre,x[t],np.tanh)
                #更新细胞状态,ct = ft * ct_pre + it * at
                states["ct"][t] = states["ft"][t] * states["ct"][t-1] + states["it"][t] * states["at"][t]
                #输出门
                states["ot"][t] = self.calcu_gate(self.who,self.wxo,self.bo,ht_pre,x[t],sigmoid)
                states["ht"][t] = states["ot"][t] * np.tanh(states["ct"][t])
                #预测输出
                states["yt"][t] = softmax(np.dot(self.wy,states["ht"][t])+self.by)
    
                return states
    
        #计算各个门的输出
        def calcu_gate(self,wh,wx,b,ht_pre,x,activation):
            return activation(np.dot(wh,ht_pre)+np.dot(wx,x)+b)
    
        #预测输出,单个x
        def predict(self,x):
            states = self.forward_prop(x)
            pre_y = np.argmax(states["yt"].reshape(len(x),-1),axis=1)
            return pre_y
    
        #计算损失,softmax交叉熵损失函数,(x,y)为多个样本
        def loss(self,x,y):
            cost = 0
            for i in range(len(y)):
                states = self.forward_prop(x[i])
                #取出y[i]中每一时刻对应的预测值
                pre_yi = states["yt"][range(len(y[i])),y[i]]
                cost -= np.sum(np.log(pre_yi))
    
            #统计所有y中的词的个数,计算平均损失
            N = np.sum([len(yi) for yi in y])
            avg_cost = cost/N
    
            return avg_cost
    
        #初始化偏导数dwh,dwx,db
        def init_wh_wx_b_grad(self):
            dwh = np.zeros(self.whi.shape)
            dwx = np.zeros(self.wxi.shape)
            db = np.zeros(self.bi.shape)
    
            return dwh,dwx,db
        #求梯度,(x,y)为一个样本
        def bptt(self,x,y):
            dwhf,dwxf,dbf = self.init_wh_wx_b_grad()
            dwhi,dwxi,dbi = self.init_wh_wx_b_grad()
            dwha,dwxa,dba = self.init_wh_wx_b_grad()
            dwho,dwxo,dbo = self.init_wh_wx_b_grad()
            dwy,dby = np.zeros(self.wy.shape),np.zeros(self.by.shape)
            # 初始化 delta_ct,因为后向传播过程中,此值需要累加
            delta_ct = np.zeros((self.h,1))
    
            #前向计算
            states = self.forward_prop(x)
            #目标函数对输出y的偏导数,y_hat - 1
            delta_z = states["yt"]
            delta_z[range(len(y)),y] -= 1
    
            for t in np.arange(len(y))[::-1]:
                # 输出层wy, by的偏导数,由于所有时刻的输出共享输出权值矩阵,故所有时刻累加
                dwy += np.dot(delta_z[t],states["ht"][t].reshape(1,-1))
                dby += delta_z[t]
                #目标函数对隐藏状态ht的偏导数
                delta_ht = np.dot(self.wy.T,delta_z[t])
                #目标函数对各个门及状态单元的偏导数
                delta_ct += delta_ht * states["ot"][t] *(1-np.tanh(states["ct"][t])**2)
                delta_ft = delta_ct * states["ct"][t-1]
                delta_it = delta_ct * states["at"][t]
                delta_at = delta_ct * states["it"][t]
                delta_ot = delta_ht * np.tanh(states["ct"][t])
    
                delta_ft_net = delta_ft * states["ft"][t] *(1-states["ft"][t])
                delta_it_net = delta_it * states["it"][t] *(1-states["it"][t])
                delta_at_net = delta_at * (1-states["at"][t] ** 2)
                delta_ot_net = delta_ot * states["ot"][t] *(1-states["ot"][t])
    
                # 更新各权重矩阵的偏导数,由于所有时刻共享权值,故所有时刻累加
                dwhf,dwxf,dbf = self.calcu_grad_delta(dwhf,dwxf,dbf,delta_ft_net,states["ht"][t-1],x[t])
                dwhi,dwxi,dbi = self.calcu_grad_delta(dwhi,dwxi,dbi,delta_it_net,states["ht"][t-1],x[t])
                dwha,dwxa,dba = self.calcu_grad_delta(dwha,dwxa,dba,delta_at_net,states["ht"][t-1],x[t])
                dwho,dwxo,dbo = self.calcu_grad_delta(dwho,dwxo,dbo,delta_ot_net,states["ht"][t-1],x[t])
    
                return [dwhf,dwxf,dbf,
                        dwhi,dwxi,dbi,
                        dwha,dwxa,dba,
                        dwho,dwxo,dbo,
                        dwy,dby]
    
        #更新各权重矩阵的偏导数
        def calcu_grad_delta(self,dwh,dwx,db,delta_net,ht_prev,x):
            dwh += delta_net * ht_prev
            dwx += delta_net * x
            db += delta_net
    
            return dwh,dwx,db
    
        #计算梯度,(x,y)为一个样本
        def sgd_step(self,x,y,learning_rate):
            dwhf, dwxf, dbf,\
            dwhi, dwxi, dbi,\
            dwha, dwxa, dba,\
            dwho, dwxo, dbo,\
            dwy, dby = self.bptt(x,y)
    
            #更新权重矩阵
            self.whf,self.wxf,self.bf = self.update_wh_wx_b(learning_rate,self.whf,self.wxf,self.bf,dwhf,dwxf,dbf)
            self.whi,self.wxi,self.bi = self.update_wh_wx_b(learning_rate,self.whi,self.wxi,self.bi,dwhi,dwxi,dbi)
            self.wha,self.wxa,self.ba = self.update_wh_wx_b(learning_rate,self.wha,self.wxa,self.ba,dwha,dwxa,dba)
            self.who,self.wxo,self.bo = self.update_wh_wx_b(learning_rate,self.who,self.wxo,self.bo,dwho,dwxo,dbo)
    
            self.wy,self.by = self.wy - learning_rate * dwy,self.by - learning_rate * dby
    
        # 更新权重矩阵函数
        def update_wh_wx_b(self,learning_rate,wh,wx,b,dwh,dwx,db):
            wh -= learning_rate * dwh
            wx -= learning_rate * dwx
            b -= learning_rate * db
    
            return wh,wx,b
    
        #训练LSTM
        def train(self,x_train,y_train,learning_rate=0.005,n_epoch=5):
            losses = []
            num_examples = 0
    
            for epoch in range(n_epoch):
                for i in range(len(y_train)):
                    #计算梯度
                    self.sgd_step(x_train,y_train,learning_rate)
                    num_examples += 1
    
                # 计算损失函数
                loss = self.loss(x_train,y_train)
                losses.append(loss)
                print("epoch {0}:loss {1}".format(epoch+1,loss))
                if len(losses) > 1 and losses[-1] > losses[-2]:
                    learning_rate *= 0.5    #当损失值开始升高时,降低学习率
                    print("decrease learning rate to:",learning_rate)
    

     

     

     

     

     

     

    展开全文
  • 循环神经网络(RNN)

    2020-03-17 21:49:43
    神经网络概述 神经网络是模拟动物神经网络行为特征,进行分布式并行信息处理的算法数学模型。 从x到h到y可以近似看作动物神经,权重则可以看作是神经的...全连接神经网络和卷积神经网络的缺点 全连接神经网络和卷...
  • 循环神经网络

    2017-05-08 11:02:52
    其中从左到右的结构分别可以用来作为神经网络、图形标注、情感分析、机器翻译、视频分类。 a、Vanilla RNN b、LSTM 原始的RNN有很大的缺点,在训练序列较长的模型时,容易造成梯度消失和梯度爆炸的情况发生...
  • 文章目录通俗LSTM长短时记忆循环神经网络介绍LSTM图解处理流程流程图解总结说明PyTorch实战参考资料 版权声明:本文为博主原创文章,转载请注明原文出处! 写作时间:2019-03-02 18:20:11 本文部分图片素材来自...
  • 1.one-hot ...循环神经网络:①在每一时间步中,循环神经网络传递一个激活值到下一时间步中用于计算; ②循环神经网络是从左向右扫描数据,同时每个时间步参数也是共享,下图表示为参数。 缺点...
  • 循环神经网络的提出背景、优缺点。着重学习RNN的反向传播、RNN出现的问题(梯度问题、长期依赖问题)、BPTT算法。 双向RNN3 LSTM、GRU的结构、提出背景、优缺点。 针对梯度消失(LSTM等其他门控RNN)、梯度爆炸...
  • 原始的循环神经网络,本质是全连接网络,输入分为两个部分,分别为上一层输出以及本层输入。 网络中维护三个参数,本层输入权重W,上层输出权重U以及偏置b。 优点: 1.RNN很适合处理序列数据,因为考虑了...
  • 但是对于时间等序列预测,比如天气预报,明天是否下雨不仅仅与今天状态有关,还可能与之前几天甚至几十天状态有关,因此这里就需要使用循环神经网络。卷积神经网络是在神经网络上加了一层卷积层,同样道理,...
  • RNN循环神经网络简述

    2019-10-13 15:54:56
    RNN:本质是像人一样拥有记忆能力,它输出就依赖于当前输入和记忆。主要应用于自言语言处理及语音处理,缺点是随着信息传播,信号会减弱。 ...
  • 文档分类,输出情感,但是下面的结构存在上下文、长时间的序列损失的缺点。 一对多 看图描述文字任务。找到CNN特征图的图片之间的对应关系。 多对多 机器翻译 Sequence to Sequence 编码器和解码器,等价与 ...
  • 写给自己备忘内容:RNN基础1概述Recurrentneural network,循环神经网络,在普通多层BP神经网络基础上,增加了隐藏层各单元间横向联系,通过一个权重矩阵,可以将上一个时间序列神经单元值传递至当前...
  • 前向传播分为从左向右,从右向左两部分,这样,隐藏层神经元会产生两个激活值,均对输出有影响。 对很多NLP问题,双向带有LSTMRNN用最多。缺点是必须获取整个序列才能获得输出。 如果要学习复杂函数,需要将...
  • 循环神经网络 循环神经网络(RNN)是一个数学模型,是一个基础的思想的实现,用来做序列信息的预测,比如文本、翻译、推荐等。若要做实际的文本预测的话只用RNN还是不行,它的缺点很多,比如无法关注一个太长的句子...
  • 文章目录一 RNN在训练过程中的问题二 RNN的两种训练模式三 什么是Teacher Forcing四 Free-Running vs Teacher Forcing 实例4.1 Free-running 训练过程4.2 Teacher-Forcing 训练过程五 Teacher Forcing的缺点及其解决...
  • 递归神经网络RNN和BP神经网络的区别: 不同点:递归神经网络L有反馈回路,可以记住上一次的输出,并作为下一次的输入之一,BP神经网络没有反馈回路。 相同点:都有梯度消失的问题,之前输入的数据会随着时间的流逝...
  • 本文将介绍两种比RNN更好地应对梯度消失问题模型结构——LSTM和GRU,文章以CS224N课件和材料为基础,以...循环神经网络RNN由于模型结构上缺陷,很容易引起梯度爆炸和梯度消失,梯度爆炸可以用梯度截断方法在一定.
  • 本文着重讨论循环神经网络(Recurrent Neural Network,RNN)的数学推导过程(主要是反向过程),不会对RNN做全面的介绍,其特点,缺点假定读者已经了解,并且假定读者已经掌握全连接(FC)神经网络的原理和相关函数...
  • RNNLM,循环神经网络的基本结构与训练过程、优缺点;语言模型的评价指标说明。
  • 循环神经网络的提出背景、优缺点。着重学习RNN的反向传播、RNN出现的问题(梯度问题、长期依赖问题)、BPTT算法。 双向RNN 递归神经网络 LSTM、GRU的结构、提出背景、优缺点。 针对梯度消失(LSTM等其他门控RNN)、...
  • RNN循环神经网络 隐藏层之间节点不再是无连接 隐藏层输入不仅包括输入层输出还包括上一时刻隐藏层输出。 缺点:经过多次迭代容易梯度爆炸 实现语句:tf.nn.dynamic_rnn LSTM(长短时记忆 )网络 [RNN...
  • RNN它解决了前馈神经网络,无法体现数据时序关系的缺点。在RNN网络中,不仅同一个隐含层的节点可以相互连接,同时隐含层的输入不仅来源于输入层的输入还包括了上一个隐含层的输出。  RNN中主要有以下几个参数: ...
  • 循环神经网络的提出背景、优缺点。着重学习RNN的反向传播、RNN出现的问题(梯度问题、长期依赖问题)、BPTT算法。 双向RNN LSTM、GRU的结构、提出背景、优缺点。 4、针对梯度消失(LSTM等...
  • 本文将从语言模型概念出发,引出循环神经网络RNN概念,对RNN结构进行描述,详细推导了梯度计算过程,并解释RNN容易出现梯度消失、梯度爆炸原因。文章最后对RNN应用场景进行了简单介绍。 目录一、背景...
  • 循环神经网络的提出背景、优缺点。着重学习RNN的反向传播、RNN出现的问题(梯度问题、长期依赖问题)、BPTT算法。 双向RNN 递归神经网络 LSTM、GRU的结构、提出背景、优缺点。 针对梯度消失(LSTM等其他门控RNN...
  • 值得一提是,共享特征还有助于减少神经网络参数数量,一定程度上减小了模型计算复杂度。 RNN模型包含三类权重系数,分别是Wax,Waa,Wya。 优点:不同元素之间同一位置共享同一权重系数。 缺点:它只使...
  • Rnn中最明显的缺点就是共享了一组U,W,b,都是不变的,看这个输出y和hi,其中这个图中hi就是h1,h2,h3,还可以发现h2依赖于h1的结果,h3依赖于h2的结果,等等。 Rnn可以是多个并且有序,比如像人物说话,或者做事...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 161
精华内容 64
关键字:

循环神经网络的缺点