基于 RNN 的语言模型

时间:2024-11-05 11:17:33

基于 RNN 的语言模型

循环神经网络(Recurrent Neural Network, RNN)是一类网络连接中包含环路的
神经网络的总称。
给定一个序列,RNN 的环路用于将历史状态叠加到当前状态上。沿着时间维度,历史状态被循环累积,并作为预测未来状态的依据。RNN 可以基于历史规律,对未来进行预测。
基于 RNN 的语言模型,以词序列作为输入,基于被循环编码的上文和当前词来预测下一个词出现的概率。

循环神经网络 RNN

按照推理过程中信号流转的方向,神经网络的正向传播范式可分为两大类:前馈传播范式和循环传播范式。
采用前馈传播范式的神经网络可以统称为前馈神经网络(Feed-forward Neural Network,FNN),
而采用循环传播范式的神经网络被统称为循环神经网络(Recurrent Neural Network, RNN)
在这里插入图片描述

前馈神经网络(FNN)

  • 计算是逐层向前的,没有反馈连接。
  • 输出仅依赖于当前输入,不考虑历史信息
计算公式
  1. 输入层

    • 假设输入向量为 x = [ x 1 , x 2 , . . . , x n ] \mathbf{x} = [x_1, x_2, ..., x_n] x=[x1,x2,...,xn]
  2. 隐藏层(如果有多个隐藏层,这个过程会重复):

    • 每个神经元的加权输入计算为 z = w 1 x 1 + w 2 x 2 + . . . + w n x n + b z = w_1x_1 + w_2x_2 + ... + w_nx_n + b z=w1x1+w2x2+...+wnxn+b,其中 w i w_i wi是权重, b b b是偏置项。
    • 激活函数 g ( z ) g(z) g(z)被应用于加权输入,以产生神经元的输出。常见的激活函数包括 Sigmoid、Tanh、ReLU 等。
    • 因此,隐藏层的输出 h h h可以表示为 h = g ( z ) = g ( w 1 x 1 + w 2 x 2 + . . . + w n x n + b ) h = g(z) = g(w_1x_1 + w_2x_2 + ... + w_nx_n + b) h=g(z)=g(w1x1+w2x2+...+wnxn+b)
  3. 输出层

    • 输出层的计算与隐藏层类似,但是输出层的输出通常不经过非线性激活函数(如果是分类问题,最后一层可能使用 Softmax 函数)。
    • 输出 o \mathbf{o} o可以表示为 o = f ( V h + b ) \mathbf{o} = f(Vh + b) o=f(Vh+b),其中 V V V是从隐藏层到输出层的权重矩阵, h h h是隐藏层的输出向量, b b b是输出层的偏置项, f f f是输出层的激活函数(对于回归问题, f f f可以是恒等函数)。

以一个具体的数学表达式来表示一个简单的FNN模型的前向传播过程:

假设有一个输入向量 x \mathbf{x} x,一个隐藏层,其权重矩阵为 W \mathbf{W} W,偏置向量为 b \mathbf{b} b,激活函数为 g g g,以及一个输出层,其权重矩阵为 V \mathbf{V} V,偏置向量为 b ′ \mathbf{b}' b,输出层激活函数为 f f f

  1. 计算隐藏层的加权输入和输出:
    z = W x + b \mathbf{z} = \mathbf{W}\mathbf{x} + \mathbf{b} z=Wx+b
    h = g ( z ) \mathbf{h} = g(\mathbf{z}) h=g(z)
  2. 计算输出层的加权输入和输出:
    o = V h + b ′ \mathbf{o} = \mathbf{V}\mathbf{h} + \mathbf{b}' o=Vh+b
    y = f ( o ) \mathbf{y} = f(\mathbf{o}) y=f(o)
    其中, y \mathbf{y} y是网络的最终输出。这个过程是逐层向前的,每一层的输出仅依赖于当前层的输入和权重,而不依赖于网络中其他层的历史信息。

循环神经网络(RNN)

RNN 的工作方式:

  • 输入序列被逐个元素地串行输入。具有循环连接,可以将之前的状态信息传递到后续的计算中。
  • 每个时间步的隐状态是前一个隐状态和当前输入的函数。输出不仅依赖于当前输入,还依赖于之前的所有输入,因为它们被编码在隐状态中。
  • 输出是当前隐状态的函数。
基本计算公式:
  1. 隐藏状态更新公式
    h t = f ( W h h h t − 1 + W x h x t + b h ) h_t = f(W_{hh}h_{t-1} + W_{xh}x_t + b_h) ht=f(Whhht1+Wxhxt+bh)

    • h t h_t ht是时间步 t t t的隐藏状态。
    • h t − 1 h_{t-1} ht1是时间步 t − 1 t-1 t1的隐藏状态。
    • x t x_t xt是时间步 t t t的输入。
    • W h h W_{hh} Whh是隐藏状态到隐藏状态的权重矩阵。
    • W x h W_{xh} Wxh是输入到隐藏状态的权重矩阵。
    • b h b_h bh是隐藏状态的偏置项。
    • f f f是激活函数,常用的激活函数包括tanh、ReLU等。
  2. 输出计算公式
    y t = g ( W h y h t + b y ) y_t = g(W_{hy}h_t + b_y) yt=g(Whyht+by)

    • y t y_t yt是时间步 t t t的输出。
    • W h y W_{hy} Why是隐藏状态到输出的权重矩阵。
    • b y b_y by是输出的偏置项。
    • g g g是输出层的激活函数,对于分类问题可能是softmax函数,对于回归问题可能是线性函数。

梯度衰减

问题描述
在RNN中,梯度需要通过时间反向传播,每一步的梯度计算都会涉及到前一步的权重。如果权重的导数(梯度)是小于1的正数,那么随着时间步的增加,梯度会指数级减少。这意味着对于较早时间步的输入,网络很难学习到它们对最终输出的影响。

解决方案

  1. 使用ReLU激活函数:相比于tanh或sigmoid,ReLU激活函数可以减轻梯度衰减问题,因为它的导数在正区间内是常数。
  2. 权重初始化:使用如Glorot初始化(Xavier初始化)或He初始化等方法,可以更好地控制梯度的大小。
  3. 梯度裁剪(Gradient Clipping):通过限制梯度的大小来防止梯度爆炸,间接缓解梯度衰减。
  4. 使用LSTM或GRU:这两种RNN的变体通过引入门控机制来减少梯度衰减的影响。

梯度爆炸

问题描述
与梯度衰减相反,梯度爆炸是指在反向传播过程中,梯度值随着时间步的增加而变得非常大,导致权重更新过大,从而使学习过程变得不稳定。

解决方案

  1. 梯度裁剪:在每次更新前,将梯度限制在一个合理的范围内,以防止梯度爆炸。
  2. 使用LSTM或GRU:这两种结构通过门控机制来控制信息流,从而减少梯度爆炸的风险。
  3. 正则化:如L1、L2正则化,可以限制权重的大小,间接控制梯度的大小。
  4. 使用批量归一化(Batch Normalization):在RNN中应用批量归一化可以帮助稳定梯度。
其他注意事项
  • 截断反向传播(Truncated Backpropagation Through Time, TBPTT):这种方法不是在整个序列上进行反向传播,而是在序列的一个小片段上进行,可以减少计算量并减轻梯度问题。
  • 调整学习率:使用自适应学习率算法,如Adam,可以帮助更好地控制学习过程。

基于循环神经网络(RNN)的语言模型

基于循环神经网络(RNN)的语言模型是一种序列生成模型,它能够根据当前词和之前的隐藏状态来预测下一个词的概率。

  1. 条件概率

    • 给定词序列 { w 1 , w 2 , … , w N } \{w_1, w_2, \ldots, w_N\} {w1,w2,,wN},RNN语言模型预测下一个词 w i + 1 w_{i+1} wi+1