循环神经网络

卷积神经网络通常处理的是静态数据,如一张图片,而在现实生活中,我们同样需要处理动态数据,特别是时间序列数据。在这些发展中,循环神经网络(Recurrent Neural Networks, RNN) 扮演了至关重要的角色。RNN的设计初衷是为了处理序列数据,例如时间序列、文本、语音、视频等。

传统的神经网络(如MLP)在处理时间序列数据时存在显著的局限性。它们假设所有输入是相互独立的,这种假设在处理具有时间依赖性的任务时表现不佳。例如,在自然语言处理中,一个单词的含义往往依赖于前后文的信息,这种依赖性无法被捕捉到。而循环圣经网络则通过引入循环连接,使得网络能够在处理序列数据时记住前面的信息,并将其影响到后续的计算中。这种循环连接使得RNN具有“记忆”功能,可以在处理当前输入时参考之前的输入,从而捕捉序列数据中的时间依赖性和上下文信息。下面我们就来一起学习RNN相关的知识。

RNN的基本结构

在前面学习过的多层感知机和卷积神经网络中,数据流是单向的,从输入层经过层层中间的隐藏层到输出层。而在RNN中,数据流存在循环机制,使得网络能够捕捉数据中的时序依赖关系。我们以下图来简单说明,只考虑最左边的那一部分时,RNN和普通的MLP是类似的。图中左侧的红色虚线箭头表示 RNN 的隐状态的循环连接。隐状态不仅依赖于当前时间步的输入,还会反馈给自己,影响下一个时间步的计算。这是 RNN 能够捕捉时间序列数据中时序依赖关系的关键。图中从左到右分别为从t=1 t=1t=Tt=T^′ 展开显示。每个时间步都有自己的输入数据和对应的隐藏层状态,后面的时间步依赖于前面的隐藏层状态。展开后的图形类似于前馈神经网络的层级结构,但每层之间的连接是通过时间步上的递归关系(循环)实现的。每一层的输出会作为下一时间步的输入,这样,后续时间步的隐藏层不仅受到当前输入的影响,还会受到之前时间步的信息。图中的红色箭头表示了这种时间步间的信息传递。

隐状态(Hidden State)的定义与作用

隐状态 hth_t​ 是RNN的核心,它携带了前序时间步的信息,并随着时间步的推进而更新。隐状态的更新方式通常为:

ht=σ(Whxxt+Whhht1+bh)h_t = \sigma(W_{hx} x_t + W_{hh} h_{t-1} + b_h)

其中:

  • WhxW_{hx}是输入到隐状态的权重矩阵。

  • WhhW_{hh}​ 是隐状态到隐状态的权重矩阵。

  • bhb_h​ 是偏置项。

  • σ\sigma 是非线性激活函数,如tanh或ReLU。

隐状态的作用在于捕捉并存储序列数据的上下文信息,从而使得RNN能够在处理长序列时,保留早期的关键信息并在后续的时间步中加以利用。

参数共享与时间步长

在RNN中,参数共享 是一个重要的特性,无论是在哪个时间步 tt,网络中的这些权重矩阵 ,Whx,Whh,WhyW_{hx}, W_{hh}, W_{hy}​ 和偏置 bh,byb_h, b_y​ 都是固定的,也就是说它们在整个序列的时间步中是共享的。这种参数共享大大减少了模型的参数数量,使得RNN在处理长序列时更为高效。

由于参数共享,RNN可以通过在时间维度上展开(unrolling) 的方式进行表示。时间展开将RNN的递归计算转化为一个时间步长上的链式结构,其中每一层都代表RNN在某一时间步的操作。展开后的RNN网络展示了如何在每个时间步中使用相同的参数集:

h1=σ(Whxx1+Whhh0+bh)h2=σ(Whxx2+Whhh1+bh)hT=σ(WhxxT+WhhhT1+bh)\begin{align*} h_1 &= \sigma(W_{hx} x_1 + W_{hh} h_0 + b_h) \\ h_2 &= \sigma(W_{hx} x_2 + W_{hh} h_1 + b_h) \\ &\vdots \\ h_T &= \sigma(W_{hx} x_T + W_{hh} h_{T-1} + b_h) \end{align*}

RNN的数据流和BPTT(Backpropagation Through Time)

RNN的前向传播中,对于每个时间步,输入数据 xtx_t 与前一时间步的隐状态ht1h_{t-1}​ 一起进入网络。通过权重矩阵和激活函数,计算出当前时间步的隐状态 hth_t​。根据当前时间步的隐状态 hth_t​ 生成输出yty_t​。当前时间步的隐状态 hth_t​ 传递到下一个时间步,作为 ht+1h_{t+1}​ 的输入。前向传播的结果是生成每个时间步的输出,并更新隐状态,直至处理完整个序列。

由于在RNN中,每个时间步的计算依赖于前一个时间步的隐状态,为了训练RNN,我们需要将RNN在时间维度上展开,将每个时间步视为一层网络。与标准的反向传播算法(BP, Backpropagation)类似,RNN采用BPTT来更新网络中的权重。

在前向传播过程中,RNN逐步处理输入序列的每一个时间步,生成每个时间步的隐状态 hth_t​ 和输出 yty_t。这些隐状态和输出将用于后续的反向传播计算。

在每个时间步,前向传播的过程可以用以下公式表示:

  • 更新隐状态:

    ht=σ(Whxxt+Whhht1+bh)h_t = \sigma(W_{hx} x_t + W_{hh} h_{t-1} + b_h)

  • 计算输出:

    yt=ϕ(Whyht+by)y_t = \phi(W_{hy} h_t + b_y)

通过前向传播计算每个时间步的输出后,接下来我们会计算总的损失函数 L\mathcal{L}。损失函数通常是时间步误差的总和:

L=t=1T(yt,y^t)\mathcal{L} = \sum_{t=1}^T \ell(y_t, \hat{y}_t)

其中,yty_t​ 是RNN的输出,y^t\hat{y}_t​ 是目标值,\ell 是损失函数(例如交叉熵或均方误差)。

接下来,我们计算损失函数对输出层权重WhyW_{hy}​ 的梯度:

LWhy=t=1T(yt,y^t)ytytWhy\frac{\partial \mathcal{L}}{\partial W_{hy}} = \sum_{t=1}^T \frac{\partial \ell(y_t, \hat{y}_t)}{\partial y_t} \cdot \frac{\partial y_t}{\partial W_{hy}}

每个时间步 tt 对隐状态的梯度 Lht\frac{\partial \mathcal{L}}{\partial h_t}​会被传递给前一个时间步 t1t−1,影响之前时间步的梯度计算:

Lht=(yt,y^t)ht+Lht+1ht+1ht\frac{\partial \mathcal{L}}{\partial h_t} = \frac{\partial \ell(y_t, \hat{y}_t)}{\partial h_t} + \frac{\partial \mathcal{L}}{\partial h_{t+1}} \cdot \frac{\partial h_{t+1}}{\partial h_t}

由于RNN中的参数是共享的,我们还需要计算损失函数对隐状态到隐状态权重WhhW_{hh}​ 的梯度:

LWhh=t=1TLhthtWhh\frac{\partial \mathcal{L}}{\partial W_{hh}} = \sum_{t=1}^T \frac{\partial \mathcal{L}}{\partial h_t} \cdot \frac{\partial h_t}{\partial W_{hh}}

一旦通过BPTT计算出梯度,我们就来更新RNN中的权重:

WWαLWW \leftarrow W - \alpha \frac{\partial \mathcal{L}}{\partial W}

其中,α\alpha 是学习率,WW 是需要更新的权重矩阵。

常见RNN架构

LSTM长短期记忆网络

LSTM(Long Short-Term Memory)网络是在传统RNN的基础上提出的一种改进模型,专门用于解决RNN中常见的梯度消失和梯度爆炸 问题。LSTM由Hochreiter和Schmidhuber于1997年提出,通过引入记忆单元(Memory Cell) 和 门控机制(Gating Mechanisms),LSTM能够有效地在长序列数据中保留关键信息,从而在序列建模任务中表现出色。

LSTM通过门控机制来控制信息的流动,具体包括以下三类门:输入门(Input Gate):控制新输入对记忆单元的影响。遗忘门(Forget Gate):控制之前记忆单元中的信息有多少应该被保留或遗忘。输出门(Output Gate):控制记忆单元的信息有多少可以用于生成当前时间步的输出。

LSTM的核心在于通过这些门控机制来灵活地控制信息的存储和更新。在每个时间步,LSTM的输入包括当前时间步的输入 XtX_t​ 和前一时间步的隐藏状态 Ht1H_{t-1}​,通过多个全连接层计算出输入门、遗忘门和输出门的值。具体公式如下:

  • 输入门(Input Gate)ItI_t​:

It=σ(Wi[Ht1,Xt]+bi)I_t = \sigma(W_i [H_{t-1},X_t] + b_i)
  • 遗忘门(Forget Gate) FtF_t​:

Ft=σ(Wf[Ht1,Xt]+bf)F_t = \sigma(W_f [H_{t-1}, X_t] + b_f)
  • 输出门(Output Gate) OtO_t​:

Ot=σ(Wo[Ht1,Xt]+bo)O_t = \sigma(W_o [H_{t-1}, X_t] + b_o)

其中,WW 是权重矩阵,bb 是偏置,σ\sigma 是sigmoid激活函数,用于将门值限制在 [0,1][0, 1] 之间。

此外,输入节点(Input Node) 是通过tanh激活函数计算的,用于生成当前输入对记忆单元的候选更新值 C~t\tilde{C}_t​:

C~t=tanh(WC[Ht1,Xt]+bC)\tilde{C}_t = \tanh(W_C [H_{t-1}, X_t] + b_C)

记忆单元的更新过程结合了输入门和遗忘门的值,计算出新的记忆单元状态 CtC_t​。遗忘门 ftf_t​ 控制了之前记忆单元 Ct1C_{t-1}​ 的保留比例,输入门 ItI_t​ 决定了当前候选记忆 C~t\tilde{C}_t​ 有多少会写入到记忆单元:

Ct=FtCt1+ItC~tC_t = F_t \cdot C_{t-1} + I_t \cdot \tilde{C}_t

通过这种设计,LSTM能够灵活地决定在每个时间步中应保留多少历史信息,同时引入新的信息。

记忆单元的状态 CtC_t​ 保留了序列中的重要信息,而隐藏状态(Hidden State) HtH_t​ 则是LSTM的输出,并传递到下一时间步。隐藏状态通过输出门和当前记忆单元的状态共同决定:

Ht=Ottanh(Ct)H_t = O_t \cdot \tanh(C_t)

在此过程中,输出门 OtO_t​ 控制了当前时间步的记忆单元对输出的影响。如果 OtO_t​ 的值接近1,当前记忆单元会对输出产生较大影响;如果OtO_t​ 的值接近0,则当前记忆单元的信息不会对输出产生影响。

LSTM在解决RNN中的梯度消失问题上具有明显优势,主要体现在以下几个方面:

LSTM网络通过引入记忆单元和门控机制,有效解决了RNN中的梯度消失问题,使得网络能够在长序列中保留和处理关键信息。LSTM的遗忘门、输入门和输出门为信息的存储和更新提供了极大的灵活性,这使得LSTM在自然语言处理、时间序列预测和语音识别等任务中得到了广泛应用。

GRU门控循环单元

门控循环单元(Gated Recurrent Unit, GRU)是由Cho等人在2014年提出的一种简化的循环神经网络架构。GRU减少了LSTM中的门控机制,将LSTM中的三个门(输入门、遗忘门、输出门)简化为两个:重置门(Reset Gate) 和 更新门(Update Gate)。这种设计使得GRU能够保留LSTM的一些核心功能,同时在计算效率上有显著提升。

重置门控制着先前的隐状态 ht1h_{t-1}​ 有多少信息能够保留并参与当前时间步的计算。通过这一机制,GRU能够动态选择性地遗忘历史信息,从而适应短期依赖。

重置门的计算公式为:

Rt=σ(Wr[Ht1,Xt]+br)R_t = \sigma(W_r [H_{t-1}, X_t] + b_r)

其中,WrW_r​ 是权重矩阵,brb_r​ 是偏置,σ\sigma 是sigmoid激活函数。rtr_t​ 的值越接近1,表示保留更多的历史信息;值越接近0,表示更多地遗忘过去的隐状态。

更新门决定了当前时间步的新状态 hth_t​ 是保留多少之前的隐状态,还是更新为新的候选状态。更新门类似于LSTM中的遗忘门和输入门的结合,它平衡了旧信息和新信息的融合,适应了长期依赖。更新门的计算公式为:

Zt=σ(Wz[Ht1,Xt]+bz)Z_t = \sigma(W_z [H_{t-1}, X_t] + b_z)

其中,WzW_z​ 是权重矩阵,bzb_z​ 是偏置,σ\sigma 是sigmoid激活函数。更新门的值ztz_t​ 决定了新状态HtH_t​ 和旧状态 Ht1H_{t-1}​ 的权重比例。

GRU中的重置门不仅控制信息的遗忘,还决定了旧隐状态在生成候选隐状态(Candidate Hidden State) H~t\tilde{H}_t​ 时的作用。候选隐状态表示可能作为当前时间步新隐状态的一个备选值,最终的新隐状态还需要结合更新门的影响。候选隐状态的计算公式为:

H~t=tanh(Wh[RtHt1,Xt]+bh)\tilde{H}_t = \tanh(W_h [R_t * H_{t-1}, X_t] + b_h)

其中,重置门 RtR_ t 与先前的隐状态进行Hadamard积,从而控制历史信息的参与程度。通过这种方式,GRU可以在某些情况下完全重置先前的隐状态(当 RtR_t 约等于0时),或者保留大部分历史信息(当RtR_t ​约等于1时)。

在计算了候选隐状态后,GRU通过更新门ZtZ_t​ 来控制最终的新隐状态 HtH_t​。更新门 ZtZ_t​ 决定新隐状态 HtH_t​ 是更接近旧的隐状态Ht1H_{t-1}​,还是更接近新的候选隐状态H~t\tilde{H}_t​。

Ht=ZtHt1+(1Zt)H~tH_t = Z_t * H_{t-1} + (1 - Z_t) * \tilde{H}_t

ZtZ_t​ 接近1时,GRU更倾向于保留旧隐状态 Ht1H_{t-1}​,而当 ZtZ_t​ 接近0时,GRU则倾向于更新为新的候选隐状态 H~t\tilde{H}_t​。这种设计允许GRU在必要时保持对历史信息的长时间依赖,也能够快速调整为新的状态。

GRU是一种高效的循环神经网络架构,通过引入重置门和更新门,GRU在处理长短期依赖时能够有效地控制信息的流动。相较于LSTM,GRU具有更简化的结构和更高的计算效率,因此在处理大规模序列任务时得到了广泛应用。

最后更新于