循环神经网络(RNN)是一种特殊的神经网络,它能够处理序列数据。理论上,RNN的行为与人类大脑相似,能够以其他算法无法做到的方式处理序列数据。本文将深入探讨RNN的内部工作原理,并尝试以最简单的方式理解它。同时,也会探讨RNN面临的一些问题。
在RNN中,一次传递一个单词,但机器理解的是数字而非单词,因此不能直接将单词传递给模型。需要将单词转换为数字。以“Chirag在印度的微软工作”为例,首先需要创建一个词汇表,这个词汇表包含了已知的所有单词,但可以限制在几千个英文单词以内。假设单词“Chirag”在词汇表中的位置是“3456”,第二个单词的位置是“6969”。
一旦为单词赋予了数字,就可以将其输入模型,但在输入之前,还需要将这个数字转换为独热编码(One-hot representation)。独热编码是一个向量,除了在位置“3456”处的值为1外,其他所有值都是0。类似地,第二个单词的独热编码表示如下:
将单词转换为独热编码后,可以将它们输入网络。接下来,将深入了解这个算法的细节。在下一节中,将了解这个模型在内部是如何工作的。
在人工神经网络(ANN)中,下一层的激活是通过将权重乘以上一层的激活,加上一些偏置,然后传递给激活函数来计算的。对于RNN,将做类似的事情。方程将类似,但这里有两个输入,一个是来自前一层的激活,另一个是单词“X”。在ANN中,只有一个输入,因此只乘以一个权重矩阵,但在这里有两个输入,所以将有两个权重矩阵。方程看起来像这样:
Y = f(W_aa * A_prev + W_ax * X + b)
其中,Y的方程是:
这是1个RNN单元,并且在每个时间步,将计算一些激活值,并产生一些输出。因此,从更大的图景来看,它看起来像这样:
还看到,对于许多应用,如多对一应用,并不是在每个时间戳都有输出,而只有在最终单词处有输出。架构看起来像这样:
假设正在制作一个电影评分系统,其目的是根据给定的评论对电影进行1-5的评分。这个问题属于多对一架构。要理解RNN中的反向传播,这将是最好的架构来开始。
将在这里使用的损失函数是“分类交叉熵”:
现在让以更简单的方式理解反向传播是如何工作的。已经知道,在RNN中,相同的权重矩阵由所有单元在每个时间步共享,这意味着W_aa和W_ax在每个单元的所有时间戳中共享。这些权重矩阵只会在最终时间戳结束时更新。这意味着将通过时间向前移动,当到达句子的末尾时,将通过损失函数计算损失,并且基于这个损失值或错误,模型将尝试通过向后传播并更新这些权重(W_aa, W_ax和W_ay)来最小化这个错误。已经知道:
dL/dw = dL/dO * dO/dw
让从计算损失相对于W_ya的导数开始。如果仔细观察,会发现损失依赖于O,O依赖于W_ya,根据链式法则得到:
如果不理解这个公式是如何来的,那么不用担心,可以记住它,或者自己尝试推导它以练习。
在有了损失相对于W_ya的导数后,只需要将值放入权重更新公式中,即:
W_ya = W_ya - learning_rate * dL/dW_ya
这是较容易的部分,因为W_ya只出现在最终时间戳。更具挑战性的部分是获得W_aa和W_ax。
让计算损失相对于W_aa的导数。在这里,损失依赖于O,O依赖于a3,而a3依赖于W_aa。但故事并没有就此结束,因为如果看到相同的W_aa在所有时间戳中都有贡献,这意味着为了获得a3,即最终激活,激活a1和a2也有贡献,这也依赖于W_aa。
需要关注这个链,现在让在这个结构中反向传播或使用链式法则。
dL/dW_aa = dL/dO * dO/da3 * da3/dW_aa
类似地,可以计算损失相对于W_ax的导数,因为它们共享相同的故事。因此,方程将是:
dL/dW_ax = dL/dO * dO/da3 * da3/dW_ax
因此,已经获得了RNN反向传播所需的所有3个方程。
假设正在制作一个语法检查器,检查给定的句子是否语法正确。例如,在应用中输入句子,这会输出,“只是想让知道在那里,如果现在对自己非常苛刻,因为已经发生了一些事情……这是正常的”。
显然,这里应该是“yourself”而不是“herself”。这意味着如果使用RNN来创建语法检查器,那么这个NN应该建议这里应该是“yourself”而不是“herself”,但实际上RNN无法做到这一点。让看看为什么?
假设将句子传递给这个RNN,所有单词将逐一作为输入传递给这个RNN,但当将这个长句子传递给RNN时,它将无法识别这个错误。
在RNN中,这些隐藏状态被传递到下一个时间戳,并在每个时间戳更新。因此,当它到达句子的末尾或错误所在的位置时,a的值已经更新了很多次,几乎丢失了它在看到第一个单词或句子上下文时存在的信息。这就是为什么RNN的问题是,每当传递一个长句子时,它就会丢失很早之前的句子中的信息。它记得最后几个词的信息,但忘记了很久以前出现的词或信息。
这也可以通过反向传播来理解。推导出了损失相对于权重的导数,结果是一个方程:
dL/dW = dL/dO * dO/daT * daT/dW
这意味着当从时间戳T=t反向传播到时间戳T=1时,必须乘以很多梯度才能到达时间戳T=1,也知道梯度值的范围,它在0-1之间,这意味着梯度值是一个小数,如果一个小数一次又一次地相乘,它几乎接近0,这意味着在更新权重,即实际训练模型时,早期出现的词几乎没有发言权,这个问题被称为“梯度消失问题”。
在本文中,了解了RNN的内部工作原理。看了反向传播是如何在这个算法中工作的。然后看了RNN面临的问题以及为什么不再使用它。在下一篇文章中,将看到LSTM和GRU如何解决这些问题。在结束这篇文章之前,这里有一些关于构建RNN的实现细节。
对于第一个RNN块,由于没有先前的隐藏状态可用,通常输入一个零向量。在输入不同长度的文本时,填充每个文本,使每个序列长度相等。为了指定句子的开始和结束,可以使用标记。