当前位置: 代码迷 >> 综合 >> RNN和梯度消失爆炸 cs224n
  详细解决方案

RNN和梯度消失爆炸 cs224n

热度:47   发布时间:2023-10-12 09:56:20.0

语言模型

说实话,这里是很重要。因为做一件事情首先需要明确的就是目的是什么?否则就会再后续的问题中迷失了方向。
什么是语言模型,视频中是指计算一个单词序列(句子)的概率P(w1,…,wm)P(w_1,…,w_m)P(w1?,,wm?)的模型。听上去很简单,做起来很难;听上去没什么用处,但用处非常多。比如在机器翻译中,判断译文序列中一种词序的自然程度高于另一种,判断一种用词选择优于另一种。
RNN和梯度消失爆炸 cs224n
这个图给我留下挺深的印象,nlp的时代已经从以前的传统到xgb全面迈入了深度学习的过程。

传统模型

为了简化问题,必须引入马尔科夫假设,句子的概率通常是通过待预测单词之前长度为n的窗口建立条件概率来预测:
P(w1,…,wm)=∏i=1i=mP(wi∣w1,…,wi?1)≈∏i=1i=mP(wi∣wi?n,…,wi?1)P(w_1,…,w_m) = \prod_{i=1}^{i=m} P(w_{i} | w_1, …, w_{i-1}) \approx \prod_{i=1}^{i=m} P(w_{i} | w_{i-n}, …, w_{i-1}) P(w1?,,wm?)=i=1i=m?P(wi?w1?,,wi?1?)i=1i=m?P(wi?wi?n?,,wi?1?)
为了估计此条件概率,常用极大似然估计,比如对于BiGram和TriGram模型,有
p(w2∣w1)=count(w1,w2)count(w1)p(w3∣w1,w2)=count(w1,w2,w3)count(w1,w2)p(w_2 | w_1) = \frac {count(w_1,w_2)}{count(w_1)} \\ p(w_3 | w_1, w_2) = \frac {count(w_1,w_2,w_3)}{count(w_1, w_2)} p(w2?w1?)=count(w1?)count(w1?,w2?)?p(w3?w1?,w2?)=count(w1?,w2?)count(w1?,w2?,w3?)?
在数据量足够的情况下,n-gram中的n越大,模型效果越好。但实际上,数据量总是不如人意,这时候一些平滑方法就不可或缺。另外,这些ngram可能会占用上G的内存,在最新的研究中,一个1260亿的语料在140G内存的单机上花了2.8天才得到结果。
缺陷:

  • 稀疏性
  • 计算量复杂

Recurrent Neural Networks

新的语言模型是利用RNN对序列建模,复用不同时刻的线性非线性单元及权值,理论上之前所有的单词都会影响到预测单词。
所需内存只与词表大小成正比,不取决于序列长度。
RNN和梯度消失爆炸 cs224n
给定一个词向量序列: x1,...,xt?1,xt,xt+1,...xTx_1,...,x_{t?1},x_t,x_{t+1},...x_Tx1?,...,xt?1?,xt?,xt+1?,...xT? ,在每个时间点上都有隐藏层的特征表示:

ht=σ(W(hh)ht?1+W(hx)xt)h_t=σ(W^{(hh)}h_t?1+W^{(hx)}x_t)ht?=σ(W(hh)ht??1+W(hx)xt?)
其中,

xt∈Rdx_t∈R^dxt?Rd:是时间t时输入的单词的词向量。

Whx∈RDh×dW^{hx}∈R^{D_h×d}WhxRDh?×d:用来condition输入词向量xtx_txt?的的权值矩阵。

Whh∈RDh×DhW^{hh}∈R^{D_h×D_h}WhhRDh?×Dh?:用来condition前一个时间节点隐藏层特征表示ht?1的权值矩阵。

ht?1∈RDh:h_{t?1}∈R^{D_h}:ht?1?RDh?: 前一个时间点 t?1 的非线性激活函数的输出, $h_0∈R^{D_h} 是时间点 t=0 时的隐藏层初始状态。

σ(): 非线性激活函数(sigmoid)

yt=softmax(W(S)ht)y^t=softmax(W^{(S)}h_t)yt=softmax(W(S)ht?):在时刻t时输出的整个词表 |V| 上的概率分布,yty^tyt是给定上文ht?1h_{t?1}ht?1?和最近的单词 x_{(t)}预测的下一个单词。其中W(S)∈R∣V∣×DhW^{(S)}∈R^{|V|×D_h}W(S)RV×Dh?yt∈R∣V∣y^t∈R|V|ytRV
损失函数,在大小为T的序列上的交叉熵误差为:
J=1T∑t=1TJ(t)(θ)=?1T∑t=1T∑j=1∣V∣yt,j×log(y^t,j)J = \dfrac{1}{T} \sum_{t=1}^{T} J^{(t)}(\theta) = - \dfrac{1}{T} \sum_{t=1}^{T} \sum_{j=1}^{|V|} y_{t,j} \times log (\hat{y}_{t,j})J=T1?t=1T?J(t)(θ)=?T1?t=1T?j=1V?yt,j?×log(y^?t,j?)

  • 看懂一个公式,理解公式中的各个维度很重要
  • y的理解很重要,它是根据上文和当前位置单词预测下一个单词的整个词表的概率分布
  • h0∈RDhh_0∈R^{D_h}h0?RDh? 是时间点 t=0 时的隐藏层初始状态,可能是平时大佬们常说的初始化
  • 前向传播的过程W是不会随t发生变化

梯度消失与爆炸

梯度下降,其实我听的不是很明白它是什么意思。
RNN和梯度消失爆炸 cs224n
而大于1时,浮点数运算会产生溢出(NaN),一般可以很快发现。这叫做梯度爆炸。小于1,或者下溢出并不产生异常,难以发现,但会显著降低模型对较远单词的记忆效果,这叫做梯度消失。

其实我不明白为什么要提出不等式小于(βwβh)(t?k)(\beta_w\beta_h)^{(t-k)}(βw?βh?)(t?k)

https://www.cnblogs.com/maybe2030/p/6336896.html
这里讲的就挺好的,就是因为网络的变多,所以再反向梯度的时候需要进行较多的连乘,导致了指数的增长或消失。
而且更重要的是:
不稳定的梯度问题: 根本的问题其实并非是消失的梯度问题或者激增的梯度问题,而是在前面的层上的梯度是来自后面的层上项的乘积。当存在过多的层次时,就出现了内在本质上的不稳定场景。唯一让所有层都接近相同的学习速度的方式是所有这些项的乘积都能得到一种平衡。如果没有某种机制或者更加本质的保证来达成平衡,那网络就很容易不稳定了。简而言之,真实的问题就是神经网络受限于不稳定梯度的问题。所以,如果我们使用标准的基于梯度的学习算法,在网络中的不同层会出现按照不同学习速度学习的情况。

预防措施:

梯度剪枝

一种暴力的方法是,当梯度的长度大于某个阈值的时候,将其缩放到某个阈值。虽然在数学上非常丑陋,但实践效果挺好
RNN和梯度消失爆炸 cs224n
每次迭代梯度本来是正常的,一次一小步,但遇到这堵墙之后突然梯度爆炸到非常大,可能指向一个莫名其妙的地方(实线长箭头)。但缩放之后,能够把这种误导控制在可接受的范围内(虚线短箭头)。
但这种trick无法推广到梯度消失,因为你不想设置一个最低值硬性规定之前的单词都相同重要地影响当前单词。因为步伐变大会慢慢变小,如果步伐规定了不能变小,其实就很难走到最小值。

减缓梯度消失

与其随机初始化参数矩阵,不如初始化为单位矩阵。这样初始效果就是上下文向量和词向量的平均。然后用ReLU激活函数。这样可以在step多了之后,依然使得模型可训练。

RNN和梯度消失爆炸 cs224n

困惑度

衡量语句的通顺度,这里自己也困惑过,这么虚的概念怎么衡量。

其基本思想是给测试集的句子赋予较高概率值的语言模型较好,当语言模型训练完之后,测试集中的句子都是正常的句子,那么训练好的模型就是在测试集上的概率越高越好。

迷惑度越小,句子概率越大,语言模型越好