CompModCogPsy
  • 全书介绍和写作计划
  • 第一章 计算认知科学导论
    • 前言
    • 1.1 交叉学科三角
    • 1.2 认知科学的特点
    • 1.3 认知科学的发展历史
    • 1.4 我们为什么需要计算认知
      • 1.4.1 认知科学的基础假设:信息处理理论
      • 1.4.2 挑战与“诞生”
      • 1.4.3 计算认知的必要性
  • 第二章 计算模型基础
    • 2.1 什么是计算模型?
    • 2.2 模型选择
    • 2.3 模型拟合
    • 2.4 模型准确度
    • 2.5 模型可信度
  • 第三章 概率推断和贝叶斯理论
    • 3.1 概率基础
    • 3.2 概率推断
      • 3.2.1 似然函数
      • 3.2.2 最大似然估计
    • 3.3 贝叶斯理论
    • 3.4 拓展阅读:p值
    • 3.5 编程练习-最大似然估计
  • 第四章 心理物理学和信号检测论
    • 心理物理学基础
    • 心理物理曲线
      • 几种常见的心理物理曲线
      • 拟合心理物理曲线
    • 信号检测论
      • dprime
      • 决策标准
      • receiver operating curve (ROC)曲线和area under curve (AUC)
      • dprime和AUC的关系
      • 2AFC的应用
      • Page
    • 展望
  • 第五章 近似推断
    • 马尔科夫链蒙特卡洛采样
      • Metropolis-Hasting算法
    • 变分推断
    • 展望
  • 第六章 知觉决策
    • 模拟一个简单知觉决策
    • 模拟决策和反应时
    • 权衡反应时和正确率
    • 6.4 经典漂移扩散模型
    • 漂移扩散模型的应用
      • 基于价值的决策
      • 精神疾病的应用
      • 社会认知
    • 展望
  • 第七章 价值决策
    • 人类决策基础
    • 前景理论
    • 风险决策
    • 展望
  • 第八章 强化学习
    • 机器学习强化学习基础
      • 动态规划
      • 时间差分学习
      • 基于模型和无模型强化学习
    • 心理学的强化学习
    • 强化学习的交叉关系
    • 强化学习模型和参数估计
    • Rescorlar-wagner模型
    • 二阶段任务
    • 展望
  • 第九章 社会决策和社会学习
    • 社会决策
    • 社会学习
    • 展望
  • 第十章 神经网络
    • 神经网络和心理学引言
    • 神经网络基础
      • 多层感知机
      • 卷积神经网络
      • 循环神经网络
    • 神经网络和人脑加工的关系
      • 感知觉的编解码
      • 工作记忆
      • 长时记忆
      • 学习和决策
    • 展望
由 GitBook 提供支持
在本页
  • RNN的基本结构
  • 隐状态(Hidden State)的定义与作用
  • 参数共享与时间步长
  • RNN的数据流和BPTT(Backpropagation Through Time)
  • 常见RNN架构
  • LSTM长短期记忆网络
  • GRU门控循环单元
  1. 第十章 神经网络
  2. 神经网络基础

循环神经网络

最后更新于9个月前

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

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

RNN的基本结构

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

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

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

ht=σ(Whxxt+Whhht−1+bh)h_t = \sigma(W_{hx} x_t + W_{hh} h_{t-1} + b_h)ht​=σ(Whx​xt​+Whh​ht−1​+bh​)

其中:

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

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

  • bhb_hbh​​ 是偏置项。

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

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

参数共享与时间步长

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

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

h1=σ(Whxx1+Whhh0+bh)h2=σ(Whxx2+Whhh1+bh)⋮hT=σ(WhxxT+WhhhT−1+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*}h1​h2​hT​​=σ(Whx​x1​+Whh​h0​+bh​)=σ(Whx​x2​+Whh​h1​+bh​)⋮=σ(Whx​xT​+Whh​hT−1​+bh​)​

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

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

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

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

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

  • 更新隐状态:

    ht=σ(Whxxt+Whhht−1+bh)h_t = \sigma(W_{hx} x_t + W_{hh} h_{t-1} + b_h)ht​=σ(Whx​xt​+Whh​ht−1​+bh​)

  • 计算输出:

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

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

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

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

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

∂L∂Why=∑t=1T∂ℓ(yt,y^t)∂yt⋅∂yt∂Why\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}}∂Why​∂L​=∑t=1T​∂yt​∂ℓ(yt​,y^​t​)​⋅∂Why​∂yt​​

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

∂L∂ht=∂ℓ(yt,y^t)∂ht+∂L∂ht+1⋅∂ht+1∂ht\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}∂ht​∂L​=∂ht​∂ℓ(yt​,y^​t​)​+∂ht+1​∂L​⋅∂ht​∂ht+1​​

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

∂L∂Whh=∑t=1T∂L∂ht⋅∂ht∂Whh\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}}∂Whh​∂L​=∑t=1T​∂ht​∂L​⋅∂Whh​∂ht​​

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

W←W−α∂L∂WW \leftarrow W - \alpha \frac{\partial \mathcal{L}}{\partial W}W←W−α∂W∂L​

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

常见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_tXt​​ 和前一时间步的隐藏状态 Ht−1H_{t-1}Ht−1​​,通过多个全连接层计算出输入门、遗忘门和输出门的值。具体公式如下:

  • 输入门(Input Gate)ItI_tIt​​:

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

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

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

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

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

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

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

Ct=Ft⋅Ct−1+It⋅C~tC_t = F_t \cdot C_{t-1} + I_t \cdot \tilde{C}_tCt​=Ft​⋅Ct−1​+It​⋅C~t​

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

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

Ht=Ot⋅tanh⁡(Ct)H_t = O_t \cdot \tanh(C_t)Ht​=Ot​⋅tanh(Ct​)

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

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

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

GRU门控循环单元

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

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

重置门的计算公式为:

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

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

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

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

其中,WzW_zWz​​ 是权重矩阵,bzb_zbz​​ 是偏置,σ\sigmaσ 是sigmoid激活函数。更新门的值ztz_tzt​​ 决定了新状态HtH_tHt​​ 和旧状态 Ht−1H_{t-1}Ht−1​​ 的权重比例。

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

H~t=tanh⁡(Wh[Rt∗Ht−1,Xt]+bh)\tilde{H}_t = \tanh(W_h [R_t * H_{t-1}, X_t] + b_h)H~t​=tanh(Wh​[Rt​∗Ht−1​,Xt​]+bh​)

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

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

Ht=Zt∗Ht−1+(1−Zt)∗H~tH_t = Z_t * H_{t-1} + (1 - Z_t) * \tilde{H}_tHt​=Zt​∗Ht−1​+(1−Zt​)∗H~t​

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

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