让我向您展示什么是RNNs,它们在哪里使用,它们如何向前和向后传播以及如何在PyTorch中使用它们。大多数类型的神经网络都会对它们训练的样本进行预测。一个典型的例子是MNIST数据集。像MLP这样的常规神经网络知道有10个数字,即使图像与训练网络的图像有很大不同,它也会仅根据它们进行预测。现在,假设我们可以使用这个网络进行顺序分析,方法是向它提供9个有序数字的序列并要求网络猜测第10个数字。网络不仅知道如何区分10位数字,而且还知道从0到8的序列,下一个数字可能是9。在分析序列数据时,我们了解到序列中的元素通常是以某种方式相关,这意味着它们相互依赖。因此,我们需要考虑每个元素以了解序列。剑桥大学出版社将序列定义为“事物或事件彼此跟随的顺序”,或者最重要的是,“一系列相关的事物或事件”。为了使这个定义适应深度学习的上下文,序列是一组包含可训练上下文的数据,删除一些元素可能会使它变得无用。但是序列包含什么?哪些分组数据可以有上下文?以及如何提取上下文以利用神经网络的力量?在深入了解神经网络之前,让我向您展示通常使用递归神经网络(RNN)解决的两类问题。时间序列预测第一个例子是时间序列预测问题,我们在现有值序列(蓝色)上训练神经网络,以预测未来的时间步长(红色)。如果我们将这些家庭按历年来每月的能源消耗进行排序,我们可以看到一个上升趋势和突然下降趋势的正弦曲线。正弦部分的背景可能是整个夏季(夏季到冬季)和回到夏季的不同能量需求。使用更多的电器和设备,或改用可能需要更多能源的更强大的电器和设备,可能会大幅增加支出。突然跌倒的背景可能意味着一个人已经到了可以离开家的年龄,而那个人所需要的能量已经不复存在了。您知道的上下文越多,您通常可以通过连接输入向量来帮助网络理解数据来为网络提供更多信息。在这种情况下,对于每个月,我们可以将另外三个值与能源相关联,包括电器和设备的数量、它们的能效以及家庭拥有的人数。自然语言处理Mary骑自行车,自行车是____。第二个例子是自然语言处理问题。这也是一个很好的例子,因为神经网络必须考虑现有句子提供的上下文才能做到这一点。假设我们的网络被训练来完成带有所有格代词的句子。一个训练有素的网络会理解这个句子是由第三人称单数构成的,而Mary很可能是一个女性名字。因此,预测代词应该是“hers”而不是阳性“his”或复数“theirs”。现在我们已经看到了两个排序数据的例子,让我们来探索网络的前向和反向传播。RNN配置正如我们所见,RNN从序列中提取信息以提高其预测能力。>简单的循环网络图。图作者。一个简单的RNN图如上所示。绿色节点接受一些输入x^t并输出一些值h^t,该值也被馈送到节点,再次包含从输入中收集的信息。无论输入节点的模式如何,它都会学习并保留下一个输入的信息。上标t代表时间步长。>循环网络配置。图作者。根据输入或输出的形状,神经网络的配置会发生一些变化,稍后我们将看到节点内部发生了什么。多对一配置是指我们在不同的时间步长输入多个输入以获得一个输出,这可能是在电影场景的各个帧中捕获的情感分析。一对多使用一个输入获得多个输出。例如,我们可以使用多对一配置来编码表达某种情感的诗歌,并使用一对多配置来创建具有相同情感的新诗行。多对多使用多个输入来获得多个输出,例如使用一系列值(例如在能源使用中)并预测未来十二个月而不是一个月。堆叠配置只是一个具有多层隐藏节点的网络。RNN预测为了了解神经网络节点内部发生了什么,我们将使用一个简单的数据集作为“时间序列预测”示例。Bellow是完整的值序列,它们被重新组合为训练和测试数据集。我从这个网站上拿了这个例子,这是一般深度学习的重要资源。现在,让我们将数据集分成几批。我没有在这里展示它,但不要忘记应该对数据集进行归一化。这很重要,因为神经网络对数据集值的大小很敏感。这个想法是预测未来的价值。因此,假设我们选择了批处理的第一行:[102030],在训练我们的网络之后,我们应该得到一个值40。要测试神经网络,您可以输入向量[708090]并期望如果网络训练有素,则获得接近100的值。我们将使用多对一配置,分别为每个序列提供三个时间步长。当使用循环网络时,输入值并不是进入网络的唯一值,还有一个隐藏数组被构造为在节点之间传递序列的上下文。我们将其初始化为零数组,并将其连接到输入。它的大小(1x2)是个人选择,只需使用与1x1步进输入不同的大小。>循环前传。图作者。仔细观察,我们可以看到权重矩阵分为两部分。第一个处理输入以创建两个输出,第二个处理隐藏数组以创建两个输出。然后将这两组输出相加,得到一个新的隐藏数组,其中包含来自第一个输入(10)的信息,并被馈送到下一个时间步长输入(20)。应该注意的是,权重和偏置矩阵在时间步长之间是相同的。上面显示了全局输入向量X^t、权重矩阵W和偏置矩阵B以及隐藏数组的计算。只剩下一步来完成前进。我们正在尝试预测未来值,我们有三个隐藏数组,每个输入的信息作为输出,因此我们需要将它们转换为单个值,希望是经过多次训练后的正确值。通过连接和重塑数组,我们可以附加一个线性层来计算最终结果。完整的网络具有以下形式:>完整的循环图。图作者。你能看到多对一的配置吗?我们从一个序列中提供三个输入,它们的上下文由权重和偏置矩阵捕获,存储在一个隐藏数组中,该数组在每个时间步用新信息更新。最终,存储在隐藏数组中的上下文将经过另一组权重和偏差,并且在序列的所有时间步长都被输入网络后,将输出一个值。我们可以看到隐藏状态的线性形式和线性层的权重和偏置矩阵,以及预测值(yhat)的计算。现在,这是RNN的正向传播,但我们还没有看到反向传播。RNNBackwardPass反向传播是训练每个神经网络的一个非常重要的步骤。在这里,预测输出和实际值之间的误差被传播到神经网络,目的是改进权重和偏差,以便每次迭代产生更好的预测。在大多数情况下,由于其复杂性,此步骤会被忽略。在提到重要的东西的同时,我会给你一个尽可能简单的解释。向后传递是使用微积分的链式法则从损失到所有权重和偏差参数的一系列推导。这意味着我们最终需要以下值(如果是多维则为数组):article,这通常意味着我们已经找到了系统中的最小值,理想情况下我们将无法进一步改进它。这里要注意一件事:零也可以是最大值,这是不稳定的,不应该在那里优化,或者是鞍点,它本身不是很稳定。最小值可以是全局值(函数的最小值)或局部值。这对我的解释并不重要,但是如果您想了解更多信息,可以查找它!>梯度下降示例。两个球从山上滚下来。图作者。你在图片中看到的是两个球从山上滚下来。滚下山谷。从视觉上看,一阶导数给了我们山的大小。如果我们沿增加W轴的方向(从左到右)行进,则绿球的斜率是负的(向下),红球的斜率为正(上)。仔细阅读下一段,然后根据需要返回图表。如果我们希望损失最小,我们希望球到达山谷的最低点。W代表weight和bias的值,所以如果我们在绿球处我们将对绿球的W位置减去一部分负导数(使其为正),将其向右移动并减去一部分将红球W位置的正导数向左移动(使其为负),因此两个球都接近最小值。在数学上,我们有以下内容:η调整我们用来更新权重和偏差的导数的比例。现在,继续向后传递问题。我将涵盖从损失到所有参数的链式导数,我们将看到每个导数代表什么。重要的是要记住上面介绍的层的方程式及其参数矩阵。要记住的一件事是,我们正在寻找的四个一阶导数数组必须与我们正在更新的参数具有相同的形状。例如,数组dL/dW_h必须与权重数组W_h具有相同的形状。上标T表示矩阵已转置。我们一直回到线性层的参数。因为我们将隐藏状态数组重塑为线性向量,所以我们应该将dL/dH^t重塑为串联隐藏状态数组的原始形状。目前,它是一个6x1数组,但从循环层计算出的隐藏数组的形状是3x2。我们还将所有全局输入连接在一起(t=1、2和3),现在我们可以继续与向后传球。现在剩下要做的就是应用我们之前看到的梯度下降方程来更新参数,模型为下一次迭代做好准备。让我们看看如何使用PyTorch构建一个简单的RNN。PyTorch中的RNN使用PyTorch非常简单,因为我们真的不需要担心反向传播。然而,即使我们不直接使用它,我仍然认为了解它的工作原理很重要。继续,如果我们参考PyTorch的文档,我们可以看到他们已经准备好使用RNN对象。定义它时,有两个基本参数:input_size—输入x中的预期特征数hidden_??size—隐藏状态h中的特征数input_size为1,因为我们一次使用每个序列一个时间步长(例如序列10、20、10outof30),hidden_??size是2因为我们得到了一个有两个值的隐藏状态。将n_layers参数定义为2意味着我们有一个带有两个隐藏层的堆叠式RNN。此外,我们将参数batch_first定义为True。这意味着输入和输出中的batchsize在前(输入输出不能错)input:input,inputofshapeh_0(seq_len,batch,input_size):包含输入序列特征的Tensor。h_0(num_layers*num_directions,batch,hidden_??size)的形状:包含批次中每个元素的初始隐藏状态的张量。RNN的输入应该是形状为1x3x1的输入数组。该序列由三个时间步长组成,即数据集的前10、20和30。从每个批次中,大小为1的输入将作为三个时间步长的序列被馈送到网络三次。隐藏状态h_0是我们的第一个隐藏数组,我们将其与形状为1x1x2的第一个时间步输入一起馈入网络。输出:输出,h_n形状的输出(seq_len,batch,num_directions*hidden_??size):包含每个t的RNN最后一层的输出特征(h_t)。h_n(num_layers*num_directions,batch,hidden_??size)的形状:包含t=seq_len的隐藏状态的张量。输出包含神经网络在形状为1x3x2的每个时间步计算的所有隐藏状态,h_n是最后一个时间步的隐藏状态。这对保持有用很有用,因为如果我们选择使用堆叠循环网络,这将是隐藏状态,它将在第一个时间步被馈送,形状为1x1x2。所有这些数组都表示在上面的示例,可以在RNN图中看到。另一个需要注意的是,使用循环网络和“时间序列预测”的具体例子,将num_directions设置为2将意味着预测未来和过去。此处不考虑此类配置。我将在实现RNN以及如何训练它的过程中留下一段代码。我也会让你根据需要使用你想要的数据集。在使用网络之前,不要忘记规范化数据并创建数据集和数据加载器。总结思想为了以简短的总结结束这个故事,我们首先研究了通常使用递归网络解决的两类问题,即时间序列预测和自然语言处理。后来,我们看到了一些典型配置的示例,以及一个目标是使用多对一配置预测未来一步的实际示例。在正向传递中,我们看到了输入和隐藏状态如何与循环层的权重和偏差相互作用,以及隐藏状态中包含的信息如何用于预测下一个时间步长值。向后传递只是链式法则的应用,从损失相对于预测的梯度到相对于我们要优化的参数的变化。最后,我们浏览了有关RNN的部分PyTorch文档,并讨论了构建基本循环网络的最重要部分。谢谢阅读!也许你从这个漫长的故事中得到了一些启发。我写它们是为了帮助我理解新概念,并希望也能帮助其他人。原文链接:https://towardsdatascience.com/rnns-from-theory-to-pytorch-f0af30b610e1
