array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 RNN、LSTM、GRU学习资料记录 - 爱码网

RNN、LSTM:人人都能看懂的LSTM
GRU:人人都能看懂的GRU
其他参考:
1、深度学习笔记——RNN(LSTM、GRU、双向RNN)学习总结
2、[tensorflow应用之路]RNN预测时间序列原理及LSTM/GRU算法实现
3、pytorch LSTM用于时间序列的分析

一、RNN

RNN:循环神经网络(Recurrent Neural Network,RNN)是一种用于处理序列数据的神经网络。

1、单个输入xx
RNN、LSTM、GRU学习资料记录
公式:f:h,y=f(h,x)f: h',y = f(h,x)
输入:xx为当前状态下数据的输入,hh为接收到上一个节点的输入
输出:yy为当前状态下本节点的输出,hh'为传递到下一个节点的输出

公式1:h=σ(Whh+Wix)h'=\sigma(W^hh+W^ix)
可以看出,输出hh',与hhxx的值都有关

公式2:y=σ(Woh)y=\sigma(W^oh')
yy则常常使用hh'投入到一个线性层(主要是进行维度映射)然后使用softmax进行分类得到需要的数据。
对这里的yy如何通过hh'计算得到往往看具体模型的使用方式。

2、序列输入x1,x2,x3...x^1,x^2,x^3...:
RNN、LSTM、GRU学习资料记录

二、LSTM

LSTM:长短期记忆(Long short-term memory, LSTM)是一种特殊的RNN,主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题。
简单来说,就是相比普通的RNN,LSTM能够在更长的序列中有更好的表现。

2.1 LSTM的输入输出

LSTM结构(图右)和普通RNN(图左)的主要输入输出区别如下所示。
RNN、LSTM、GRU学习资料记录
RNN只有一个传递状态hth^t,而LSTM有两个传递状态,一个ctc^t(cell state),和一个hth^t(hidden state)。(Tips:RNN中的hth^t对应于LSTM中的ctc^t
其中对于传递下去的ctc^t改变得很慢,通常输出的ctc^t是上一个状态传过来的ct1c^{t-1}加上一些数值。
hth^t则在不同节点下往往会有很大的区别。

2.2 LSTM的内部结构(计算公式)

1、首先使用LSTM的当前输入xtx^t和上一个状态传递下来的ht1h^{t-1}拼接训练,得到以下四个状态:
RNN、LSTM、GRU学习资料记录
RNN、LSTM、GRU学习资料记录
其中,ziz^izfz^fzoz^o 是由拼接向量乘以权重矩阵之后,再通过一个 sigmoidsigmoid**函数转换成0到1之间的数值,来作为一种门控状态。
sigmoid:s(x)=1/(1+e(x))sigmoid:s(x)=1/(1+e^{(-x)})
zz则是将结果通过一个tanhtanh**函数将转换成-1到1之间的值(这里使用tanhtanh是因为这里是将其做为输入数据,而不是门控信号)。

2、通过以下公式计算得到ctc^thth^tyty^t
RNN、LSTM、GRU学习资料记录
\bigodot是Hadamard Product,也就是操作矩阵中对应的元素相乘,因此要求两个相乘矩阵是同型的。
\bigoplus则代表进行矩阵加法。

2.3 LSTM原理解释

LSTM内部主要有三个阶段:
1、忘记阶段。
这个阶段主要是对上一个节点传进来的输入进行选择性忘记。简单来说就是会 “忘记不重要的,记住重要的”。

具体来说是通过计算得到的zfz^f(f表示forget)来作为忘记门控,来控制上一个状态的c(t1)c^{(t-1)}哪些需要留哪些需要忘。

2、选择记忆阶段。
这个阶段将这个阶段的输入有选择性地进行“记忆”。主要是会对输入xtx^t进行选择记忆。哪些重要则着重记录下来,哪些不重要,则少记一些。当前的输入内容由前面计算得到的zz表示。而选择的门控信号则是由ziz^i(i代表information)来进行控制。

将上面两步得到的结果相加,即可得到传输给下一个状态的ctc^t。也就是上图中的第一个公式。

3、输出阶段。
这个阶段将决定哪些将会被当成当前状态的输出。主要是通过zoz^o来进行控制的。并且还对上一阶段得到的coc^o进行了放缩(通过一个tanh**函数进行变化)。(上图中的第二个公式)

与普通RNN类似,输出yty^t往往最终也是通过hth^t变化得到。(上图中的第三个公式)

三、RNN和LSTM的总结、GRU的引入

以上,就是LSTM的内部结构。通过门控状态来控制传输状态,记住需要长时间记忆的,忘记不重要的信息;而不像普通的RNN那样只能够“呆萌”地仅有一种记忆叠加方式。对很多需要“长期记忆”的任务来说,尤其好用。

但也因为引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当但参数更少的GRU来构建大训练量的模型。

四、GRU

GRU(Gate Recurrent Unit)是RNN的一种。和LSTM一样,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。
相比LSTM,使用GRU能够达到相当的效果,并且相比之下更容易进行训练,能够很大程度上提高训练效率,因此很多时候会更倾向于使用GRU。

4.1 GRU的输入输出

和RNN一样:
RNN、LSTM、GRU学习资料记录

4.2 GRU的内部结构(计算公式)

1、通过上一个传输下来的状态h(t1)h^{(t-1)}和当前节点的输入xtx^t来获取两个门控状态。
如下图所示,其中rr控制重置的门控(reset gate),zz为控制更新的门控(update gate)。
RNN、LSTM、GRU学习资料记录
2、得到门控信号之后,首先使用重置门控来得到“重置”之后的数据 ht1=ht1r{h^{t-1}}' = h^{t-1}\bigodot r
再将ht1{h^{t-1}}'与输入xtx^t进行拼接,再通过一个tanh**函数来将数据放缩到-1~1的范围内。即得到如下图所示的hh'
RNN、LSTM、GRU学习资料记录
这里的hh'主要是包含了当前输入的xtx^t数据。有针对性地对hh'添加到当前的隐藏状态,相当于”记忆了当前时刻的状态“。类似于LSTM的选择记忆阶段。
RNN、LSTM、GRU学习资料记录
3、最后介绍GRU最关键的一个步骤,我们可以称之为”更新记忆“阶段。

在这个阶段,我们同时进行了遗忘和记忆两个步骤。我们使用了先前得到的更新门控zz(update gate)。

更新表达式:ht=zht1+(1z)hh^t = z \bigodot h^{t-1}+(1-z) \bigodot h'
输出表达式:yt=σ(Wht)y^t=\sigma(Wh^t)

首先再次强调一下,门控信号(这里的zz)的范围为0~1。门控信号越接近1,代表”记忆“下来的数据越多;而越接近0则代表”遗忘“的越多。

GRU很聪明的一点就在于,我们使用了同一个门控zz就同时可以进行遗忘和选择记忆(LSTM则要使用多个门控)。

  • zht1z \bigodot h^{t-1}:表示对原本隐藏状态的选择性“遗忘”。这里的 zz 可以想象成遗忘门(forget gate),忘记 ht1h^{t-1} 维度中一些不重要的信息。
  • (1z)h(1-z) \bigodot h' : 表示对包含当前节点信息的 hh' 进行选择性”记忆“。与上面类似,这里的 (1z)(1-z) 同理会忘记 hh' 维度中的一些不重要的信息。或者,这里我们更应当看做是对 hh' 维度中的某些信息进行选择。

结合上述,这一步的操作就是忘记传递下来的 ht1h^{t-1} 中的某些维度信息,并加入当前节点输入 hh' 的某些维度信息。

可以看到,这里的遗忘 zz 和选择 (1z)(1-z) 是联动的。也就是说,对于传递进来的维度信息,我们会进行选择性遗忘,则遗忘了多少权重 (zz),我们就会使用包含当前输入的 hh' 中所对应的权重进行弥补 (1z)(1-z) 。以保持一种”恒定“状态。

4.3 LSTM与GRU的关系

GRU是在2014年提出来的,而LSTM是1997年。
rr (reset gate)实际上与他的名字有点不符。我们仅仅使用它来获得了 hh'
那么这里的 hh' 实际上可以看成对应于LSTM中的 hth^t(hidden state);上一个节点传下来的 ht1h^{t-1} 则对应于LSTM中的 ctc^t(cell state)。
zz 对应的则是LSTM中的 zfz^f(forget gate),那么 (1z)(1-z) 我们似乎就可以看成是选择门 ziz^i 了。

相关文章: