RNN网络用循环来保持序列里元素彼此间的影响。但是有个基本假设就是一个元素受离他越近元素影响越大。离当前元素越远,影响越小。但是在自然语言里有些情况是例外的。
比如下边这句话:
“妻子每天上班很辛苦,早上要赶6点的班车去离家20公里的地方去上班,晚上下班还要赶回来给我做饭,她真是个顾家的人。”
不要在意内容,那是我编的。你需要注意的是句子最后的那个“她”字,之所以这里是“她”,而不是“他”,就是因为开始的“妻子”。这个“她”和对它产生决定影响的元素“妻子”,在序列里离得很远。我们之前的办法来训练RNN,效果就不好。

在了解GRU之前,我们先看一个正常的RNN unit

RNN Unit

GRU

Memory Cell 记忆单元

GRU里引入了一个新的单元Memory cell来提供记忆能力。我们用c来表示。比如上边那句话,记忆单元可以记住“妻子”是女性,后来在需要第三人称指代时会根据记忆选择“她”。下边我们看一下具体实现。
在GRU里,c^{<t>}就等于之前我们说的RNN里的a^{<t>},但是这里还是区别用两种符号,是为了和后来的LSTM unit来区别。

Gate

门函数是通过一个sigmoid函数来实现的。因为sigmoid函数的特性是它值域的大部分都接近于0或者1。只有中间一小部分值域是在0和1之间的。因此可以用它来模拟门的开和关。1代表开,让信号向下一次循环传递,0代表关,信号不会被传递给下一个循环。

门函数我们用符号\Gamma表示。
\Gamma=sigmoid(w[c^{<t-1>},x^{<t>}]+b)
需要注意的是这个sigmoid函数是对向量里的元素逐一应用的。所以门函数对向量w[c^{<t-1>},x^{<t>}]+b里的元素的打开或者关闭是不一样的。可以理解为某些特征允许传递下去,有些特征不能传递下去。

GRU的候选状态

之前我们说的RNN里每次循环都是更新状态a^{<t>}。在GRU里我们用一个记忆单元c^{<t>}来代替a^{<t>}在循环里保持状态,除此之外,在每次循环里还有一个候选状态\tilde{c}^{<t>}。在GRU更新本次循环的c^{<t>}会用到候选状态\tilde{c}^{<t>}
候选状态的公式为:
\tilde{c}^{<t>}=tanh(w_c[c^{<t-1>},x^{<t>}]+b_c)
实际上\tilde{c}^{<t>}的公式比上边的更复杂一点,就是加上了门函数来控制c^{<t-1>}有哪些元素可以进入本次循环的候选状态计算。
{\Gamma}_r=sigmoid(w_r[c^{<t-1>},x^{<t>}]+b_r)
\tilde{c}^{<t>}=tanh(w_c[{\Gamma}_r*c^{<t-1>},x^{<t>}]+b_c)

GRU里的状态更新

GRU里的状态更新由两部分构成,一个是当前循环产生的候选输出\tilde{c}^{<t>}。一个是上次循环状态c^{<t-1>}。他们两个向量的各个元素由一个门函数控制一起构成了本次循环的状态c^{<t>}
{\Gamma}_u=sigmoid(w_u[c^{<t-1>},x^{<t>}]+b_u)
c^{<t>}={\Gamma}_u*\tilde{c}^{<t>}+(1-{\Gamma}_u)*c^{<t-1>}

GRU只保留一个内部状态c^{<t>}。在计算这个内部状态时引入了候选状态\tilde{c}^{<t>}。在更新本次循环的内部状态向量c^{<t>}时,因为引入了门函数{\Gamma}_u。所以内部状态向量的每一个元素可以理解为在之前状态c^{<t-1>}和本次候选状态\tilde{c}^{<t>}两个值里边二选一。(因为{\Gamma}_u的取值大部分情况下近似于0或者1。)

GRU的输出

GRU的输出和之前说的RNN unit类似。对c^{<t>}再使用softmax等输出函数构成本次循环的输出。

希望下边这张图可以帮助你理解:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: