diff --git a/totrans/dl-scr_6.yaml b/totrans/dl-scr_6.yaml index 4952516..2e074f8 100644 --- a/totrans/dl-scr_6.yaml +++ b/totrans/dl-scr_6.yaml @@ -1326,11 +1326,13 @@ id: totrans-176 prefs: [] type: TYPE_NORMAL + zh: 这就是`RNNLayer`的工作原理。现在似乎唯一剩下的就是描述递归神经网络的核心:`RNNNode`,在这里实际计算发生。在我们继续之前,让我们澄清`RNNNode`及其在整个RNN中的变体的作用。 - en: The Essential Elements of RNNNodes id: totrans-177 prefs: - PREF_H2 type: TYPE_NORMAL + zh: RNNNodes的基本要素 - en: 'In most treatments of RNNs, the first thing discussed is the workings of what we are here calling `RNNNode`s. However, we cover these last because the most important concepts to understand about RNNs are those that we’ve described in @@ -1351,12 +1353,15 @@ id: totrans-178 prefs: [] type: TYPE_NORMAL + zh: 在大多数关于RNN的讨论中,首先讨论的是我们在这里称为`RNNNode`的工作原理。然而,我们最后讨论这些,因为关于RNN最重要的概念是我们在本章中迄今为止描述的那些:数据的结构方式以及数据和隐藏状态在层之间和通过时间如何路由。事实证明,我们可以实现`RNNNode`的多种方式,即给定时间步骤的数据的实际处理和层的隐藏状态的更新。一种方式产生了通常被认为是“常规”递归神经网络的东西,我们在这里将其称为另一个常见术语:香草RNN。然而,还有其他更复杂的方式可以产生不同的RNN变体;例如,一种带有称为GRUs的`RNNNode`的变体,GRUs代表“门控循环单元”。通常,GRUs和其他RNN变体被描述为与香草RNN有显著不同;然而,重要的是要理解*所有* + RNN变体都共享我们迄今为止看到的层的结构——例如,它们都以相同的方式向前传递数据,更新它们的隐藏状态(s)在每个时间步。它们之间唯一的区别在于这些“节点”的内部工作方式。 - en: 'To reinforce this point: if we implemented a `GRULayer` instead of an `RNNLayer`, the code would be exactly the same! The following code would still form the core of the forward pass:' id: totrans-179 prefs: [] type: TYPE_NORMAL + zh: 为了强调这一点:如果我们实现了一个`GRULayer`而不是一个`RNNLayer`,代码将完全相同!以下代码仍然构成前向传递的核心: - en: '[PRE23]' id: totrans-180 prefs: [] @@ -1367,6 +1372,7 @@ id: totrans-181 prefs: [] type: TYPE_NORMAL + zh: 唯一的区别是`self.nodes`中的每个“节点”将是一个`GRUNode`而不是`RNNNode`。类似地,`backward`方法也将是相同的。 - en: 'This is also almost entirely true for the most well-known variant on vanilla RNNs: LSTMs, or “Long Short Term Memory” cells. The only difference with these is that `LSTMLayer`s require *two* quantities to be “remembered” by the layer @@ -1379,23 +1385,27 @@ id: totrans-182 prefs: [] type: TYPE_NORMAL + zh: 这对于香草RNN的最知名变体——LSTMs或“长短期记忆”单元——也几乎完全正确。唯一的区别在于,这些`LSTMLayer`需要在通过时间向前传递序列元素时“记住”*两个*量,并更新:除了“隐藏状态”外,层中还存储着“细胞状态”,使其能够更好地建模长期依赖关系。这导致了我们在实现`LSTMLayer`与`RNNLayer`时会有一些细微差异;例如,`LSTMLayer`将有两个`ndarray`来存储层在整个时间步中的状态: - en: An `ndarray` `start_H` of shape `(1, hidden_size)`, representing the layer’s hidden state id: totrans-183 prefs: - PREF_UL type: TYPE_NORMAL + zh: 一个形状为`(1, hidden_size)`的`ndarray` `start_H`,表示层的隐藏状态 - en: An `ndarray` `start_C` of shape `(1, cell_size)`, representing the layer’s cell state id: totrans-184 prefs: - PREF_UL type: TYPE_NORMAL + zh: 一个形状为`(1, cell_size)`的`ndarray` `start_C`,表示层的细胞状态 - en: 'Each `LSTMNode`, therefore, should take in the input, as well as both the hidden state *and* the cell state. On the forward pass, this will look like:' id: totrans-185 prefs: [] type: TYPE_NORMAL + zh: 因此,每个`LSTMNode`都应该接收输入,以及隐藏状态和细胞状态。在前向传递中,这将如下所示: - en: '[PRE24]' id: totrans-186 prefs: [] @@ -1405,6 +1415,7 @@ id: totrans-187 prefs: [] type: TYPE_NORMAL + zh: 以及: - en: '[PRE25]' id: totrans-188 prefs: [] @@ -1414,6 +1425,7 @@ id: totrans-189 prefs: [] type: TYPE_NORMAL + zh: 在`backward`方法中。 - en: There are many more variants than the three mentioned here, some of which, such as LSTMs with “peephole connections,” have a cell state in addition to only a hidden state, and some of which maintain only a hidden state.^([5](ch06.html#idm45732613324856)) @@ -1428,15 +1440,18 @@ id: totrans-190 prefs: [] type: TYPE_NORMAL + zh: 这里提到的三种变体远不止这些,其中一些,比如带有“窥视孔连接”的LSTMs,除了隐藏状态外还有一个细胞状态,而另一些只保留隐藏状态。尽管如此,由`LSTMPeepholeConnectionNode`组成的层将与我们迄今为止看到的变体一样适用于`RNNLayer`,因此具有相同的`forward`和`backward`方法。RNN的基本结构——数据如何通过层向前路由,以及如何通过时间步向前路由,然后在反向传递期间沿相反方向路由——这就是使递归神经网络独特的地方。例如,香草RNN和基于LSTM的RNN之间的实际结构差异相对较小,尽管它们的性能可能有显著不同。 - en: With that, let’s look at the implementation of an `RNNNode`. id: totrans-191 prefs: [] type: TYPE_NORMAL + zh: 有了这些,让我们看看`RNNNode`的实现。 - en: “Vanilla” RNNNodes id: totrans-192 prefs: - PREF_H2 type: TYPE_NORMAL + zh: “香草”RNNNodes - en: RNNs receive data one sequence element at a time; for example, if we are predicting the price of oil, at each time step, the RNN will receive information about the features we are using to predict the price at that time step. In addition, the @@ -1561,11 +1576,13 @@ id: totrans-207 prefs: [] type: TYPE_NORMAL + zh: 请注意,就像我们之前的`Operation`s一样,`backward`函数的输入形状必须与`forward`函数的输出形状匹配,`backward`函数的输出形状必须与`forward`函数的输入形状匹配。 - en: Limitations of “Vanilla” RNNNodes id: totrans-208 prefs: - PREF_H2 type: TYPE_NORMAL + zh: “Vanilla” RNNNodes的局限性 - en: 'Remember: the purpose of RNNs is to model dependencies in sequences of data. Thinking of modeling the price of oil as our canonical example, this means that we should be able to uncover the relationship between the sequence of features @@ -1578,6 +1595,7 @@ id: totrans-209 prefs: [] type: TYPE_NORMAL + zh: 记住:RNNs的目的是对数据序列中的依赖关系进行建模。以模拟石油价格为例,这意味着我们应该能够揭示我们在过去几个时间步中看到的特征序列与明天石油价格会发生什么之间的关系。但“几个”应该是多长时间呢?对于石油价格,我们可能会想象,昨天发生的事情——前一时间步——对于预测明天的石油价格最为重要,前一天的重要性较小,而随着时间的倒退,重要性通常会逐渐减弱。 - en: 'While this is true for many real-world problems, there are domains to which we’d like to apply RNNs where we would want to learn extremely long-range dependencies. *Language modeling* is the canonical example here—that is, building a model that @@ -1601,11 +1619,16 @@ id: totrans-210 prefs: [] type: TYPE_NORMAL + zh: 虽然这对许多现实世界的问题是正确的,但有些领域我们希望应用RNNs,我们希望学习极端长期的依赖关系。*语言建模*是一个典型的例子,即构建一个模型,可以预测下一个字符、单词或单词部分,给定一个理论上极长的过去单词或字符序列(因为这是一个特别普遍的应用,我们将在本章后面讨论一些与语言建模相关的细节)。对于这一点,vanilla + RNNs通常是不够的。现在我们已经看到了它们的细节,我们可以理解为什么:在每个时间步,隐藏状态都会被同一组权重矩阵乘以*所有层中的所有时间步。考虑当我们一遍又一遍地将一个数字乘以一个值`x`时会发生什么:如果`x + < 1`,数字会指数级地减少到0,如果`x > 1`,数字会指数级地增加到无穷大。循环神经网络也有同样的问题:在长时间跨度上,因为在每个时间步中隐藏状态都会被相同的权重集乘以,这些权重的梯度往往会变得极小或极大。前者被称为*消失梯度问题*,后者被称为*爆炸梯度问题*。这两个问题使得训练RNNs来模拟非常长期的依赖关系(50-100个时间步)变得困难。我们接下来将介绍的两种常用的修改vanilla + RNN架构的方法都显著缓解了这个问题。 - en: 'One Solution: GRUNodes' id: totrans-211 prefs: - PREF_H2 type: TYPE_NORMAL + zh: 一种解决方案:GRUNodes - en: Vanilla RNNs can be described as taking the input and hidden state, combining them, and using the matrix multiplication to determine how to “weigh” the information contained in the hidden state against the information in the new input to predict @@ -1618,12 +1641,14 @@ id: totrans-212 prefs: [] type: TYPE_NORMAL + zh: Vanilla RNNs可以被描述为将输入和隐藏状态结合在一起,并使用矩阵乘法来确定如何“加权”隐藏状态中包含的信息与新输入中的信息,以预测输出。激发更高级RNN变体的洞察力是,为了模拟长期依赖关系,比如语言中存在的依赖关系,*有时我们会收到告诉我们需要“忘记”或“重置”隐藏状态的信息*。一个简单的例子是句号“。”或冒号“:”——如果语言模型收到其中一个,它就知道应该忘记之前的字符,并开始对字符序列中的新模式进行建模。 - en: A first, simple variant on vanilla RNNs that leverages this insight is GRUs or Gated Recurrent Units, so named because the input and the prior hidden state are passed through a series of “gates.” id: totrans-213 prefs: [] type: TYPE_NORMAL + zh: 第一个简单的变体是GRUs或门控循环单元,利用了这一洞察力,因为输入和先前的隐藏状态通过一系列“门”传递。 - en: 'The first gate is similar to the operations that take place in vanilla RNNs: the input and hidden state are concatenated together, multiplied by a weight matrix, and then passed through a `sigmoid` operation. We can think of the output of this @@ -1632,6 +1657,7 @@ prefs: - PREF_OL type: TYPE_NORMAL + zh: 第一个门类似于在vanilla RNNs中发生的操作:输入和隐藏状态被连接在一起,乘以一个权重矩阵,然后通过`sigmoid`操作传递。我们可以将其输出视为“更新”门。 - en: 'The second gate is interpreted as a “reset” gate: the input and hidden state are concatenated, multiplied by a weight matrix, passed through a `sigmoid` operation, *and then multiplied by the prior hidden state*. This allows the network to “learn @@ -1641,6 +1667,7 @@ prefs: - PREF_OL type: TYPE_NORMAL + zh: 第二个门被解释为“重置”门:输入和隐藏状态被连接在一起,乘以一个权重矩阵,通过`sigmoid`操作,*然后乘以先前的隐藏状态*。这使得网络能够“学会忘记”隐藏状态中的内容,给定传入的特定输入。 - en: The output of the second gate is then multiplied by another matrix and passed through the `Tanh` function, with the output being a “candidate” for the new hidden state. @@ -1648,17 +1675,20 @@ prefs: - PREF_OL type: TYPE_NORMAL + zh: 然后,第二个门的输出乘以另一个矩阵,并通过`Tanh`函数传递,输出为新隐藏状态的“候选”。 - en: Finally, the hidden state is updated to be the update gate times the “candidate” for the new hidden state, plus the old hidden state times 1 minus the update gate. id: totrans-217 prefs: - PREF_OL type: TYPE_NORMAL + zh: 最后,隐藏状态更新为更新门乘以新隐藏状态的“候选”,再加上旧隐藏状态乘以1减去更新门。 - en: Note id: totrans-218 prefs: - PREF_H6 type: TYPE_NORMAL + zh: 注意 - en: 'We’ll cover two advanced variants on vanilla RNNs in this chapter: GRUs and LSTMs. LSTMs are more popular and were invented long before GRUs. Nevertheless, GRUs are a simpler version of LSTMs, and more directly illustrate how the idea @@ -1667,11 +1697,13 @@ id: totrans-219 prefs: [] type: TYPE_NORMAL + zh: 在本章中,我们将介绍普通RNN的两个高级变体:GRUs和LSTMs。LSTMs更受欢迎,比GRUs早发明很久。尽管如此,GRUs是LSTMs的一个更简单的版本,并更直接地说明了“门”的概念如何使RNN能够“学会重置”其隐藏状态,这就是为什么我们首先介绍它们。 - en: 'GRUNodes: A diagram' id: totrans-220 prefs: - PREF_H3 type: TYPE_NORMAL + zh: GRUNodes:一个图表 - en: '[Figure 6-8](#fig_06_08) depicts `GRUNode` as a series of gates. Each gate contains the operations of a `Dense` layer: multiplication by a weight matrix, adding a bias, and feeding the result through an activation function. The activation @@ -1682,16 +1714,19 @@ id: totrans-221 prefs: [] type: TYPE_NORMAL + zh: '[图6-8](#fig_06_08)将`GRUNode`描述为一系列门。每个门包含一个`Dense`层的操作:乘以一个权重矩阵,加上一个偏置,并通过激活函数传递结果。使用的激活函数要么是`sigmoid`,在这种情况下,结果的范围在0到1之间,要么是`Tanh`,在这种情况下,范围在-1到1之间;下一个产生的每个中间`ndarray`的范围在数组的名称下显示。' - en: '![Output of length one](assets/dlfs_0608.png)' id: totrans-222 prefs: [] type: TYPE_IMG + zh: '![长度为一的输出](assets/dlfs_0608.png)' - en: Figure 6-8\. The flow of data forward through a GRUNode, passing through gates and producing X_out and H_out id: totrans-223 prefs: - PREF_H6 type: TYPE_NORMAL + zh: 图6-8。数据通过GRUNode向前流动,通过门并产生X_out和H_out - en: In [Figure 6-8](#fig_06_08) as in Figures [6-9](#fig_06_09) and [6-10](#fig_06_10), the inputs to the node are colored green, the intermediate quantities computed are colored blue, and the outputs are colored red. All the weights (not directly @@ -1699,6 +1734,7 @@ id: totrans-224 prefs: [] type: TYPE_NORMAL + zh: 在[图6-8](#fig_06_08)中,以及图[6-9](#fig_06_09)和[6-10](#fig_06_10)中,节点的输入为绿色,计算的中间量为蓝色,输出为红色。所有权重(未直接显示)都包含在门中。 - en: Note that to backpropagate through this, we would have to represent this solely as a series of `Operation`s, compute the derivative of each `Operation` with respect to its input, and multiply the results together. We don’t show that explicitly @@ -1710,36 +1746,43 @@ id: totrans-225 prefs: [] type: TYPE_NORMAL + zh: 请注意,要通过这个过程反向传播,我们必须将其表示为一系列`Operation`,计算每个`Operation`相对于其输入的导数,并将结果相乘。我们在这里没有明确展示这一点,而是将门(实际上是三个操作的组合)显示为一个单独的块。但是,到目前为止,我们知道如何通过组成每个门的`Operation`进行反向传播,而“门”的概念在循环神经网络及其变体的描述中被广泛使用,因此我们将在这里坚持使用这种表示方式。 - en: Indeed, [Figure 6-9](#fig_06_09) shows a representation of a vanilla `RNNNode`, using gates. id: totrans-226 prefs: [] type: TYPE_NORMAL + zh: 实际上,[图6-9](#fig_06_09)显示了一个使用门的普通`RNNNode`的表示。 - en: '![Output of length one](assets/dlfs_0609.png)' id: totrans-227 prefs: [] type: TYPE_IMG + zh: '![长度为一的输出](assets/dlfs_0609.png)' - en: Figure 6-9\. The flow of data forward through an RNNNode, passing through just two gates and producing X_out and H_out id: totrans-228 prefs: - PREF_H6 type: TYPE_NORMAL + zh: 图6-9。数据通过RNNNode向前流动,通过两个门并产生X_out和H_out - en: Thus, another way to think of the `Operation`s we previously described as making up a vanilla `RNNNode` is as passing the input and hidden state through two gates. id: totrans-229 prefs: [] type: TYPE_NORMAL + zh: 因此,另一种思考我们之前描述的作为一个普通`RNNNode`组成部分的`Operation`的方式是将输入和隐藏状态通过两个门传递。 - en: 'GRUNodes: The code' id: totrans-230 prefs: - PREF_H3 type: TYPE_NORMAL + zh: GRUNodes:代码 - en: 'The following code implements the forward pass for a `GRUNode` as described earlier:' id: totrans-231 prefs: [] type: TYPE_NORMAL + zh: 以下代码实现了先前描述的`GRUNode`的前向传递: - en: '[PRE28]' id: totrans-232 prefs: [] @@ -1752,6 +1795,8 @@ id: totrans-233 prefs: [] type: TYPE_NORMAL + zh: 请注意,我们没有明确连接`X_in`和`H_in`,因为—与`RNNNode`不同,在`GRUNode`中我们独立使用它们;具体来说,在`self.h_reset + = self.r * H_in`这一行中,我们独立使用`H_in`而不是`X_in`。 - en: The `backward` method can be found on [the book’s website](https://oreil.ly/2P0lG1G); it simply steps backward through the operations that make up a `GRUNode`, calculating the derivative of each operation with respect to its input and multiplying the @@ -1759,11 +1804,13 @@ id: totrans-234 prefs: [] type: TYPE_NORMAL + zh: '`backward`方法可以在[书的网站](https://oreil.ly/2P0lG1G)上找到;它只是通过组成`GRUNode`的操作向后步进,计算每个操作相对于其输入的导数,并将结果相乘。' - en: LSTMNodes id: totrans-235 prefs: - PREF_H2 type: TYPE_NORMAL + zh: LSTMNodes - en: Long Short Term Memory cells, or LSTMs, are the most popular variant of vanilla RNN cells. Part of the reason for this is that they were invented in the early days of deep learning, back in 1997,^([6](ch06.html#idm45732612415128)) whereas @@ -1772,6 +1819,7 @@ id: totrans-236 prefs: [] type: TYPE_NORMAL + zh: 长短期记忆单元,或LSTMs,是香草RNN单元最受欢迎的变体。部分原因是它们是在深度学习的早期阶段,即1997年发明的^([6](ch06.html#idm45732612415128)),而对于LSTM替代方案如GRUs的调查在过去几年中才加速进行(例如,GRUs是在2014年提出的)。 - en: 'Like GRUs, LSTMs are motivated by the desire to give the RNN the ability to “reset” or “forget” its hidden state as it receives new input. In GRUs, this is achieved by feeding the input and hidden state through a series of gates, as well @@ -1782,6 +1830,7 @@ id: totrans-237 prefs: [] type: TYPE_NORMAL + zh: 与GRUs一样,LSTMs的动机是为了让RNN能够在接收新输入时“重置”或“忘记”其隐藏状态。在GRUs中,通过将输入和隐藏状态通过一系列门传递,以及使用这些门计算“建议”的新隐藏状态—`self.h_bar`,使用门`self.r`计算—然后使用建议的新隐藏状态和旧隐藏状态的加权平均值计算最终隐藏状态,由更新门控制: - en: '[PRE29]' id: totrans-238 prefs: [] @@ -1795,20 +1844,24 @@ id: totrans-239 prefs: [] type: TYPE_NORMAL + zh: 相比之下,LSTMs*使用一个单独的“状态”向量,“单元状态”,来确定是否“忘记”隐藏状态中的内容*。然后,它们使用另外两个门来控制它们应该重置或更新*单元状态*中的内容的程度,以及第四个门来确定基于最终单元状态的情况下隐藏状态的更新程度。^([7](ch06.html#idm45732612392904)) - en: 'LSTMNodes: Diagram' id: totrans-240 prefs: - PREF_H3 type: TYPE_NORMAL + zh: 'LSTMNodes: Diagram' - en: '[Figure 6-10](#fig_06_10) shows a diagram of an `LSTMNode` with the operations represented as gates.' id: totrans-241 prefs: [] type: TYPE_NORMAL + zh: '[图6-10](#fig_06_10)显示了一个`LSTMNode`的图示,其中操作表示为门。' - en: '![](assets/dlfs_0610.png)' id: totrans-242 prefs: [] type: TYPE_IMG + zh: '![](assets/dlfs_0610.png)' - en: Figure 6-10\. The flow of data forward through an LSTMNode, passing through a series of gates and outputting updated cell states and hidden states C_out and H_out, respectively, along with an actual output X_out @@ -1816,11 +1869,13 @@ prefs: - PREF_H6 type: TYPE_NORMAL + zh: 图6-10\. 数据通过LSTMNode向前流动的流程,通过一系列门传递,并输出更新的单元状态和隐藏状态C_out和H_out,以及实际输出X_out - en: 'LSTMs: The code' id: totrans-244 prefs: - PREF_H3 type: TYPE_NORMAL + zh: 'LSTMs: The code' - en: 'As with `GRUNode`s, the full code for an `LSTMNode`, including the `backward` method and an example showing how these nodes fit into an `LSTMLayer`, is included on [the book’s website](https://oreil.ly/2P0lG1G). Here, we just show the `forward` @@ -1828,6 +1883,7 @@ id: totrans-245 prefs: [] type: TYPE_NORMAL + zh: 与`GRUNode`一样,`LSTMNode`的完整代码,包括`backward`方法和一个示例,展示了这些节点如何适应`LSTMLayer`,都包含在[书的网站](https://oreil.ly/2P0lG1G)上。在这里,我们只展示`forward`方法: - en: '[PRE30]' id: totrans-246 prefs: [] @@ -1839,11 +1895,13 @@ id: totrans-247 prefs: [] type: TYPE_NORMAL + zh: 这是我们需要开始训练模型的RNN框架的最后一个元素!我们应该涵盖的另一个主题是:如何以一种形式表示文本数据,以便我们可以将其馈送到我们的RNN中。 - en: Data Representation for a Character-Level RNN-Based Language Model id: totrans-248 prefs: - PREF_H2 type: TYPE_NORMAL + zh: 用于基于字符级RNN的语言模型的数据表示 - en: 'Language modeling is one of the most common tasks RNNs are used for. How can we reshape a sequence of characters into a training dataset so that an RNN can be trained to predict the next character? The simplest method is to use *one-hot @@ -1857,12 +1915,14 @@ id: totrans-249 prefs: [] type: TYPE_NORMAL + zh: 语言建模是RNN最常用的任务之一。我们如何将字符序列重塑为训练数据集,以便RNN可以训练以预测下一个字符?最简单的方法是使用*one-hot编码*。具体操作如下:首先,每个字母都表示为一个维度等于*词汇表的大小*或文本总体语料库中字母数量的向量(这是在网络中预先计算并硬编码为一个超参数)。然后,每个字母都表示为一个向量,其中该字母所在位置为1,其他位置为0。最后,每个字母的向量简单地连接在一起,以获得字母序列的整体表示。 - en: 'Here’s a simple example of how this would look with a vocabulary of four letters, `a`, `b`, `c`, and `d`, where we arbitrarily call `a` the first letter, `b` the second letter, and so on:' id: totrans-250 prefs: [] type: TYPE_NORMAL + zh: 这是一个简单的示例,展示了具有四个字母`a`、`b`、`c`和`d`的词汇表,我们任意地将`a`称为第一个字母,`b`称为第二个字母,依此类推: - en: a b c d b 1 0 0 0 @@ -1908,6 +1968,7 @@ id: totrans-252 prefs: [] type: TYPE_NORMAL + zh: 这个二维数组将代替一个形状为`(sequence_length, num_features) = (5, 4)`的观察值在一个序列批次中。因此,如果我们的文本是“abcdba”—长度为6—并且我们想要将长度为5的序列馈送到我们的数组中,第一个序列将被转换为前述矩阵,第二个序列将是: - en: b c d b a 0 1 0 0 @@ -1952,12 +2013,14 @@ id: totrans-254 prefs: [] type: TYPE_NORMAL + zh: 然后将它们连接在一起,以创建一个形状为`(batch_size, sequence_length, vocab_size) = (2, 5, 4)`的RNN输入。继续这样,我们可以将原始文本转换为一批序列,以馈送到RNN中。 - en: In the [Chapter 6 notebook](https://oreil.ly/2P0lG1G) on the book’s GitHub repo, we code this up as part of an `RNNTrainer` class that can take in raw text, preprocess it using the techniques described here, and feed it into an RNN in batches. id: totrans-255 prefs: [] type: TYPE_NORMAL + zh: 在书的GitHub存储库中的[第6章笔记本](https://oreil.ly/2P0lG1G)中,我们将其编码为`RNNTrainer`类的一部分,该类可以接受原始文本,使用这里描述的技术对其进行预处理,并将其批量馈送到RNN中。 - en: Other Language Modeling Tasks id: totrans-256 prefs: @@ -2090,6 +2153,9 @@ id: totrans-271 prefs: [] type: TYPE_NORMAL + zh: 一个经典的练习是训练RNN以特定风格写文本;[在书的网站上](https://oreil.ly/2P0lG1G),我们有一个端到端的代码示例,使用本章描述的抽象定义模型,学习以莎士比亚风格写文本。我们还没有展示的唯一组件是一个`RNNTrainer`类,它通过训练数据进行迭代,对其进行预处理,并将其馈送到模型中。这与我们之前看到的`Trainer`的主要区别是,对于RNN,一旦我们选择要馈送的数据批次——每个批次元素仅为一个字符串——我们必须首先对其进行预处理,对每个字母进行独热编码,并将生成的向量连接成一个序列,将长度为`sequence_length`的每个字符串转换为形状为`(sequence_length, + vocab_size)`的`ndarray`。为了形成将馈送到我们的RNN中的批次,*这些* `ndarray`将被连接在一起,形成大小为`(sequence_length, + vocab_size, batch_size)`的批次。 - en: 'But once the data has been preprocessed and the model defined, RNNs are trained in the same way as other neural networks we’ve seen: batches are iteratively fed through, the model’s predictions are compared to the targets to generate the loss, @@ -2098,11 +2164,13 @@ id: totrans-272 prefs: [] type: TYPE_NORMAL + zh: 但是一旦数据经过预处理并且模型定义好了,RNN的训练方式与我们之前看到的其他神经网络相同:批次被迭代地馈送,模型的预测与目标进行比较以生成损失,损失通过构成模型的操作进行反向传播以更新权重。 - en: Conclusion id: totrans-273 prefs: - PREF_H1 type: TYPE_NORMAL + zh: 结论 - en: In this chapter, you learned about recurrent neural networks, a special kind of neural network architecture designed for processing sequences of data, rather than individual operations. You learned how RNNs are made up of layers that pass @@ -2116,6 +2184,7 @@ id: totrans-274 prefs: [] type: TYPE_NORMAL + zh: 在本章中,您了解了递归神经网络,这是一种专门设计用于处理数据序列而不是单个操作的神经网络架构。您了解了RNN由在时间上向前传递数据的层组成,随着时间的推移更新它们的隐藏状态(以及在LSTMs的情况下更新它们的单元状态)。您看到了高级RNN变体GRUs和LSTMs的细节,以及它们如何通过每个时间步的一系列“门”向前传递数据;然而,您了解到这些高级变体基本上以相同的方式处理数据序列,因此它们的层结构相同,在每个时间步应用的特定操作不同。 - en: Hopefully this multifaceted topic is now less of a black box. In [Chapter 7](ch07.html#pytorch), I’ll conclude the book by turning to the practical side of deep learning, showing how to implement everything we’ve talked about thus far using the PyTorch framework, @@ -2124,6 +2193,7 @@ id: totrans-275 prefs: [] type: TYPE_NORMAL + zh: 希望这个多方面的主题现在不再是一个黑匣子。在[第7章](ch07.html#pytorch)中,我将通过转向深度学习的实践方面来结束本书,展示如何使用PyTorch框架实现我们迄今所讨论的一切,PyTorch是一个高性能、基于自动微分的框架,用于构建和训练深度学习模型。继续前进! - en: ^([1](ch06.html#idm45732615342296-marker)) We happened to find it convenient to arrange the observations along the rows and the features along the columns, but we didn’t necessarily have to arrange the data that way. The data does, however, @@ -2131,10 +2201,12 @@ id: totrans-276 prefs: [] type: TYPE_NORMAL + zh: ^([1](ch06.html#idm45732615342296-marker)) 我们碰巧发现将观察结果排列在行上,将特征排列在列上很方便,但我们不一定要以这种方式排列数据。然而,数据必须是二维的。 - en: ^([2](ch06.html#idm45732615335848-marker)) Or this edition of the book, at least. id: totrans-277 prefs: [] type: TYPE_NORMAL + zh: ^([2](ch06.html#idm45732615335848-marker)) 或者至少是这本书的这个版本。 - en: '^([3](ch06.html#idm45732614959096-marker)) I want to mention an alternative solution to this problem shared by author Daniel Sabinasz on his blog, [*deep ideas*](http://www.deepideas.net): he represents the operations as a graph and @@ -2144,24 +2216,32 @@ id: totrans-278 prefs: [] type: TYPE_NORMAL + zh: ^([3](ch06.html#idm45732614959096-marker)) 我想提到作者Daniel Sabinasz在他的博客[*deep + ideas*](http://www.deepideas.net)上分享的另一种解决这个问题的方法:他将操作表示为一个图,然后使用广度优先搜索来计算反向传播中的梯度,以正确的顺序构建一个模仿TensorFlow的框架。他关于如何做到这一点的博客文章非常清晰和结构良好。 - en: ^([4](ch06.html#idm45732615077368-marker)) For a deeper dive into how to implement automatic differentiation, see *Grokking Deep Learning* by Andrew Trask (Manning). id: totrans-279 prefs: [] type: TYPE_NORMAL + zh: ^([4](ch06.html#idm45732615077368-marker)) 深入了解如何实现自动微分,请参阅Andrew Trask的*Grokking + Deep Learning*(Manning)。 - en: ^([5](ch06.html#idm45732613324856-marker)) See the Wikipedia page on LSTMs for more examples of [LSTM variants](https://oreil.ly/2TysrXj). id: totrans-280 prefs: [] type: TYPE_NORMAL + zh: ^([5](ch06.html#idm45732613324856-marker)) 请查看LSTMs的维基百科页面,了解更多[LSTM变体](https://oreil.ly/2TysrXj)的例子。 - en: ^([6](ch06.html#idm45732612415128-marker)) See the original LSTM paper, [“Long Short-Term Memory”](https://oreil.ly/2YYZvwT), by Hochreiter et al. (1997). id: totrans-281 prefs: [] type: TYPE_NORMAL + zh: ^([6](ch06.html#idm45732612415128-marker)) 参见Hochreiter等人的原始LSTM论文[“长短期记忆”](https://oreil.ly/2YYZvwT) + (1997)。 - en: ^([7](ch06.html#idm45732612392904-marker)) At least the standard variant of LSTMs; as mentioned, there are other variants such as “LSTMs with peephole connections” whose gates are arranged differently. id: totrans-282 prefs: [] type: TYPE_NORMAL + zh: 至少是标准变体的LSTMs;正如提到的,还有其他变体,比如“带有窥视孔连接的LSTMs”,其门的排列方式不同。