前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习 学习笔记(24) 序列建模:循环和递归网络

机器学习 学习笔记(24) 序列建模:循环和递归网络

作者头像
发布2018-09-04 10:58:24
1.8K0
发布2018-09-04 10:58:24
举报
文章被收录于专栏:WD学习记录WD学习记录

循环神经网络(recurrent nerual network)或RNN是一类用于处理序列数据的神经网络,就像卷积网络是专门用于处理网格化数据X的神经网络。循环神经网络是专门用于处理序列

x^{(1)},...,x^{(\tau )}
x^{(1)},...,x^{(\tau )}

的神经网络。循环网络可以扩展到更长的序列(比不基于序列的特化网络长得多)。大多数循环网络也能处理可变长度的序列。

在模型的不同部分,共享参数,参数共享使得模型能够扩展到不同形式的样本(这里指不同长度的样本)并进行泛化。如果我们在每个时间点都有一个单独的参数,不但不能泛化到训练时没有见过的序列长度,也不能在时间上共享不同序列长度和不同位置的统计强度。当信息的特定部分会在序列内多个位置出现时,这样的共享尤为重要。

在一维序列上使用卷积,这种卷积方法是延时神经网络的基础。卷积操作允许网络跨时间共享参数,但是浅层的。卷积的输出是一个序列,其中输出中的每一项是相邻几项输入的函数。参数共享的概念体现在每个时间步中使用相同的卷积核。循环神经网络以不同的方式共享参数。输出的每一项是前一项的函数。输出的每一项对先前的输出应用相同的更新规则而产生。这种循环方式刀子参数通过很深的计算图共享。

通常指RNN是在序列上的操作,并且该序列在时刻t(从1到

\tau
\tau

)包含向量

x^{(\tau )}
x^{(\tau )}

。在实际情况中,循环网络通常在序列的小批量上操作,并且小批量的每项具有不同长度

\tau
\tau

。省略了小批量索引来简化记号。此外,时间步索引不必是字面上现实世界中流逝的时间,有时,它仅仅表示序列中的位置。RNN也可以应用于跨越两个维度的空间数据(如图像)。当应用于涉及时间的数据,并且将整个序列提供给网络之前就能观察到整个序列时,该网络可具有关于时间向后的连接。

将计算图的思想扩展到包括循环,这些周期代表变量自身的值在未来某一时间步对自身的影响。这样的计算图允许我们定义循环神经网络。然后,我们描述许多构建、训练和使用循环神经网络的不同方式。

展开计算图

展开递归或循环计算得到重复结构,这些重复结构对应于一个事件链。展开这个计算图将导致深度网络结构中的参数共享。

动态系统的经典形式为:

s^{(t)}=f(s^{(t-1)};\theta )
s^{(t)}=f(s^{(t-1)};\theta )

,其中

s^{(t)}
s^{(t)}

称为系统的状态。s在时刻t定义需要参考时刻t-1时同样的定义。因此是循环的。

对有限时间步

\tau
\tau

\tau -1
\tau -1

次应用这个定义可以展开这个图。例如

\tau =3
\tau =3

时,

s^{(3)}=f(s^{(2)};\theta )=f(f(s^{(1)};\theta );\theta )
s^{(3)}=f(s^{(2)};\theta )=f(f(s^{(1)};\theta );\theta )

,以这种方式重复应用定义,展开等式,就能得到不涉及循环的表达。使用传统有向无环计算图来呈现:

考虑由外部信号

x^{(t)}
x^{(t)}

驱动的动态系统:

s^{(t)}=f(s^{(t-1)},x^{(t)};\theta )
s^{(t)}=f(s^{(t-1)},x^{(t)};\theta )

,当前状态包含了整个过去序列的信息。

循环神经网络可以通过许多不同的方式建立。就像几乎所有函数都可以被认为是前馈网络,本质上任何实际循环的函数都可以视为一个循环神经网络。

常使用如上的公式来定义隐藏单元的值。用h代表状态重写:

h^{(t)}=f(h^{(t-1)},x^{(t)};\theta )
h^{(t)}=f(h^{(t-1)},x^{(t)};\theta )

如上图所示,典型的RNN会增加额外的架构特性,如读取h状态进行预测的输出层。

当训练循环网络根据过去预测未来时,网络通常要学会使用

h^{(t)}
h^{(t)}

作为过去序列(直到t)与任务相关方面的有损摘要。此摘要一般而言一定是有损的,因为其映射任意长度的序列

(x^{(t)},x^{(t-1)},x^{(t-2)},...,x^{(2)},x^{(1)})
(x^{(t)},x^{(t-1)},x^{(t-2)},...,x^{(2)},x^{(1)})

到固定长度的向量

h^{(t)}
h^{(t)}

根据不同的训练准则,摘要可能选择性地精确保留过去序列的某些方面。例如:如果在统计语言建模中使用的RNN,通常给定前一个词预测下一个词,可能没必要存储时刻t前输入序列中的所有信息,而仅仅存储足够预测句子其他部分的信息。最苛刻的情况是要求

h^{(t)}
h^{(t)}

足够丰富,并能大致恢复输入序列,如自编码器框架。

用一个函数

g^{(t)}
g^{(t)}

代表经过t步展开后的循环:

h^{(t)}=g^{(t)}(x^{(t)},x^{(t-1)},...,x^{(2)},x^{(1)})=f(h^{(t-1)},x^{(t)};\theta)
h^{(t)}=g^{(t)}(x^{(t)},x^{(t-1)},...,x^{(2)},x^{(1)})=f(h^{(t-1)},x^{(t)};\theta)

。函数

g^{(t)}
g^{(t)}

将全部的过去序列

(x^{(t)},x^{(t-1)},...,x^{(2)},x^{(1)})
(x^{(t)},x^{(t-1)},...,x^{(2)},x^{(1)})

作为输入来生成当前状态,但是展开的循环架构允许我们将

g^{(t)}
g^{(t)}

分解为函数f的重复应用。因此,展开过程主要有两个优点:(1)无论序列的长度,学成的模型始终具有相同的输入大小,因为它指定的是从一种状态到另一种状态的转移,而不是在可变长度的历史状态上操作。(2)我们可以在每个时间步使用相同参数的相同转义函数f。

这两个因素使得学习在所有时间步和所有序列长度上操作单一模型f时可能的,而不需要在所有可能的时间步学习独立的模型

g^{(t)}
g^{(t)}

。学习单一的共享模型允许泛化到没有见过的序列长度(没有出现在训练集中),并且估计模型所需的训练样本远远少于不带参数共享的模型。

无论是循环图还是展开图,都有其用途。循环图简洁,展开图能够明确描述其中的计算流程。展开图还通过显式的信息流动路径帮助说明信息在时间上向前(计算输出和损失)和向后(计算梯度)的思想。

循环神经网络

循环神经网络中的一些重要的设计模型包括以下几种:

(1)每个时间步都有输出,并且隐藏单元之间有循环连接的循环网络。

(2)每个时间步都产生一个输出,只有当前时刻的输出到下个时刻的隐藏单元之间有循环连接的循环网络。

(3)隐藏单元之间存在循环连接,但读取整个序列后产生单个输出的循环网络。

任何图灵计算否可以通过这样一个有限维的循环网络计算,在这个意义上图10.3和公式

a^{t}=b+Wh^{(t-1)}+Ux^{(t)}
a^{t}=b+Wh^{(t-1)}+Ux^{(t)}

的循环神经网络是万能的。RNN经过若干时间步后读取输出,这与图形机所用的时间步是渐近线性的,与输入长度也是渐近线性的。由图灵机计算的函数是离散的,所以这些结果都是函数的具体实现,而不是近似。RNN作为图灵机使用时,需要一个二进制序列作为输入,其输出必须是离散化以提供二进制输出。

研究图10.3中RNN前向传播公式,假设使用双曲正切激活函数,假设输出的离散的,如用于预测词或者字符的RNN,表示离散变量的常规方式是把输出o作为每个离散变量可能值的非标准化对数概率。然后,我们可以用softmax函数后续处理后,获得标准化后的概率的输出向量

\hat{y}
\hat{y}

。RNN从特定初始状态

h^{(0)}
h^{(0)}

开始前向传播,从

t=1
t=1

t=\tau
t=\tau

的每个时间步,应用以下方程:

a^{t}=b+Wh^{(t-1)}+Ux^{(t)}
a^{t}=b+Wh^{(t-1)}+Ux^{(t)}
h^{(t)}=tanh(a^{(t)})
h^{(t)}=tanh(a^{(t)})
o^{(t)}=c+Vh^{(t)}
o^{(t)}=c+Vh^{(t)}
y^{(t)}=softmax(o^{(t)})
y^{(t)}=softmax(o^{(t)})

其中参数的偏置向量b和c连同权重矩阵U、V和W分别对应于输入到隐藏、隐藏到输出和隐藏到隐藏的连接。这个循环网络将一个输入序列映射到相同长度的输出序列。

与x序列配对的y的总损失就是所有时间步的损失之和,例如,

L^{(t)}
L^{(t)}

为给定的

x^{(1)},...,x^{(t)}
x^{(1)},...,x^{(t)}

后的

y^{(t)}
y^{(t)}

的负对数似然,则:

L(\{x^{(1)},...,x^{(\tau )}\},\{y^{(1)},y^{(\tau )}\})=\sum_{t}L^{(t)}=-\sum_t log p_{model}(y^{(t)}|\{x^{(1)},...,x^{(t)}\})
L(\{x^{(1)},...,x^{(\tau )}\},\{y^{(1)},y^{(\tau )}\})=\sum_{t}L^{(t)}=-\sum_t log p_{model}(y^{(t)}|\{x^{(1)},...,x^{(t)}\})

其中

p_{model}(y^{(t)}|\{x^{(1)},...,x^{(t)}\})
p_{model}(y^{(t)}|\{x^{(1)},...,x^{(t)}\})

需要读取模型输出向量

\hat{y}^{(t)}
\hat{y}^{(t)}

中对应于

y^{(t)}
y^{(t)}

的项。关于各个参数计算这个损失函数的梯度时计算成本很高的操作,梯度计算涉及执行一次前向传播(图10.3展开图中从左到右的传播),接着是从右到左的反向传播。运行时间是

O(\tau )
O(\tau )

,并且不能通过并行化来降低,因为前向传播图是固有循序的,每个时间步只能一前一后的进行计算。前向传播中的各个状态必须保存,直到它们反向传播中被再次使用,因此内存代价也是

O(\tau )
O(\tau )

。应用于展开图且代价为

O(\tau )
O(\tau )

的反向传播算法称为通过时间反向传播(back-propagation through time,BPTT)。隐藏单元之间存在的循环网络非常强大但是训练代价也很大。

导师驱动过程和输出循环网络

仅在一个时间步的输出和下一个时间步的隐藏单元间存在循环连接的网络确实没有那么强大(因为缺乏隐藏到隐藏之间的连接)。因为缺少隐藏到隐藏的循环,它要求输出单元捕捉用于预测未来的关于过去的所有信息。因为输出单元明确地训练成匹配训练集的目标,它们不太能捕获关于过去输入历史的必要信息,除非用户知道如何描述系统的全部状态,并且将它作为训练目标的一部分。消除隐藏到隐藏的优点在于:任何基于比较时刻t的预测和时刻t的训练目标的损失函数中的所有时间步都解耦了。因此训练可以并行化,即在各时刻t分别计算梯度,因为训练集提供输出的理想值,所以没有必要先计算前一时刻的输出。

由输出反馈到模型而产生循环的连接模型可以用导师驱动过程进行训练。训练模型时,导师驱动过程不再使用最大似然准则,而在时刻t+1接收真实值

y^{(t)}
y^{(t)}

作为输入。通过检查两个时间步的序列可得知,条件最大似然准则是:

logp(y^{(1)},y^{(2)}|x^{(1)},x^{(2)})=logp(y^{(2)}|y^{(1)},x^{(1)},x^{(2)})+log p(y^{(1)}|x^{(1)},x^{(2)})
logp(y^{(1)},y^{(2)}|x^{(1)},x^{(2)})=logp(y^{(2)}|y^{(1)},x^{(1)},x^{(2)})+log p(y^{(1)}|x^{(1)},x^{(2)})

使用导师驱动过程最初动机是为了在缺乏隐藏到隐藏连接的模型中避免通过时间反向传播。只有模型的一个时间步的输出与下一时间步的计算的值存在连接,导师驱动过程仍然可以应用到这些存在隐藏连接的模型。然而,只有隐藏单元成为较早时间步的函数,BPTT算法是必要的。因此训练某些模型时间要同时使用导师驱动过程和BPTT。

如果之后网络在开环(open-loop)模式下使用,即网络输出(或输出分布样本)反馈作为输入,那么完全使用导师驱动过程进行训练的缺点就会出现,在这种情况下,训练期间该网络看到的输入与测试时看到的会有很大不同。减轻此问题的一种方法是同时使用导师驱动过程和自由运行的输入进行训练,例如在展开循环的输出到输入路径上预测几个步骤的正确目标值。通过这种方式,网络可以学会考虑在训练时没有接触到的输入条件(如自由运行模式下,自身生成自身),以及将状态映射回使网络几步支行生成正确输出的状态。另一种方式是通过随意选择生成值或真实的数据值作为输入以减小训练时和测试时看到的输入之间的差别。这种方法利用了课程学习策略,逐步使用更多生成值作为输入。

计算循环神经网络的梯度

计算循环神经网络的梯度是容易的。可以简单地将推广反向传播算法应用于展开的计算图,不需要特殊的算法。由反向传播计算得到的梯度,并结合任何通用的基于梯度的技术就可以训练RNN。

通过BPTT计算

a^{t}=b+Wh^{(t-1)}+Ux^{(t)}
a^{t}=b+Wh^{(t-1)}+Ux^{(t)}

L(\{x^{(1)},...,x^{(\tau )}\},\{y^{(1)},y^{(\tau )}\})=\sum_{t}L^{(t)}=-\sum_t log p_{model}(y^{(t)}|\{x^{(1)},...,x^{(t)}\})
L(\{x^{(1)},...,x^{(\tau )}\},\{y^{(1)},y^{(\tau )}\})=\sum_{t}L^{(t)}=-\sum_t log p_{model}(y^{(t)}|\{x^{(1)},...,x^{(t)}\})

的梯度。

计算图节点包括参数U、V、W、b和c以及t为索引的节点序列

x^{(t)}
x^{(t)}

h^{(t)}
h^{(t)}

o^{(t)}
o^{(t)}

L^{(t)}
L^{(t)}

。对于每一节点N,需要基于N后面的节点的梯度,递归地计算梯度

\nabla_NL
\nabla_NL

。从最终损失节点开始递归:

\frac{\partial L}{\partial L^{(t)}}=1
\frac{\partial L}{\partial L^{(t)}}=1

在这个导数中,假设输出

o^{(t)}
o^{(t)}

作为softmax函数的参数,可以从softmax函数可以获得关于输出概率的向量

\hat{y}
\hat{y}

。也假定损失是迄今为止给定了输入之后的真实目标

y^{(t)}
y^{(t)}

的负对数似然。对于所有i、t,关于时间步t输出的梯度

\nabla_{o^{(t)}}L
\nabla_{o^{(t)}}L

如下:

(\nabla_{o^{(t)}}L)_i=\frac{\partial L}{\partial o^{(t)}_i}=\frac{\partial L}{\partial L^{(T)}}\frac{\partial L^{(T)}}{\partial o^{(t)}_i}=\hat{y}^{(t)}_i-1_{i,y^{(t)}}
(\nabla_{o^{(t)}}L)_i=\frac{\partial L}{\partial o^{(t)}_i}=\frac{\partial L}{\partial L^{(T)}}\frac{\partial L^{(T)}}{\partial o^{(t)}_i}=\hat{y}^{(t)}_i-1_{i,y^{(t)}}

从序列的末尾开始,反向进行计算,在最后的时间步

\tau
\tau

h^{(\\tau )}
h^{(\\tau )}

只有

o^{(\tau )}
o^{(\tau )}

作为后续节点,因此梯度很简单:

\nabla_{h^{(\tau )}}L=V^T\nabla_{o^{(\tau )}}L
\nabla_{h^{(\tau )}}L=V^T\nabla_{o^{(\tau )}}L

然后们可以从时刻

t=\tau -1
t=\tau -1

到t=1反向迭代,通过时间反向传播梯度,注意

h^{(t)}(t<\tau )
h^{(t)}(t<\tau )

同时具有

o^{(t)}
o^{(t)}

h^{(t+1)}
h^{(t+1)}

两个后续节点,因此它的梯度为:

\nabla_{h^{(t)}}L=(\frac{\partial h^{(t+1)}}{\partial h^{(t)}})^T(\nabla_{h^{(t+1)}}L)+(\frac{\partial o^{(t)}}{\partial h^{(t)}})^T(\nabla_{o^{(t)}}L)
\nabla_{h^{(t)}}L=(\frac{\partial h^{(t+1)}}{\partial h^{(t)}})^T(\nabla_{h^{(t+1)}}L)+(\frac{\partial o^{(t)}}{\partial h^{(t)}})^T(\nabla_{o^{(t)}}L)
=W^T(\nabla_{h^{(t+1)}}L)diag(1-(h^{(t+1)})^2)+V^T(\nabla_{o^{(t)}}L)
=W^T(\nabla_{h^{(t+1)}}L)diag(1-(h^{(t+1)})^2)+V^T(\nabla_{o^{(t)}}L)

其中

diag(1-(h^{(t+1)})^2)
diag(1-(h^{(t+1)})^2)

表示包含元素

1-(h^{(t+1)}_i)^2
1-(h^{(t+1)}_i)^2

的对角矩阵。这是关于时刻t+1与隐层单元i关联的双曲正切Jacobian。

一旦获得了计算图内部结点的梯度,就可以得到关于参数节点的梯度,因为参数在许多时间步共享,必须在表示这些变量的微积分操作时谨慎对待。微积分中的

\nabla_Wf
\nabla_Wf

算子,计算W对于f的贡献时将计算图中的所有边都考虑进去了。为了消除这种奇异,定义只在t时刻使用的虚拟变量

W^{(t)}
W^{(t)}

作为W的副本,然后,使用

\nabla_{W^{(t)}}
\nabla_{W^{(t)}}

表示权重在时间步t对梯度的贡献。

剩下的参数梯度如下:

\nabla_cL=\sum_t(\frac{\partial o^{(t)}}{\partial c})^T\nabla_{o^{(t)}}L=\sum_t \nabla_{o^{(t)}}L
\nabla_cL=\sum_t(\frac{\partial o^{(t)}}{\partial c})^T\nabla_{o^{(t)}}L=\sum_t \nabla_{o^{(t)}}L
\nabla_bL=\sum_t(\frac{\partial h^{(t)}}{\partial b^{(t)}})^T\nabla_{h^{(t)}}L=\sum_tdiag(1-(h^{(t)})^2)\nabla_{h^{(t)}}L
\nabla_bL=\sum_t(\frac{\partial h^{(t)}}{\partial b^{(t)}})^T\nabla_{h^{(t)}}L=\sum_tdiag(1-(h^{(t)})^2)\nabla_{h^{(t)}}L
\nabla_VL=\sum_t \sum_i(\frac{\partial L}{\partial o^{(t)}_i})\nabla_Vo^{(t)}_i=\sum_t(\nabla_{o^{(t)}}L)(h^{(t)})^T
\nabla_VL=\sum_t \sum_i(\frac{\partial L}{\partial o^{(t)}_i})\nabla_Vo^{(t)}_i=\sum_t(\nabla_{o^{(t)}}L)(h^{(t)})^T
\nabla_WL=\sum_t\sum_i(\frac{\partial L}{\partial h^{(t)}_i})\nabla_{W^{(t)}}h^{(t)}_i=\sum_tdiag(1-(h^{(t)})^2)(\nabla_{h^{(t)}}L)(h^{(t-1)})^T
\nabla_WL=\sum_t\sum_i(\frac{\partial L}{\partial h^{(t)}_i})\nabla_{W^{(t)}}h^{(t)}_i=\sum_tdiag(1-(h^{(t)})^2)(\nabla_{h^{(t)}}L)(h^{(t-1)})^T
\nabla_UL=\sum_t\sum_i(\frac{\partial L}{\partial h^{(t)}_i})\nabla _{U^{(t)}}h^{(t)}_i=\sum_tdiag(1-(h^{(t)})^2)(\nabla_{h^{(t)}}L)(x^{(t)})^T
\nabla_UL=\sum_t\sum_i(\frac{\partial L}{\partial h^{(t)}_i})\nabla _{U^{(t)}}h^{(t)}_i=\sum_tdiag(1-(h^{(t)})^2)(\nabla_{h^{(t)}}L)(x^{(t)})^T

因为计算图中定义的损失的任何参数都不是训练数据

x^{(t)}
x^{(t)}

的父节点,所以我们不需要计算关于它的梯度。

作为有向图模型的循环网络

原则上循环网络几乎可以使用任何损失,但必须根据任务来选择损失。如前馈网络,通常我们希望将RNN的输出解释为一个概率分布,并且通常使用与分布相关联的交叉熵来定义损失。均方误差是与单位高斯分布的输出相关联的交叉熵损失。

当使用一个预测性对数似然的训练目标,将RNN训练为能够根据之前的输入估计下一个序列元素

y^{(t)}
y^{(t)}

的条件分布,这意味着,我们最大化对数似然:

logp(y^{(t)}|x^{(1)},...,x^{(t)})
logp(y^{(t)}|x^{(1)},...,x^{(t)})

或者,如果模型包括来自一个时间步的输出到下一个时间步的连接:

logp(y^{(t)}|x^{(1)},...,x^{(t)},y^{(1)},...,y^{(t-1)})
logp(y^{(t)}|x^{(1)},...,x^{(t)},y^{(1)},...,y^{(t-1)})

将整个序列y联合分布分解为一些列单步的概率预测时捕获关于整个序列完整联合分布的一种方法。如果我们不把过去的y值反馈给下一步作为预测的条件,那么有向图模型不包含任何过去

y^{(i)}
y^{(i)}

到当前

y^{(t)}
y^{(t)}

的边。在这种情况下,输出y与给定的x序列是条件独立的。如果我们反馈真实的y值(不是他们的预测值,而是真正观测到或生成的值)给网络,那么有向图模型包含所有从过去

y^{(i)}
y^{(i)}

到当前

y^{(t)}
y^{(t)}

的边。

图模型中的边表示哪些变量直接依赖于其他变量,许多图模型的目标是省略不存在强相互作用的边以实现统计和计算的效率。

通常可以做Markov假设,即图模型应该包含从

\{y^{(t-k)},...,y^{(t-1)}\}
\{y^{(t-k)},...,y^{(t-1)}\}

y^{(t)}
y^{(t)}

的边,而不是包含整个过去历史的边。然而,在一些情况下,我们认为整个过去的输入会对序列的下一个元素有一定影响。当我们认为

y^{(t)}
y^{(t)}

的分布可能取决于遥远的过去(在某种程度)的

y^{(i)}
y^{(i)}

的值,且无法通过

y^{(t-1)}
y^{(t-1)}

捕获

y^{(i)}
y^{(i)}

的影响时,RNN会很有用。

将隐藏单元

h^{(t)}
h^{(t)}

视为随机变量,从而产生RNN的图模型结构。在图模型中包括隐藏单元于是RNN能对观测的联合分布提供非常有效的参数化。假设我们用表格表示法来表示离散值上任意的联合分布,即对每个值可能的赋值分配一个单独的条目数组,该条目表示发生该赋值的概率。如果y可以取k个不同的值,表格表示法将有

O(k^\tau)
O(k^\tau)

个参数,对比RNN,由于有参数共享,RNN的参数数目为

O(1)
O(1)

且是序列长度的函数。可以调节RNN的参数数量来控制模型容量,但不用被迫与序列长度成正比。

上图中,在图模型中结合

h^{(t)}
h^{(t)}

节点可以用作过去和未来之间的中间量,从而将它们解耦。遥远过去的变量

y^{(i)}
y^{(i)}

可以通过h的影响来影响变量

y^{(t)}
y^{(t)}

。该图的结构可以表明在时间步使用相同的条件概率分布有效参数化模型,并且当观察到全部变量时,可以高效地评估联合分配给所有变量的概率。

即便使用高效参数化的图模型,某些操作在计算上仍然具有挑战性。

循环网络为了减少参数的数目付出的代价是优化参数可能变得困难。

在循环网络中使用的参数共享的前提是相同参数可用于不同时间步的假设,也就是说,假设给定时刻t的变量后,时刻t+1的变量的条件概率分布时平稳的。这意味着之前的时间步与下个时间步之间的关系并不依赖于t。原则上,可以使用t作为每个时间步的额外输入,并且让学习器在发现任何时间依赖性的同时,在不同时间步之间尽可能多的共享。

为了完整描述将RNN作为图模型的观点,我们必须描述如何从模型采样。需要执行的主要操作是简单地从每一时间步的条件分布采样。然而,这会导致额外的复杂性。RNN必须有某种机制来确定序列的长度。可以通过多种方式实现。

当输出是从词汇表获取的符号的情况下,我们可以添加一个对应于序列末端的特殊符号,当产生该符号时,采样过程停止,在训练集中,我们将该符号作为序列的一个额外成员,即紧跟每个训练样本

x^{(\tau)}
x^{(\tau)}

之后。

另一种选择使在模型中引入一个额外的Bernoulli输出,表示在每个时间步决定继续生成或停止生成。相比向词汇表增加一个额外符号,这种方法更普遍,因为它适用于任何RNN,而不仅仅是输出符号序列的RNN。

确定序列长度

\tau
\tau

的另一种方法是将一个额外输出添加到模型并预测整数

\tau
\tau

本身。模型可以采出

\tau
\tau

的值,然后采

\tau
\tau

步有价值的数据,这种方法需要在每个时间步的循环更新中增加一个额外输入,使得循环更新知道它是否靠近所产生序列的末尾。这种额外的输入可以使

\tau
\tau

的值,也可以是

\tau-t
\tau-t

剩下时间步的数量。如果没有这个额外的输入,RNN可能会产生突然结束序列,如一个句子在最终完整前结束。

基于上下文的RNN序列建模

之前讨论了将

t=1,...,\tau
t=1,...,\tau

的向量

x^{(t)}
x^{(t)}

序列作为输入的RNN。另一种选择使只使用单个向量x作为输入,当x时一个固定大小的向量时,我们可以简单地将其看做产生y序列RNN的额外输入。将额外输入提供到RNN的一些常见方法是:

(1)在每个时刻作为一个额外输入,或

(2)作为初始状态

h^{(0)}
h^{(0)}

,或

(3)结合两种方式。

第一种也是最常见的方法,如上图。输入x和每个隐藏单元向量

h^{(t)}
h^{(t)}

之间的相互作用是通过新引入的权重矩阵R参数化的,这只是包含了y序列的模型所没有的。同样的乘积

x^TR
x^TR

在每个时间步作为隐藏单元的一个额外输入,可以认为x的选择使有效地用于每个隐藏单元的一个新的偏置参数。权重与输入保持独立。我们可以认为这种模型采用了非条件模型的

\theta
\theta

,并将

w
w

带入

\theta
\theta

,其中w内的偏置参数现在是输入的函数。

RNN可以接受向量序列

x^{(t)}
x^{(t)}

作为输入,而不是仅接收单个向量x作为输入。

a^{t}=b+Wh^{(t-1)}+Ux^{(t)}
a^{t}=b+Wh^{(t-1)}+Ux^{(t)}

描述得RNN对应条件分布

P(y^{(1)},...,y^{(\tau)}|(x^{(1)},...,x^{(\tau)})
P(y^{(1)},...,y^{(\tau)}|(x^{(1)},...,x^{(\tau)})

,并在条件独立的假设下这个分布分解为:

\prod_{t}P(y^{(t)}|x^{(1)},...,x^{(t)})
\prod_{t}P(y^{(t)}|x^{(1)},...,x^{(t)})

可以在时刻t的输出到时刻t+1的隐藏单元添加连接,如图:

该模型就可以代表关于y序列的任意概率分布。这种给定一个序列表示另一个序列分布的O型的还是有一个限制,就是两个序列的长度必须是相同的。

双向RNN

在许多应用中,要输出的

y^{(t)}
y^{(t)}

的预测可能依赖于整个输入序列。例如,在语音识别中,由于协同发音,当前声音作为因素的正确解释可能取决于未来的几个因素,甚至潜在的可能取决于未来的几个词,因为词与附近的词之间存在语义依赖:如果当前的词有两种声学上的合理解释,我们可能要在更远的未来(和过去)寻找信息区分它们。

双向循环神经网络(或双向RNN)为满足这种需要而发明。

双向RNN结合时间上从序列起点开始移动的RNN和另一个时间上从序列末尾开始移动的RNN。

其中

h^{(t)}
h^{(t)}

代表通过时间向前移动的子RNN的状态,

g^{(t)}
g^{(t)}

代表通过时间向后移动的子RNN的状态。这允许

o^{(t)}
o^{(t)}

能够计算同时依赖于过去和未来的且对时刻t的输入值最敏感的表示,而不必指定t周围固定大小的窗口(这是前馈网络、卷积网络或具有固定大小的先行缓存器的常规RNN所必须要做的)。

这个想法可以自然地扩展到二维输入,如图像,由4个RNN组成,每一个沿着4个方向中的一个计算:上、下、左、右。如果RNN能够学习到承载长期信息,那在二维网格每个点(i,j)输出的

O_{i,j}
O_{i,j}

就能计算一个能捕捉到大多局部信息但仍依赖于长期输入的表示。相比卷积网络,应用于图像的RNN计算成本通常更高,但允许同一特征图的特征之间存在长期横向的相互作用。实际上,对于这样的RNN,前向传播公式可以写成使用卷积的形式,计算自底向上到每一层的输入。

基于编码-解码的序列到序列架构

RNN可以将输入序列映射成固定大小的向量,RNN将固定大小的向量映射成一个序列,也可以将一个输入序列映射到等长得输出序列。

如何将输入序列映射到不一定等长得输出序列?在语音识别、机器翻译或问答中,其中训练集的输入和输出序列的长度通常不相同。

经常讲RNN的输入称为上下文,希望产生次上下文的表示C。这个上下文C可能是一个概括输入序列

X=(x^{(1)},x^{(2)},...,x^{(n_x)})
X=(x^{(1)},x^{(2)},...,x^{(n_x)})

的向量或者向量序列。

前一系统是对另一个机器翻译系统产生的建议进行评分,而后者使用独立的循环网络生成翻译。这些作者分别将该架构称为编码-解码或序列到序列架构。

上图中所示:(1)编码器(encoder)或读取器(reader)或输入(input)RNN处理输入序列。编码器输出上下文C(通常是最终隐藏状态的简单函数)(2)解码器(decoder)或写入器(writer)或输出(output)RNN则以固定长度的向量为条件产生输出序列

Y=(y^{(1)},...,y^{(n_y)})
Y=(y^{(1)},...,y^{(n_y)})

。在序列到序列的架构中,两个RNN共同训练以最大化

log P(y^{(1)},...,y^{(n_y)}|x^{(1)},...,x^{(n_x)})
log P(y^{(1)},...,y^{(n_y)}|x^{(1)},...,x^{(n_x)})

(关于训练集中所有x和y对的平均)。编码器RNN最后一个状态

h_{n_x}
h_{n_x}

通常被当做输入的表示C并做为解码器RNN的输入。

如果上下文C是一个向量,则解码器RNN知识向量到序列的RNN。向量到序列RNN至少有两种接收输入的方法。输入可以被提供为RNN的初始状态,或连接到每个时间步中的隐藏单元。

并不强制要求编码器也解码器的隐藏层具有相同的大小。

此架构一个明显不足是,编码器RNN输出的上下文C的维度太小而难以适当地概括一个长序列。C可以成为一个可变长度的序列,而不是一个固定大小的向量。还引入将序列C的元素和输出序列的元素相关联的注意力机制。

深度循环网络

大多数RNN中的计算可以分解成3块参数及其相关的变换:

(1)从输入到隐藏状态

(2)从前一隐藏状态到下一隐藏状态

(3)从隐藏状态到输出。

当网络被展开时,每个块对应一个浅的变换。能通过深度MLP内单个层来表示的变换称为浅变换。通常,这是由学成的仿射变换和一个固定非线性表示组成的变换。

将RNN的状态分为多层有显著的好处,在上图(a)中,层次结构中较低的层起到了将原始输入转化为对更高层的隐藏状态更合适的表示的作用。上述3个块中各使用一个单独的MLP(可能是深度的),如图(b)所示。考虑表示容量,建议在这3步中都分配足够的容量,但增加深度可能会因为优化困难而损害学习效果。在一般情况下,更容易优化较浅的架构,加入图(b)的额外深度导致从时间步t到时间步t+1的最短路径变得更长。例如,如果具有单个隐藏层的MLP被用于状态到状态的转换,那么图10.3相比,就会加倍任何两个不同时间步变量之间最短路径的长度。在隐藏层与隐藏的路径中引入跳跃连接可以缓和这个问题,如图(c)所示。

递归神经网络

递归神经网络代表循环网络的另一个扩展,被构造为深的树状结构而不是RNN的链状结构。因此是不同类型的计算图。

这种网络的潜在用途,学习推论。递归网络已成功地应用于输入是数据结构的神经网络,如自然语言处理和计算机视觉。

递归网络的一个明显优势是,对于具有相同长度的

\tau
\tau

的序列,深度(通过非线性操作的组合数量来衡量)可以急剧地从

\tau
\tau

减小为

O(log \tau )
O(log \tau )

,这可能有助于解决长期依赖。一个悬而未决的问题是如何以最佳的方式构造树。一种选择是使用不依赖于数据的树结构,如平衡二叉书。在某些领域,外部方法可以为选择适当的树结构提供借鉴。例如,处理自然语言的句子时,用于递归网络的树结构可以被固定为句子语法分析树的结构(可以由自然语言法分析程序提供)。理想的情况下,人们希望学习器可以自行发现和推断适合于任意给定输入的树结构。

长期依赖的挑战

经过许多阶段传播后的梯度倾向于消失(大部分情况)或者爆炸(很少,但是对优化过程影响很大)。即使我们假设循环网络是参数稳定的(可存储记忆、且梯度不爆炸),但长期依赖的困难来自比短期相互作用指数小的权重。循环网络涉及相同函数的多次组合,每个时间步一次。这些组合可以导致极端非线性行为:

RNN梯度消失和爆炸问题是由不同研究人员独立发现。有人可能会希望通过简单地停留在梯度不消失或爆炸的参数空间来避免这个问题。不幸的是,为了存储记忆并对小扰动具有鲁棒性,RNN必须进入参数空间中的梯度消失区域。具体来说,每当模型能够表示长期依赖时,长期相互作用的梯度幅值就会变得指数小(相比短期相互作用的梯度幅值)。这并不意味着这是不可能学习的,由于长期依赖关系的信号很容易被短期相关性产生的最小波动隐藏,因而学习长期依赖可能需要很长时间。

回声状态网络

h^{(t-1)}
h^{(t-1)}

h^{(t)}
h^{(t)}

的循环权重映射以及从

x^{(t)}
x^{(t)}

h^{(t)}
h^{(t)}

的输入权重映射是循环网络中最难学习的参数。避免这种困难的方法是设定循环隐藏单元,使其能很好低捕捉过去输入历史,并且只学习输出权重。回声状态网络(echo state network)或ESN以及流体状态机(liquid state machines)分别独立地提出了这种想法。后者是类似的,不过它使用了脉冲神经元(二值输出)而不是ESN中的连续隐藏单元。ESN和流体状态机都被称为储层计算(reservoir computing),因为隐藏单元形成了可能捕获输入历史不同方面的临时特征池。

储层计算循环网络类似于核机器,这是思考他们的一种方式:它们将任意长度的序列(到时刻t的输入历史)映射为一个长度固定的向量(循环状态

h^{(t)}
h^{(t)}

),之后可以试驾一个线性预测算子(通常是一个线性回归)以解决感兴趣的问题,训练准则就可以很容易地设计为输出权重的凸函数。例如,如果输出是从隐藏单元到输出目标的线性回归,训练准则就是均方误差,由于是凸的,就可以用简单学习算法可靠地解决。

重要的问题是:如何设置输入和循环权重,才能让一组丰富的历史可以在循环神经网络的状态中表示?储层计算研究给出的答案是将循环神经网络视为动态系统,并设定让动态系统接近稳定边缘的输入和循环权重。

用于设置ESN权重的技术可以用来初始化完全可训练的循环网络的权重(通过时间反向传播来训练隐藏到隐藏的循环权重),帮助学习长期依赖。

渗漏单元和其他多时间尺度的策略

处理长期依赖的一种方法是设计工作在多个时间尺度的模型,使模型的某些部分在细粒度时间尺度上操作并能处理小细节,而其他部分在粗时间尺度上操作并把遥远过去的信息更有效地传递过来。存在多种同时构建粗细时间尺度的策略。这些策略包括在时间轴增加跳跃连接,“渗漏单元”使用不同时间常数整合信号。

时间维度的跳跃连接

增加从遥远过去的变量到目前变量的直接连接是得到粗时间尺度的一种方法。

梯度可能关于时间步数呈指数消失或爆炸,引入了d延时的循环链接以减轻这个问题。导数指数减小的速度与

\frac{\tau }{d}
\frac{\tau }{d}

相关而不是

\tau
\tau

。既然同时存在延迟和单步链接,梯度仍然可能成t指数爆炸,这允许学习算法捕获更长的依赖性,但不是所有的长期依赖都能在这种方式下良好表示。

渗漏单元和一系列不同的时间尺度

获得导数乘积接近1的另一种方式是设置线性自连接单元,并且将这些连接的权重接近1。

对某些v值应用更新

\mu^{(t)}\leftarrow \alpha\mu^{(t-1)}+(1-\alpha )v^{(t)}
\mu^{(t)}\leftarrow \alpha\mu^{(t-1)}+(1-\alpha )v^{(t)}

累积一个滑动平均值

\mu ^{(t)}
\mu ^{(t)}

,其中

\alpha
\alpha

是一个从

\mu ^{(t-1)}
\mu ^{(t-1)}

\mu ^{(t)}
\mu ^{(t)}

线性自连接的例子。当

\alpha
\alpha

接近1时,滑动平均值能记住过去很长一段时间的信息,而当

\alpha
\alpha

接近0,关于过去的信息被迅速丢弃,线性自连接的隐藏单元可以模拟滑动平均的行为。这种隐藏单元称为渗漏单元(leaky unit)。

d时间步的跳跃连接可以确保单元总能被d个时间步前的那个值影响。使用权重接近1的线性自连接是确保该单元可以访问过去值得不同方式。线性自连接通过调节实值

\alpha
\alpha

更平滑灵活地调整这种效果,而不是调整整数值的跳跃长度。

在回声状态网络中,渗漏单元被发现很有用。

可以通过两种基本策略设置渗漏单元使用的时间常数。一种策略是手动将其固定为常数,例如在初始化时从某些分布采样它们的值。另一种策略是使时间常数成为自由变量,并学习出来。在不同时间尺度使用这样的渗漏单元似乎能帮助学习长期依赖。

删除连接

处理长期依赖的另一种方法是在多个时间尺度组织RNN状态的想法,信息在较慢的时间尺度上更容易长距离流动。

这个想法与之前讨论的时间维度上的跳跃连接不同,因为它涉及主动删除长度为一的连接并用更长的连接替换它们。以这种方式修改的单元被迫在长时间尺度上运作。而通过时间跳跃连接是添加边,收到这种新连接的单元,可以学习在长时间尺度上运作,但也可以专注自己的其它短期连接。

强制一组循环单元在不同时间尺度上运作有不同的方式。一种是选择使循环单元变成渗漏单元,但不同的单元组关联不同的固定时间尺度。另一种选择是使显式且离散的更新发生在不同的时间,不同的单元组有不同的频率。

长短期记忆和其他门控RNN

实际应用中很有效的序列模型称为门控RNN(gated RNN)。包括基于长短期记忆(long short-term memory)和基于门控循环单元(gated recurrent unit)的网络。

门控RNN的想法也是基于生成通过时间的路径,其中导数既不消失也不发生爆炸。渗漏单元通过手动选择常量的连接权重或参数化的连接权重来达到这一目的。门控RNN将其推广为在每个时间步都可能改变的连接权重。

渗漏单元允许网络在较长持续时间内积累信息。然而,一旦该信息被使用,让神经网络遗忘旧的状态可能是有用的。例如:如果一个序列是由子序列组成,我们希望渗漏单元能在各子序列内积累线索,需要将状态设置为0以忘记旧状态的极值。希望神经网络学会何时清除状态,而不是手动决定。这就是门控RNN要做的事情。

LSTM

引入自循环的巧妙构思,以产生梯度长时间持续性流动的路径是初始长短期记忆(long short-term memory,LSTM)的核心贡献。其中一个关键扩展是使自循环的权重视上下文而定,而不是固定的。门控此自循环(由另一个隐藏单元控制)的权重,累积的时间尺度可以动态地改变。在这种情况下,即使是具有固定参数的LSTM,累积的时间尺度也可以因输入序列而改变,因为时间常数时模型本身的输出。LSTM在无约束手写识别、语音识别、手写生成、机器翻译、为图像生成标题和解析这些应用中都取得了重大成功。

LSTM循环网络除了外部的RNN循环外,还具有内部的LSTM细胞循环(自环),因此LSTM不是简单地项输入和循环单元的放射变换后施加一个逐元素的非线性。与普通的玄幻网络类似,每个单元由相同的输入和输出,但也有更多的参数和控制信息流的门控单元系统。最重要的组成部分是状态单元

s^{(t)}_i
s^{(t)}_i

,与渗漏单元由类似的线性自环。然而,此处自环的权重(或相关联的时间常数)由遗忘门

f^{(t)}_i
f^{(t)}_i

控制(时刻t和细胞i),有sigmoid单元将权重设置为0和1之间的值。

LSTM网络比简单的循环架构更易于学习长期依赖。

其他门控RNN

门控循环单元或GRU,与LSTM的主要区别是,单个门控单元同时控制遗忘因子和更新状态单元的决定。

优化长期依赖

截断梯度

梯度截断有不同的实例。一种选择是在参数更新之前,逐元素地截断小批量产生的参数梯度。另一种是在参数更新之前截断梯度g的范数||g||。

if ||g||>v
if ||g||>v

g\leftarrow \frac{gv}{||g||}
g\leftarrow \frac{gv}{||g||}

v是范数上界,g用来更新参数。因为所有参数(包括不同的参数组,如权重和偏置)的梯度被单个缩放因子联合重整话,所以后一方法具有的优点是保证了每个步骤仍然是在梯度方向上的,但实验表明两种形式类似。

引导信息流正则化

梯度截断有助于处理爆炸的梯度,但是无助于消失的梯度。

在展开循环架构的计算图中,沿着与弧边相关联的梯度乘积接近1的部分创建路径。实现这一点的一种方法是使用LSTM以及其它自循环和门控机制。另一个想法是正则化或约束参数,以引导信息流。

特别是即使损失函数只对序列尾部的输出做惩罚,也希望梯度向量

\nabla_{h^{(t)}}L
\nabla_{h^{(t)}}L

在反向传播时能维持其幅度。形式上要使:

(\nabla_{h^{(t)}}L)\frac{\partial h^{(t)}}{\partial h^{(t-1)}}
(\nabla_{h^{(t)}}L)\frac{\partial h^{(t)}}{\partial h^{(t-1)}}

(\nabla_{h^{(t)}}L)
(\nabla_{h^{(t)}}L)

一样大。在这个目标下,有一个正则项被提出:

\Omega =\sum_t(\frac{||(\nabla_{h^{(t)}}L)\frac{\partial h^{(t)}}{\partial h^{(t-1)}}||}{||\nabla_{h^{(t)}}L||}-1)^2
\Omega =\sum_t(\frac{||(\nabla_{h^{(t)}}L)\frac{\partial h^{(t)}}{\partial h^{(t-1)}}||}{||\nabla_{h^{(t)}}L||}-1)^2

,计算这一荼毒的正则项可能会出现困难,但是可以将后向传播向量

\nabla_{h^{(t)}}L
\nabla_{h^{(t)}}L

考虑为恒值作为近似(为了计算正则化的目的,没有必要通过它们向后传播)。

如果与标准的启发式截断(处理梯度爆炸)相结合,正则项可以显著地增加RNN可学习的依赖跨度。梯度截断特别重要,因为它保证了爆炸梯度边缘的RNN胴体,如果没有梯度截断,梯度爆炸将阻碍学习的成功。

这种方法的主要弱点是:在处理数据冗余任务时,如语言模型,并不像LSTM一样有效。

外显记忆

神经网络擅长存储隐性知识,但是很难记住事实。被存储在神经网络之前,随机梯度下降需要多次提供相同的输入,即使如此,该输入也不会被特别精确地存储。这是因为神经网络缺乏工作存储系统,即类似人类为实现一些目标而明确保存和操作相关信息片段的系统。这种外显记忆组件将使我们的系统不仅能够快速“故意”地存储和检索具体的事实,也能利用他们循序推论。神经网络处理序列信息的需要,改变了每个步骤向网络注入输入的方式,长期以来推理能力被认为是重要的,而不是对输入做出自动的、直观的反映。

为解决这一难题,记忆网络被引入,其中包括一组可以通过寻址机制来访问的记忆单元,记忆网络原本需要监督信号指示它们如何使用自己的记忆单元。神经网络图灵机(neural Turing machine)不需要明确地监督指示采取哪些行动而能学习从记忆单元读写任意内容,并通过使用基于内容的软注意机制,允许端到端的训练。这种软寻址机制已经成为其他允许基于梯度优化的模拟算法机制的相关架构标准。

参考:

  1. 《深度学习》
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年08月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 展开计算图
  • 循环神经网络
    • 导师驱动过程和输出循环网络
      • 计算循环神经网络的梯度
        • 作为有向图模型的循环网络
          • 基于上下文的RNN序列建模
          • 双向RNN
          • 基于编码-解码的序列到序列架构
          • 深度循环网络
          • 递归神经网络
          • 长期依赖的挑战
          • 回声状态网络
          • 渗漏单元和其他多时间尺度的策略
            • 时间维度的跳跃连接
              • 渗漏单元和一系列不同的时间尺度
                • 删除连接
                • 长短期记忆和其他门控RNN
                  • LSTM
                    • 其他门控RNN
                    • 优化长期依赖
                      • 截断梯度
                        • 引导信息流正则化
                        • 外显记忆
                        • 参考:
                        相关产品与服务
                        语音识别
                        腾讯云语音识别(Automatic Speech Recognition,ASR)是将语音转化成文字的PaaS产品,为企业提供精准而极具性价比的识别服务。被微信、王者荣耀、腾讯视频等大量业务使用,适用于录音质检、会议实时转写、语音输入法等多个场景。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档