引言

今天来介绍一下循环神经网络(Recurrent Neural Network,RNN),和现在比较常用的长短期记忆网络(LSTM)。并且通过多个例子来阐述这些概念,个人觉得还是比较容易理解的。

循环神经网络

我们以一个例子来引入RNN,这个例子就是填槽(Slot Filling)。

假设你要做一个智能订票系统。

假设有个人对你的订票系统说:“I would like to arrive Taipei(台北) on November 2nd.”,
作为一个订票系统,里面肯定会有像目的地(desination)和到达时间(time of arrival)这种关键信息。这里就用slot表示,你的系统要通过上面说的话就能识别出来目的地是Taipei,到达时间是:November 2nd。其他的词汇就不属于任何Slot。

这个问题可不可以用一个前馈神经网络来解,输入是一个词汇,比如把Taipei变成一个向量,丢到NN中去,但是在这之前你必须先把这个词汇用一个向量来表示。

把词汇用向量表示的方法有很多,最简单的方法是1-of-N编码。假设现在你的训练数据里面只有5个词汇,那么你就可以用一个5维向量表示,每个维度对应一个向量。出现某个词,就将对应维度的值设成1,其他都为0。

如果测试数据中出现了你训练数据中没有的词汇,那怎么办呢,有一种办法是增加一个维度,专门用来表示没有见过的词汇,这里用"other"表示。

除了这种方法外,还有一个Word Hasing的方法。
用某个词汇的字母来表示它的向量,比如有个词汇叫“apple”,“apple”里面有出现“app”、“ppl”和“ple”。在这个向量,对应中上面三个维度的值就是1,其他的都是0。

这样我们就能把一个词汇表示成一个向量,然后丢到NN中去,在填槽任务中,你希望这个前馈NN的输出是一个概率分布。这个概率分布代表我们输入的每个词汇属于每个SLOT的概率。

举例来说,就是Taipei属于这两个SLOT的概率。

如果仅是如此是不够的。

假设有人说“arrive Taipei on November 2nd”,这里面“Taipei”是目的地,“November 2nd”是时间,剩下的不属于这两个SLOT。

假设你解决了这个问题,但是另一个人说:“leave Taipei on November 2nd”。


那此时的Taipei应该是出发地,但是对于NN来说,输入是一样的东西,输出就是一样的东西。

你输入Taipei这个词汇,它输出要么都是目的地的概率最高,要么都是出发地(这里引入了一个新的SLOT)的概率最高。

你无法让同样的输入有时出发地的概率最高,有时目的地的概率最高。


如果NN是有记忆的就好了,如果它在看过红色的Taipei之间就已经看过arrive这个词汇;它记得它在看过绿色的Taipei之间,看过leave这个词汇。它就可以根据对话的上下文产生不同的输出!

这样就能解决输入是同样的词汇,输出是不同的问题。

这种有记忆的神经网络就是RNN(具体的说应该是简单的RNN(SimpleRNN))。

在RNN里面,每次我们的隐藏层产生输出的时候,这个输出都会被存到内存里面去。

那么在下次有输入的时候,此时这个NN就不仅会考虑输入的x1,x2x_1,x_2x1​,x2​,还会考虑存在内存中的值。它们都会影响这个隐藏层的输出。

这里还是用一个例子来让大家更好的明白。

假设我们现在图上的NN所有的权重都是111,并且所有的神经元都没有任何的偏置(bbb),同时假设所有的激活函数都是线性的。

假设我们的输入是这样的序列:

接下来在使用我们的RNN之前需要给a1,a2a_1,a_2a1​,a2​初始值。

这里假设里面的初始值是000。


现在输入我们输入序列中的第一个1和1。


以上面用红框框出来的神经元来说,它不仅接到我们输入的1和1,它还接到内存中的0和0。

因为我们说所有的权重www都是1,因此它的输出为:0(a1)×1(w)+0(a2)×1+1(x1)×1+1(x2)×1=20(a_1)\times 1(w) + 0(a_2)\times 1 + 1(x_1)\times 1 + 1(x_2)\times1 = 20(a1​)×1(w)+0(a2​)×1+1(x1​)×1+1(x2​)×1=2 括号里面是解释对应的值是怎么来的。


同样,隐藏层右边的神经元输出也是2。
接下来,根据同样的计算方法,红色两个神经元的输出都是4。

因此,输入是1和1的时候,输出就是4和4。

接下来RNN会把绿色神经元的输出存到内存中去,覆盖之前的0和0。

接下来再输入第二个1和1,这时绿色的神经元的输出就会是: 2×1+2×1+1×1+1×1=62 \times 1 + 2\times 1 + 1\times1 + 1\times1 = 62×1+2×1+1×1+1×1=6。

最后红色神经元的输出就是6×1+6×1=126 \times 1 + 6\times 1 = 126×1+6×1=12。

所以当输入第二个1和1的时候,输出就是12和12。


所以从这里可以看出,对于RNN来说,就算给它一样的东西,也能得到不一样的结果。因为存在内存中的值是不一样的。

别忘了,接下来还会把绿色神经元的输出6和6覆盖掉之前的2和2。

接下来输入就是2和2,


根据同样的方法,就可以计算出绿色神经元的输出是16,红色神经元的输出是32。
当输入2和2时,输出就是32和32。

在做RNN的时候,有个很重要的是,输入序列的顺序会影响输出。

所以我们要用RNN来处理填槽问题的话,它就可以就像下面这样。

有个人说:“arrive Taipei on November 2nd”。


arrive就变成了一个向量,丢到NN中去,它的隐藏层输出是a1a_1a1​(也是个向量),然后根据a1a_1a1​我们产生y1y^1y1,就是arrive属于每个SLOT的概率。

接下来a1a_1a1​会被存在内存中去,并且Taipei会变成输入,这个隐藏层会同时考虑Taipei这个输入和存在内存中的a1a_1a1​,得到a2a_2a2​,在根据a2a_2a2​产生y2y^2y2,y2y^2y2是Taipei属于每个SLOT的概率。

以此类推,我们就把a2a_2a2​存到内存中去,再把on丢进去,然后产生a3a_3a3​,进而产生y3y^3y3。

上面其实只是同一个神经网络,只是内存中保存的值不同,这里被使用了3次。

所以当神经网络有了记忆以后,刚才我们讲的输入同一个词汇,我们希望输出不同的问题就有可能被解决。


比如说,同样是输入了Taipei这个词汇,红色的前面接的是leave,绿色的Taipei前面接的是arrive。因为leave和arrive的向量不一样,所以存在内存中的值就不一样,这样最终得到的输出也不一样。

这个RNN的基本概念,虽然我们这里只有一个隐藏层,其实是可以很深的。

比如把xtx^txt丢进去后,它可以通过很多个隐藏层,最后得到输出yty^tyt。

每个隐藏层的输出都会存在内存中,下个时间点的时候,每个隐藏层都会读出前个时间点存的值,最后得到最终的输出,整个过程如下:

Elman Network & Jordan Network

RNN有不同的变形,我们刚才讨论的是Elman Network,就是把隐藏层的输出值存起来,下个时间点再读出来。如下图:

还有一种是Jordan Network,它存在的整个网络(这里用网络)的输出值,它会把这个输出值在下个时间点读进来。

据说Jordan Network能有比较好的结果,因为Elman Network的隐藏层的输出是没有目标的,你很难控制它学到怎样的东西;而输出值yyy是有目标的,我们可以很清楚知道我们放到内存中的是什么。

双向循环神经网络(Bidirectional RNN)

RNN还可以是双向的,我们刚才看到的RNN是输入一个句子,从句首读到句尾。

比如说,先读xtx^txt,再读xt+1x^{t+1}xt+1,再读xt+2x^{t+2}xt+2

但是,它的读取方向其实是可以反过来的。可以先读xt+2x^{t+2}xt+2,再读xt+1,最后读x^{t+1},最后读xt+1,最后读x^t$。

我们可以同时训练正向的RNN和逆向的RNN,然后把这两个RNN的隐藏层拿出来,都接给一个输出层,产生yyy。

用双向循环神经网络的好处是,你的网络在产生输出的时候,它看的范围是比较广的。如果你只有正向的RNN,在产生yt,yt+1y^t,y^{t+1}yt,yt+1的时候,你的网络只看过x1x^1x1一直到xt+1x^{t+1}xt+1的输入。
如果我们今天是双向循环神经网络的时候,在产生yt+1y^{t+1}yt+1的时候,你的网络不仅看了x1x^1x1到xt+1x^{t+1}xt+1的输入,它也看了从句尾一直到xt+1x^{t+1}xt+1的输入。
你的网络等于是看了整个输入的序列以后,才决定每个词汇的SLOT应该是什么。当然会比只看了句子的一般得到更好的结果。

长短期记忆网络

刚才讨论的RNN的内存版本只是最简单的,接下来我们讨论下 长短期记忆网络(Long Short-term Memory,LSTM)。

我们现在有个Memory Cell,它就像我们刚才说的RNN中隐藏层的内存。

LSTM它的Memory Cell有三个门结构,当神经网络的输出想要写到内存Memory Cell中去时,它必须先通过一个输入门(Inpute Gate),这个输入门打开的时候才能把值写到Memory Cell中去,如果关闭的时候是无法写进去的。

这个输入门是打开还是关闭是神经网络自己学的。

在输出的地方也有一个输出门(Output Gate),这个输出门会决定外界(其他的神经元)能否从这个Memory Cell中读出值。只有打开的时候才能读出值。和输入门一样,输出门什么时候打开,什么时候关闭,也是神经网络自己学习的。

第三个门是遗忘门(Forget Gate),它来决定Memory Cell是否要忘掉之前保存的值。

同样,什么时候要忘掉,什么时候要保存也是网络自己学到的。


整个LSTM你可以看成是一个特征的神经元,它有4个输入和1个输出。

这个四个输入是:想要存到Memory Cell中的值、操控输入门的讯号(决定能否存进去)、操控输出门的讯号(决定别人能否看到)以及操控遗忘门的讯号(决定是否要清除当前保存的值)。

这里应该是更“专业”的图例:

我们假设现在要存到Cell中的输入是zzz,操作输入门的数值(标量)是ziz_izi​,操控输出门的数值是zoz_ozo​,操控遗忘门的数值是zfz_fzf​,综合这些东西后得到的输出是aaa。


假设在输入zzz之前,Cell里面已经存了值ccc。

然后我们输入zzz,将zzz通过激活函数(都是与它们自己相邻的那个)得到的值记为g(z)g(z)g(z),ziz_izi​通过另外一个激活函数得到f(zi)f(z_i)f(zi​),这三个门机构的激活函数通常会选择Sigmoid函数。
因为Sigmoid函数的值是在0到1之间的,这个值可以代表这个门被打开的程度,如果经过Sigmoid函数后的输出是1,代表门是打开的;反之,0代表门是关闭的。


接下来就把g(z)g(z)g(z)乘上输入门的值:f(zi)f(z_i)f(zi​),得到g(z)f(zi)g(z)f(z_i)g(z)f(zi​)。

zfz_fzf​也通过激活函数得到f(zf)f(z_f)f(zf​),接下来把存在Cell中的值ccc乘上f(zf)f(z_f)f(zf​)得到:cf(zf)cf(z_f)cf(zf​),然后把cf(zf)cf(z_f)cf(zf​)加上g(z)f(zi)g(z)f(z_i)g(z)f(zi​)得到c′c^\primec′,它就是新的存在Cell中的值。

根据目前为止的运算你可以发现,f(zi)f(z_i)f(zi​)就是控制g(z)g(z)g(z)能否输入的一个关卡,假设f(zi)=0f(z_i)=0f(zi​)=0,那么不管你输入什么,g(z)f(zi)=0g(z)f(z_i)=0g(z)f(zi​)=0,就像是没有输入一样。

如果f(zi)=1f(z_i)=1f(zi​)=1,那就把g(z)g(z)g(z)当做输入。

而f(zf)f(z_f)f(zf​)决定是否要把存在Cell中的值清掉,假设f(zf)=1f(z_f)=1f(zf​)=1,也就是遗忘门被开启的时候,这个时候1×c1 \times c1×c,会得到ccc,然后把c+g(z)f(zi)c + g(z)f(z_i)c+g(z)f(zi​)写回去,相当于就会保存(用到)之前的值;如果f(zf)=0f(z_f)=0f(zf​)=0,也就是遗忘门关闭,0×c0 \times c0×c得到000,把0+g(z)f(zi)0 + g(z)f(z_i)0+g(z)f(zi​)写到Cell中去,就相当于忘掉了(没用到)原来的ccc。

然后把这两个值加起来写到Cell中去。遗忘门的开关和我们的直觉是相反的,打开的时候是记得,而关闭的时候是遗忘。或许应该叫它记忆门。

然后把这个c′c^\primec′通过hhh这个激活函数,得到h(c′)h(c^\prime)h(c′),接下来有一个输出门,这个输出门受zoz_ozo​所操控,zoz_ozo​通过fff得到f(zo)f(z_o)f(zo​),然后会把f(zo)f(z_o)f(zo​)乘上h(c′)h(c^\prime)h(c′)得到a=h(c′)f(zo)a = h(c^\prime)f(z_o)a=h(c′)f(zo​)。

如果f(zo)=1f(z_o)=1f(zo​)=1,表示h(c′)h(c^\prime)h(c′)可以通过这个输出门,反之如果是0,就表示这个输出就会变成0,也就是存在内存中的值就无法通过输出门被读取出来。

一个良心的例子

如果你没理解上面所说的,接下来用一个例子,结合上面说的,再描述一遍,希望你能明白。

假设我们的网络中只有一个LSTM的Memory Cell,我们的输入是3维的向量,输出都是1维的向量。

这个3维的输入向量和1维的输出向量之间的关系是

  • 当输入向量第2个维度x2x_2x2​的值是1的话(x2=1x_2=1x2​=1),x1x_1x1​的值就会被写到内存中去
  • 当x2=−1x_2=-1x2​=−1时,内存中存的值就会被遗忘
  • 当x3=1x_3=1x3​=1时,才会打开输出门,看到输出。

    假设我们原来存到内存中的值是000,当这边x2=1x_2=1x2​=1时,333会被存到内存中去,所以得到的值就变成333。

    接下来又出现了x2=1x_2=1x2​=1的情况,所以444就会被存到内存中去,加上之前的333得到777。

    接下来遇到x3=1x_3=1x3​=1,所以现在内存中的值777就会被输出。

    下面碰到了x2=−1x_2=-1x2​=−1就会忘掉内存中的值,下一个时间点内存中的值就变成了000

然后看到x2=1x_2=1x2​=1就会把此时x1x_1x1​的值666存进去。

并且看到x3=1x_3=1x3​=1,会把666输出。

接下来就来实际做一下运算。


这是一个LSTM的Memory Cell,我们知道它有4个输入标量,这4个标量就是我们输入的3维向量乘上一个权重后加上偏差所得到的的结果。


比如x1,x2,x3x_1,x_2,x_3x1​,x2​,x3​与权重进行线性转换并加上偏差后就会得到一个标量,就得到这里的输入。

这里的权重与偏差都是通过训练数据学到的,这里假设我们已经知道这些值是多少。

这里假设我们的输入是:

我们来实际运算一下,不过在这之前,先分析一下我们可能会得到的结果。

先看整个Cell的输入这里

x1x_1x1​乘111,其他都是乘000,因此这里会直接把x1x_1x1​当成输入。

再看输入门的地方

它是x2×100x_2 \times 100x2​×100而偏差是−10-10−10,就是说假设x2x_2x2​没有值时,经过运算就会得到偏差−10-10−10,经过Sigmid激活函数后,它的值会接近000,这相当于输入门是关闭的,只有在x2x_2x2​有值的时候,才有可能得到的结果比−10-10−10要大,经过Sigmoid函数得到一个正值,代表输入门被打开。

在看遗忘门这里

这里哪怕x2x_2x2​没值也会被打开,因为偏差有个正值101010,只有在x2x_2x2​有个很大的负值能压过偏差的时候,才会关闭。

最后看下输出门

输出门通常是关闭的,因为偏差是个较大的负值,如果x3x_3x3​的正值可以压过偏差的话,就可以把输出门打开。

好了,接下来就可以实际手撸一把了。

这里为了简化计算,假设g,hg,hg,h都是线性的,并且内存中的初始值是000。

现在我们输入第一个向量{3,1,0}\{3,1,0\}{3,1,0}。

先看输入这里,3×1=33 \times 1=33×1=3,因为其他的权重为000,这里得到的输入就是333。
然后再输入门这里

1×100−10=901 \times 100 - 10=901×100−10=90代入Sigmoid激活函数约等于111,这里输入门就打开。

然后就可以通过输入门,1×3=31\times 3=31×3=3


此时再来看下遗忘门

1×100+×10=1101 \times 100 + \times 10 = 1101×100+×10=110代入Sigmoid函数得到111,遗忘门被打开,意思不会遗忘。

然后把Memory Cell中的0×1+3=30 \times 1 + 3 = 30×1+3=3

所以333就会被存入Memory Cell。接下来看下输出门。


0×100−10=−100 \times 100 - 10 = -100×100−10=−10代入激活函数约等于000,说明输出门关闭,也就是值无法输出,为什么

因为我们把输出门得到的000乘以遗忘门传过来的 333 得000,就是最终的输出值,被000给消掉了。

接下来输入{4,1,0}\{4,1,0\}{4,1,0}。

首先输入的值是444,然后输入门是打开的,然后遗忘门也是打开的,所以内存中的值就变成了3×1+4=73 \times 1 + 4 = 73×1+4=7,因此更新内存中的值为777。

但是在这个输入({4,1,0}\{4,1,0\}{4,1,0})下,输出门还是关闭的,导致777也无法输出,输出的是000。

接下来输入{2,0,0}\{2,0,0\}{2,0,0}。


输入变成了222,输入门经过计算是关闭的,222乘以输入门的000得到000。
遗忘门是打开的7×1+0=77 \times 1 + 0 =77×1+0=7,相当于内存中的值不变。此时输出门还是关闭的,最终输出是000。

接下来输入{1,0,1}\{1,0,1\}{1,0,1}。


输入变成了111,输入门是关闭的,遗忘门是打开的,内存中的值不变。但是此时输出门是打开的,我们把输出门的111乘上传过来的777,得到最终的输出是777。

最后输入{3,−1,0}\{3,-1,0\}{3,−1,0}。

输入变成了333,输入门是关闭的,遗忘门也是关闭的,所以内存中的值就变成了0×3+7×0=00 \times 3 + 7 \times 0 = 00×3+7×0=0,输出门也是关闭的,不过此时哪怕打开了输出也是000。

演算完毕。


看到这个东西我们可能觉得和原来的神经网络不像,在我们原来的神经网络里面会有很多神经元,我们会把输入乘上不同的权重,得到的值当成不同神经元的输入,
每个神经元都是一个函数,输入一个标量,输出另一个标量。

如果是LSTM的话,只要把LSTM的Memory Cell想成是一个神经元就好了。
现在的输入会乘上不同的权重,当做LSTM的不同的输入。这里假设这个隐藏层只有两个神经元。

x1,x2x_1,x_2x1​,x2​乘上某组权重会去操控第一个LSTM的输出,再乘上另外一组权重操控输出门,乘上另外一组权重会去操控第一个LSTM的输入门,再乘上一组权重去操纵遗忘门。

第二个LSTM也是一样,x1,x2x_1,x_2x1​,x2​乘上不同的权重去操控第二个LSTM的输入、输出门、输入门和遗忘门。

因此对应LSTM会有4倍的参数数量。因为每组权重不同,同一个输入x1,x2x_1,x_2x1​,x2​得到的乘以权重得到的值也是不一样的。

也即使LSTM需要4个输入才会产生一个输出,而原来的神经元只要一个输入就能产生一个输出。

但是看起来还是不太像RNN,这里画另外一个图来表示它。

假设我们有一整排的神经元(LSTM),每个LSTM的Cell中都存了一个标量,把这些标量连接起来就得到一个向量ct−1c^{t-1}ct−1(表示时间点ttt的前一个时间点)。每个LSTM存的值在这个向量的某个维中。


现在在时间点ttt,有个输入向量xtx^txt,它首先会乘上一个矩阵进行线性转换变成另外一个向量zzz。zzz这个向量的每个维度代表了操控每个LSTM的输入。


它的第一维就丢给第一个Cell,第二维就丢给第二个Cell…

这个xtx^txt会乘上另外一个矩阵得到ziz^izi。ziz^izi的维度也和LSTM的数量一样,不过它的每个维度操控的是LSTM的输入门。

看到这里你可能会想到,还有有两个新的向量来操控输出门与遗忘门。对了。

同样滴,得到zfz^fzf来操控遗忘门,zoz^ozo操控输出门。


所以我们把xtx^txt乘上4个不同的矩阵,得到四个不同的向量。它们的维度都会LSTM的数量一样,这4个向量一起操控LSTM的运作。

注意每个只把4个向量的某个维度的值丢给某个LSTM,但是所有的Cell是可以共同一起被运算的。

我们知道zzz要乘上ziz^izi通过激活函数的结果,我们上面画出来。

zfz^fzf也要通过遗忘门的激活函数,然后与之前存在Cell中的值相乘(在ct−1c^{t-1}ct−1的某个维度中)。


接下来要把上面得到的两个值加起来。

zoz^ozo通过激活函数,把输出与上面的值经过激活函数的结果相乘,最后得到输出yty^tyt。


对了,红框框出来相加后的结果就是存到内存中的值ctc^tct。
整个过程会反复进行下去,在下个时间点,输入 xt+1x^{t+1}xt+1,然后经过上面一样的过程,得到下个时间点的输出yt+1y^{t+1}yt+1

你可能觉得这个很复杂,但这还仅仅是简化的形式,真正的LSTM还会接入一个hth^tht:

把上图红色箭头尾部的输出当做下个时间点的输入。

也就是说下个时间点操控这些门和输入的值不仅仅只是看原来的输入xt+1x^{t+1}xt+1,还会看前一个时间点的输出hth^tht。

其实还不只这样,还会加一个peephole(窥视孔),就是把存在前一个时间点内存中的值也拿出来当成新的时间点的输入。

而且现在随便都会叠个5,6层,它看起来是这样的:

李老师这里还贴出了个图片,类似我看到了什么鬼!?

你可能会觉得这么复杂能否真的有用,但是它还真是很常用的。好在我们用Keras这种工具,可以很方便的开箱即用(上面的没看懂也没关系)。

Keras支持LSTM、GRU(LSTM的简化版,据说表现还差不多,并且不容易过拟合)和SimpleRNN。

参考

1.李宏毅机器学习

李宏毅机器学习——循环神经网络(一)相关推荐

  1. 李宏毅机器学习——循环神经网络(二)

    引言 本文是接上一篇李宏毅机器学习--循环神经网络(一) Learning Target 在RNN中如何定义损失函数呢.还是以Slot Filling为例,给定一些句子作为训练数据 并且要给这些句子一 ...

  2. 机器学习——循环神经网络(RNN)

    相关文章链接: 机器学习--人工神经网络(NN) 机器学习--卷积神经网络(CNN) 机器学习--长短期记忆(LSTM) 机器学习--决策树(decision tree) 机器学习--随机森林(Ran ...

  3. 【李宏毅机器学习笔记】 23、循环神经网络(Recurrent Neural Network,RNN)

    [李宏毅机器学习笔记]1.回归问题(Regression) [李宏毅机器学习笔记]2.error产生自哪里? [李宏毅机器学习笔记]3.gradient descent [李宏毅机器学习笔记]4.Cl ...

  4. 【李宏毅机器学习】Recurrent Neural Network Part1 循环神经网络(p20) 学习笔记

    李宏毅机器学习学习笔记汇总 课程链接 文章目录 Example Application Slot Filling 把词用向量来表示的方法 1-of-N encoding / one-hot Beyon ...

  5. 【李宏毅机器学习】Recurrent Neural Network Part2 循环神经网络(p21) 学习笔记

    李宏毅机器学习学习笔记汇总 课程链接 文章目录 Learning Target Learning Unfortunately 基于RNN的的网络不总是容易去学习 The error surface i ...

  6. 【机器学习】RNN循环神经网络

    循环神经网络归属: 领域:机器学习 方向:自然语言处理 贡献:自动文本生成 循环神经网络实际应用: 生活中因为原始数据都是序列化的,比如自然语言,语音处理,时间序列问题(股票价格)等问题, 这个时候需 ...

  7. 时序预测的三种方式:统计学模型、机器学习、循环神经网络

    作者 | luanhz 来源 | 小数志 导读 时序预测是一类经典的问题,在学术界和工业界都有着广泛的研究和应用.甚至说,世间万物加上时间维度后都可抽象为时间序列问题,例如股票价格.天气变化等等.关于 ...

  8. tensorflow lstm从隐状态到预测值_机器学习100天-Day2405 循环神经网络RNN(LSTM)

    说明:本文依据<Sklearn 与 TensorFlow 机器学习实用指南>完成,所有版权和解释权均归作者和翻译成员所有,我只是搬运和做注解. 进入第二部分深度学习 第十四章循环神经网络 ...

  9. keras 多层lstm_机器学习100天-Day2403 循环神经网络RNN(训练多层RNN)

    说明:本文依据<Sklearn 与 TensorFlow 机器学习实用指南>完成,所有版权和解释权均归作者和翻译成员所有,我只是搬运和做注解. 进入第二部分深度学习 第十四章循环神经网络 ...

  10. sklearn 神经网络_机器学习100天-Day2404 循环神经网络RNN(预测时间序列)

    说明:本文依据<Sklearn 与 TensorFlow 机器学习实用指南>完成,所有版权和解释权均归作者和翻译成员所有,我只是搬运和做注解. 进入第二部分深度学习 第十四章循环神经网络 ...

最新文章

  1. VSCode使用笔记
  2. ubuntu16 kubernetes1.6安装(六、node节点部署)
  3. linux运行raxml,RAxML安装
  4. python学习手册中文版免费下载-Python学习手册(第3版)
  5. shiro+springboot分析思路
  6. gearhost php,Gearhost 免费主机的申请
  7. postgresql数据库基础
  8. python websocket django vue_Django资料 Vue实现网页前端实时反馈输出信息
  9. VB 将文件夹复制到指定目录
  10. WPF简单实用方法(持续更新)
  11. chromium/chrome内核修改、SEO快排搭建(2022最新源码)
  12. 【分享】RSS订阅技巧及工具和实用RSS链接分享
  13. DICOM影像中的窗宽窗位
  14. 嵌入式Linux驱动笔记(四)------USB键盘驱动程序
  15. 解决数据库高并发的常见方案
  16. 为什么Microsoft账号登录显示暂时停用你的账户_Apple ID 被锁定或停用怎么办?
  17. 网站域名未备案可以使用奇安信网站卫士吗?
  18. java项目:批量修改文件名字
  19. Fred Books图集
  20. 多多吐槽,心情会变好

热门文章

  1. Drools7.5.0教程-目录
  2. python人脸检测与微信小程序_微信小程序人脸识别功能
  3. 可能是最简单暴力的卸载工具Geek Uninstaller
  4. 在 Chrome 浏览器中安装印象笔记·剪藏插件
  5. 拉普拉斯平滑处理介绍
  6. 分享一个Atmega128L单片机在IAR for AVR中的串口1收发数据的例程
  7. 网络工程师--网络规划和设计案例分析(5)
  8. TCP/IP协议新手入门学习
  9. 实战python网络爬虫黄永祥_《实战Python网络爬虫》- 感想
  10. VMware Workstation 安装ssh服务器