• 概述

RNN是递归神经网络,它提供了一种解决深度学习的另一个思路,那就是每一步的输出不仅仅跟当前这一步的输入有关,而且还跟前面和后面的输入输出有关,尤其是在一些NLP的应用中,经常会用到,例如在NLP中,每一个输出的Word,都跟整个句子的内容都有关系,而不仅仅跟某一个词有关。LSTM是RNN的一种升级版本,它的核心思想跟RNN是一样的,但是它透过一下方法避免了一些RNN的缺点。那么下面就逐步的解析一下RNN和LSTM的结构,然后分析一下它们的原理吧。

  • RNN解析

要理解RNN,咱们得先来看一下RNN的结构,然后就来解释一下它的原理

上图中左边的图是一个RNN网络结构中总体的图,右边的图片是一个RNN Cell里面的具体细节; 从上面的左边的图咱们可以看出,一个RNN的网络结构中,无论RNNcell循环多少次,它的weights都是share的,即一个weights只有一份copy, 而每一步的Hidden state(即右图中的a<t>和a<t-1>)是不同的,每一个time step它都有一份hidden state的copy。从上面的图片分析来看, RNN的每一步的输入不单单是有X<t>, 而且还有有前面的time step中学习来的hidden state -  a<t-1>。这就实现了咱们前面的需求了,让每一步的输出不仅仅跟当前的输入有关,还得跟前面的输入有关。具体的代码实现这个RNN cell的方法,你们可以参考下面的代码来加深对RNN的理解,实际在TensorFlow中来应用RNN的话,其实非常简单,就是一句代码就搞定了,但是,这里我还是贴出RNN cell创建的源码方便大家理解

  1. def rnn_cell(xt, a_prev, parameters):
  2. """
  3. Implements a single forward step of the RNN-cell as described
  4. Arguments:
  5. xt -- your input data at timestep "t", numpy array of shape (n_x, m).
  6. a_prev -- Hidden state at timestep "t-1", numpy array of shape (n_a, m)
  7. parameters -- python dictionary containing:
  8. Wax -- Weight matrix multiplying the input, numpy array of shape (n_a, n_x)
  9. Waa -- Weight matrix multiplying the hidden state, numpy array of shape (n_a, n_a)
  10. Wya -- Weight matrix relating the hidden-state to the output, numpy array of shape (n_y, n_a)
  11. ba -- Bias, numpy array of shape (n_a, 1)
  12. by -- Bias relating the hidden-state to the output, numpy array of shape (n_y, 1)
  13. Returns:
  14. a_next -- next hidden state, of shape (n_a, m)
  15. yt_pred -- prediction at timestep "t", numpy array of shape (n_y, m)
  16. cache -- tuple of values needed for the backward pass, contains (a_next, a_prev, xt, parameters)
  17. """
  18.  
  19. # Retrieve parameters from "parameters"
  20. Wax = parameters["Wax"]
  21. Waa = parameters["Waa"]
  22. Wya = parameters["Wya"]
  23. ba = parameters["ba"]
  24. by = parameters["by"]
  25.  
  26. # compute next activation state using the formula given above
  27. a_next = np.tanh(Wax.dot(xt)+Waa.dot(a_prev)+ba)
  28. # compute output of the current cell using the formula given above
  29. yt_pred = softmax(Wya.dot(a_next)+by)
  30.  
  31. # store values you need for backward propagation in cache
  32. cache = (a_next, a_prev, xt, parameters)
  33.  
  34. return a_next, yt_pred, cache
  35.  
  36. np.random.seed(1)
  37. xt_tmp = np.random.randn(3,10)
  38. a_prev_tmp = np.random.randn(5,10)
  39. parameters_tmp = {}
  40. parameters_tmp['Waa'] = np.random.randn(5,5)
  41. parameters_tmp['Wax'] = np.random.randn(5,3)
  42. parameters_tmp['Wya'] = np.random.randn(2,5)
  43. parameters_tmp['ba'] = np.random.randn(5,1)
  44. parameters_tmp['by'] = np.random.randn(2,1)
  45.  
  46. a_next_tmp, yt_pred_tmp, cache_tmp = rnn_cell_forward(xt_tmp, a_prev_tmp, parameters_tmp)
  47. print("a_next[4] = ", a_next_tmp[4])
  48. print("a_next.shape = ", a_next_tmp.shape)
  49. print("yt_pred[1] =", yt_pred_tmp[1])
  50. print("yt_pred.shape = ", yt_pred_tmp.shape)
  51. print( a_next_tmp[:,:])
  52. print( a_next_tmp[:,0])
  • LSTM解析

根据上面的RNN的结构图片,你们仔细的看一下有没有什么缺点。如果怎么的RNN需要循环很多次的话,咱们可能会有丢失信息的可能,就是gradient vanishing的情况发生,如果gradient vanishing的情况发生的话,它就不会继续学习咱们的信息了,就变成了standard neuro network了,RNN就失去了意义了。而且,咱们的sequence越长(即:循环的次数越多),gradient vanishing的可能性就越大。这个时候,咱们就有必要优化咱们的RNN了,让优化了的结构不但能够不断的学习能力,还能够有记忆功能,能把咱们学习的主要的东西能够记住,这就让咱们的RNN进化到了LSTM(Long short term memory)阶段了。为了能够更好的解释LSTM的网络结构,咱们还是先来看一些它就结构图片,然后再来解释一下吧

上图是一个LSTM cell的基本结构,这个图有有些不重要的元素,我都省略了,主要留下了一些最重要的信息。首先对比RNN, 咱们可以看出咱们多了3个gate和一个memory cell - C<t>。这个memory cell也称作internal hidden state。那么咱们来看看这个三个gate到底是干什么的。第一个gate是forget gate,它是帮助咱们的memory cell删除(或者称之为过滤)掉一些不重要的信息的,这个gate的值是在[0,1]这个区间,一般咱们用sigmoid函数来运算了,然后再和C来做element-wise的乘法运算,如果forget gate中的值趋向于0就删除掉相应的信息,如果forget gate中的值趋向于1则保留相应的值。第二个gate是update gate; 这个gate要跟咱们candidate memory cell来共同作用来产生新的信息,它们两个进行element-wise的相乘运算后,再跟咱们经过forget gate后的memory cell来进行element-wise的相加匀速,相当于把咱们从当前time step中学习到的信息添加到咱们的memory cell中。第三个gate就是output gate了;顾名思义就是过滤咱们输出的hidden state的, 这个gate也是sigmoid函数,根据前一个hidden state a<t-1> 和当前time step的输入 X<t>来共同决定的,它跟经过forget gate和update gate处理后的memory cell 的tanh值进行element-wise相乘过后,得到了了咱们当前time step的hidden state-a<t>,同时还得到了咱们当前time step的memory cell值;从这里咱们也可以看出output hidden state-a<t>和internal hidden state(memory cell)的dimension是一样的。上面解释了一下一个LSTM Cell中具体的结构跟功能。为了能够更好的加深大家对于LSTM的理解,我还是用代码演示一下如何构建一个LSTM cell, 代码如下所示:

 

  1. def lstm_cell(xt, a_prev, c_prev, parameters):
  2. """
  3. Implement a single forward step of the LSTM-cell as described in Figure (4)
  4.  
  5. Arguments:
  6. xt -- your input data at timestep "t", numpy array of shape (n_x, m).
  7. a_prev -- Hidden state at timestep "t-1", numpy array of shape (n_a, m)
  8. c_prev -- Memory state at timestep "t-1", numpy array of shape (n_a, m)
  9. parameters -- python dictionary containing:
  10. Wf -- Weight matrix of the forget gate, numpy array of shape (n_a, n_a + n_x)
  11. bf -- Bias of the forget gate, numpy array of shape (n_a, 1)
  12. Wi -- Weight matrix of the update gate, numpy array of shape (n_a, n_a + n_x)
  13. bi -- Bias of the update gate, numpy array of shape (n_a, 1)
  14. Wc -- Weight matrix of the first "tanh", numpy array of shape (n_a, n_a + n_x)
  15. bc -- Bias of the first "tanh", numpy array of shape (n_a, 1)
  16. Wo -- Weight matrix of the output gate, numpy array of shape (n_a, n_a + n_x)
  17. bo -- Bias of the output gate, numpy array of shape (n_a, 1)
  18. Wy -- Weight matrix relating the hidden-state to the output, numpy array of shape (n_y, n_a)
  19. by -- Bias relating the hidden-state to the output, numpy array of shape (n_y, 1)
  20.  
  21. Returns:
  22. a_next -- next hidden state, of shape (n_a, m)
  23. c_next -- next memory state, of shape (n_a, m)
  24. yt_pred -- prediction at timestep "t", numpy array of shape (n_y, m)
  25. cache -- tuple of values needed for the backward pass, contains (a_next, c_next, a_prev, c_prev, xt, parameters)
  26.  
  27. Note: ft/it/ot stand for the forget/update/output gates, cct stands for the candidate value (c tilde),
  28. c stands for the cell state (memory)
  29. """
  30.  
  31. # Retrieve parameters from "parameters"
  32. Wf = parameters["Wf"] # forget gate weight
  33. bf = parameters["bf"]
  34. Wi = parameters["Wi"] # update gate weight (notice the variable name)
  35. bi = parameters["bi"] # (notice the variable name)
  36. Wc = parameters["Wc"] # candidate value weight
  37. bc = parameters["bc"]
  38. Wo = parameters["Wo"] # output gate weight
  39. bo = parameters["bo"]
  40. Wy = parameters["Wy"] # prediction weight
  41. by = parameters["by"]
  42.  
  43. # Retrieve dimensions from shapes of xt and Wy
  44. n_x, m = xt.shape
  45. n_y, n_a = Wy.shape
  46.  
  47. ### START CODE HERE ###
  48. # Concatenate a_prev and xt
  49. concat = np.concatenate((a_prev, xt), axis=0)
  50.  
  51. # Compute values for ft (forget gate), it (update gate),
  52. # cct (candidate value), c_next (cell state),
  53. # ot (output gate), a_next (hidden state)
  54. ft = sigmoid(Wf.dot(concat)+bf) # forget gate
  55. it = sigmoid(Wi.dot(concat)+bi) # update gate
  56. cct = np.tanh(Wc.dot(concat)+bc) # candidate value
  57. c_next = c_prev*ft + cct*it # cell state
  58. ot = sigmoid(Wo.dot(concat)+bo) # output gate
  59. a_next = ot*np.tanh(c_next) # hidden state
  60.  
  61. # Compute prediction of the LSTM cell
  62. yt_pred = softmax(Wy.dot(a_next)+by)
  63. ### END CODE HERE ###
  64.  
  65. # store values needed for backward propagation in cache
  66. cache = (a_next, c_next, a_prev, c_prev, ft, it, cct, ot, xt, parameters)
  67.  
  68. return a_next, c_next, yt_pred, cache
  69.  
  70. np.random.seed(1)
  71. xt_tmp = np.random.randn(3,10)
  72. a_prev_tmp = np.random.randn(5,10)
  73. c_prev_tmp = np.random.randn(5,10)
  74. parameters_tmp = {}
  75. parameters_tmp['Wf'] = np.random.randn(5, 5+3)
  76. parameters_tmp['bf'] = np.random.randn(5,1)
  77. parameters_tmp['Wi'] = np.random.randn(5, 5+3)
  78. parameters_tmp['bi'] = np.random.randn(5,1)
  79. parameters_tmp['Wo'] = np.random.randn(5, 5+3)
  80. parameters_tmp['bo'] = np.random.randn(5,1)
  81. parameters_tmp['Wc'] = np.random.randn(5, 5+3)
  82. parameters_tmp['bc'] = np.random.randn(5,1)
  83. parameters_tmp['Wy'] = np.random.randn(2,5)
  84. parameters_tmp['by'] = np.random.randn(2,1)
  85.  
  86. a_next_tmp, c_next_tmp, yt_tmp, cache_tmp = lstm_cell_forward(xt_tmp, a_prev_tmp, c_prev_tmp, parameters_tmp)
  87. print("a_next[4] = \n", a_next_tmp[4])
  88. print("a_next.shape = ", c_next_tmp.shape)
  89. print("c_next[2] = \n", c_next_tmp[2])
  90. print("c_next.shape = ", c_next_tmp.shape)
  91. print("yt[1] =", yt_tmp[1])
  92. print("yt.shape = ", yt_tmp.shape)
  93. print("cache[1][3] =\n", cache_tmp[1][3])
  94. print("len(cache) = ", len(cache_tmp))
  • 总结

上面的两个部分主要介绍了RNN和LSTM的结构,以及分析了它们结构内部的功能和流程。并且分别在每一个cell后面都用Python展示了如何用代码去构建一个RNN cell和LSTM cell。咱们可以理解LSTM是对RNN的一种优化,同时要明白为什么要进行这样的优化;其次最重要的是理解RNN的这样一种新的解决问题的方法和思路,这跟咱们之前见过的standard neuro network最明显的一个区别就是,之前在神经网络,regressor 或者classfier中,每一个输出只跟咱们的输入features相关, 而RNN的思路则是不仅仅跟当前的输入有关,还跟前面的输入有关,这在以前sequence model中是非常常见的,例如Language modeling, machine translation等等的应用中,都是要用到RNN的思想的。

机器学习- RNN以及LSTM的原理分析的更多相关文章

  1. RNN 与 LSTM 的原理详解

    原文地址:https://blog.csdn.net/happyrocking/article/details/83657993 RNN(Recurrent Neural Network)是一类用于处 ...

  2. 图机器学习(GML)&图神经网络(GNN)原理和代码实现(前置学习系列二)

    项目链接:https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1 欢迎fork欢迎三连!文章篇幅有限, ...

  3. RNN 与 LSTM 的应用

    之前已经介绍过关于 Recurrent Neural Nnetwork 与 Long Short-Trem Memory 的网络结构与参数求解算法( 递归神经网络(Recurrent Neural N ...

  4. 浅谈RNN、LSTM + Kreas实现及应用

    本文主要针对RNN与LSTM的结构及其原理进行详细的介绍,了解什么是RNN,RNN的1对N.N对1的结构,什么是LSTM,以及LSTM中的三门(input.ouput.forget),后续将利用深度学 ...

  5. Apache Flink:特性、概念、组件栈、架构及原理分析

     2016-04-30 22:24:39    Yanjun Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时(Flink Runtim ...

  6. 3. RNN神经网络-LSTM模型结构

    1. RNN神经网络模型原理 2. RNN神经网络模型的不同结构 3. RNN神经网络-LSTM模型结构 1. 前言 之前我们对RNN模型做了总结.由于RNN也有梯度消失的问题,因此很难处理长序列的数 ...

  7. 深度学习:浅谈RNN、LSTM+Kreas实现与应用

    主要针对RNN与LSTM的结构及其原理进行详细的介绍,了解什么是RNN,RNN的1对N.N对1的结构,什么是LSTM,以及LSTM中的三门(input.ouput.forget),后续将利用深度学习框 ...

  8. 深度学习--RNN,LSTM

    一.RNN 1.定义 递归神经网络(RNN)是两种人工神经网络的总称.一种是时间递归神经网络(recurrent neural network),另一种是结构递归神经网络(recursive neur ...

  9. GOCR v0.50 原理分析

    一,简介: GOCR是一个c写的开源OCR库,GNU Public License,作者:Joerg Schulenburg 项目主页:http://jocr.sourceforge.net/inde ...

随机推荐

  1. ZJNU 1130 - 龟兔赛跑——中高级

    只需求出乌龟最短耗时跟兔子耗时比即可将起点 0 和终点 N+1 也看做充电站,进行动态规划对第i个点进行动态规划,则可以得到状态转移方程为dp[i] = max{dp[j]+time[i][j]} j ...

  2. 学习4412开发板gdb和gdbserver的调试

    因为有很多的小伙伴是从单片机转过来的,用惯了单片机上的JLINK调试程序,换到Linux上非常的不习惯.确实,如果能设置断点,单步调试,查看变量,那确实是太爽了,那么在我们的Linux可以做到吗,答案 ...

  3. SAP 配置表根据输入的值带出描述

    在SAP客制功能需求中,为了程式的灵活配置采用配置表的形成,使后期使用中不需要更改源代码实现功能的增加.在配置表的使用过程中,有时候会有这样的需求:在配置中输入或选择了编码,根据编码带出描述.以下详细 ...

  4. LeetCode No.139,140,141

    No.139 WordBreak 单词拆分 题目 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可 ...

  5. C语言占位符(待完善)

    %c 读入一个字符 %s 读入一个字符串,遇到空格制表符或者换行符时结束. %d 读入一个十进制整数 %x或者%X   读入一个十六进制整数(读出时,%x:小写,%X:大写) %o   读入一个八进制 ...

  6. 使用Cron表达式创建定时任务

    CronTriggerCronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用.CroTr ...

  7. ip获取到城市

    <?phpfunction GetIP() {    if ($_SERVER["HTTP_X_FORWARDED_FOR"])        $ip = $_SERVER[ ...

  8. UFT安装目录简单介绍

    1.在安装的help目录下可查看UFT相关的文档 2.在samples/filght/app目录下可看到UFT自带的用作测试的软件

  9. 吴裕雄--天生自然HTML学习笔记:HTML 图像

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. 吴裕雄--天生自然HTML学习笔记:HTML <head>

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...