diff --git a/new/pt-ai-fund/2.md b/new/pt-ai-fund/2.md index 0e66c105ff1fe269041af643b24de8fdfe495962..086d3ed4a6681e9d4849c160e011e44b21948263 100644 --- a/new/pt-ai-fund/2.md +++ b/new/pt-ai-fund/2.md @@ -156,7 +156,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机 在本秘籍中,我们将扩展在先前秘籍“定义神经网络类”中定义的类。 在“定义神经网络类”秘籍中,我们仅创建了所需架构的组件; 现在我们将把所有这些部分捆绑在一起,以建立一个明智的网络。 我们各层的进度将从 784 个单位增加到 256 个,然后是 128 个,最后是 10 个单位的输出层。 -在本秘籍中,我们将使用类的构造函数中定义的组件来研究网络架构。 然后,我们将完成网络类定义并创建其对象。 +在本秘籍中,我们将使用类的构造器中定义的组件来研究网络架构。 然后,我们将完成网络类定义并创建其对象。 # 操作步骤 @@ -228,7 +228,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机 # 工作原理 -在秘籍中,通过建立前向网络来完成网络,其中我们将构造函数中定义的网络组件捆绑在一起。 用`nn.Module`定义的网络需要定义`forward()`方法。 它采用输入张量,并按照正向方法中定义的操作顺序,将其通过网络类中`__init__()`方法中定义的网络组件。 +在秘籍中,通过建立前向网络来完成网络,其中我们将构造器中定义的网络组件捆绑在一起。 用`nn.Module`定义的网络需要定义`forward()`方法。 它采用输入张量,并按照正向方法中定义的操作顺序,将其通过网络类中`__init__()`方法中定义的网络组件。 当传递输入时,将引用模型对象的名称自动调用 forward 方法。 `nn.Module`自动创建将在正向方法中使用的权重和偏差张量。 线性单元本身定义了线性函数,例如`xW + B`; 要具有非线性功能,我们需要插入非线性激活函数,在这里我们使用最流行的激活函数之一 ReLU,尽管您可以在 PyTorch 中使用其他可用的激活函数。 @@ -252,7 +252,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机 让我们定义损失函数: -1. 首先,我们将从网络构造函数中的`__init__`方法开始,将现有的网络架构修改为`softmax`而不是`softmax`的输出日志: +1. 首先,我们将从网络构造器中的`__init__`方法开始,将现有的网络架构修改为`softmax`而不是`softmax`的输出日志: ```py >>self.log_softmax = nn.LogSoftmax() diff --git a/new/pt-ai-fund/3.md b/new/pt-ai-fund/3.md index 79505cd2d32c32c2a33b72c933e7b3a65f1a1bc0..3ef8072faa355610e26a92b6a1a78b54d5aff7dd 100644 --- a/new/pt-ai-fund/3.md +++ b/new/pt-ai-fund/3.md @@ -676,7 +676,7 @@ CNN( # 工作原理 -此秘籍的工作方式与第 2 章,“处理神经网络”时非常相似,当我们研究一个全连接神经网络时。 我们从`__init__()`方法和父类的构造函数开始,定义了从 PyTorch 中的`nn.Module`继承的 CNN 类。 之后,我们通过传入与每一层相关的参数来定义 CNN 中的各个层。 对于我们的第一卷积层,输入通道的数量为 3(RGB),输出通道的数量定义为 16,其平方核大小为 3。第二卷积层采用上一层的张量,并具有 16 个输入通道和 32 个输出通道,内核尺寸为`3 x 3`。类似地,第三卷积层具有 32 个输入通道和 64 个输出通道,内核尺寸为`3 x 3`。 我们还需要一个最大池化层,并使用 2 的内核大小和 2 的步幅。我们使用`.view()`将张量的三个维度展平为一个维度,以便可以将其传递到全连接网络中。 `view`函数中的 -1 通过确保`view`函数之前和之后的元素数量保持相同(在本例中为批量大小)来确保将正确的尺寸自动分配给该尺寸。 +此秘籍的工作方式与第 2 章,“处理神经网络”时非常相似,当我们研究一个全连接神经网络时。 我们从`__init__()`方法和父类的构造器开始,定义了从 PyTorch 中的`nn.Module`继承的 CNN 类。 之后,我们通过传入与每一层相关的参数来定义 CNN 中的各个层。 对于我们的第一卷积层,输入通道的数量为 3(RGB),输出通道的数量定义为 16,其平方核大小为 3。第二卷积层采用上一层的张量,并具有 16 个输入通道和 32 个输出通道,内核尺寸为`3 x 3`。类似地,第三卷积层具有 32 个输入通道和 64 个输出通道,内核尺寸为`3 x 3`。 我们还需要一个最大池化层,并使用 2 的内核大小和 2 的步幅。我们使用`.view()`将张量的三个维度展平为一个维度,以便可以将其传递到全连接网络中。 `view`函数中的 -1 通过确保`view`函数之前和之后的元素数量保持相同(在本例中为批量大小)来确保将正确的尺寸自动分配给该尺寸。 对于第一个全连接层,我们有 1,024 个输入(通过将最大池后的`64 x 4 x 4`张量展平而获得)和 512 个输出。 对于最后一个全连接层,我们有 512 个输入和 10 个输出,代表输出类别的数量。 我们还为全连接层定义了一个丢弃层,概率为 0.3。 diff --git a/new/pt-ai-fund/4.md b/new/pt-ai-fund/4.md index 09dc063ddda8c7a0a76f04f86f899987c59b64f9..0e6d406d3b70006324b037a0bb75ea94b7abc368 100644 --- a/new/pt-ai-fund/4.md +++ b/new/pt-ai-fund/4.md @@ -464,7 +464,7 @@ return self.fc(hidden) # 工作原理 -我们使用`torch.nn`模块创建了从`torch.nn.Module`继承的模型类`LSTMClassifier`,并初始化了基类构造函数。 然后,我们定义嵌入层,其中输入维与词汇量大小相同,输出为嵌入维,然后将嵌入层输出传递到 LSTM 层,其中输入维为嵌入维,然后 定义隐藏状态维度。 +我们使用`torch.nn`模块创建了从`torch.nn.Module`继承的模型类`LSTMClassifier`,并初始化了基类构造器。 然后,我们定义嵌入层,其中输入维与词汇量大小相同,输出为嵌入维,然后将嵌入层输出传递到 LSTM 层,其中输入维为嵌入维,然后 定义隐藏状态维度。 然后,我们定义了全连接层和丢弃层。 接下来,我们定义`forward()`方法,该方法接受输入序列,并将其传递给嵌入层,从而产生尺寸为`embedding_dim`的输出,该输出是输入序列的嵌入向量。 然后将这个字向量传递到 LSTM 层,该层输出三个状态-输出状态,隐藏状态和单元状态。 @@ -533,7 +533,7 @@ class MultiLSTMClassifier(nn.Module): # 工作原理 -在此秘籍中,我们在构造函数中添加了`num_layers`和参数以控制模型中 LSTM 的层数,并将其作为关键字参数`num_layers`传递给 LSTM 定义。 +在此秘籍中,我们在构造器中添加了`num_layers`和参数以控制模型中 LSTM 的层数,并将其作为关键字参数`num_layers`传递给 LSTM 定义。 然后,在`forward()`方法中,由于隐藏状态的形状是`[num_layers * num_directions, batch, hidden_dim]`(默认情况下`num_direction`是`1`),因此我们仅使用`hidden[-1]`从最后一个 LSTM 层获取了隐藏状态。 这意味着`hidden[-1]`给出了最后一层的隐藏状态。 通过这样做,我们可以选择`num_layers`作为超参数。 来自较低层的隐藏状态输出作为较高状态的输入传递。 diff --git a/new/pt-ai-fund/6.md b/new/pt-ai-fund/6.md index dc2e807c0dc2049a26adecf010540d494017c5ba..53f1e1e16328b452f9c3dcf6c759c9c4214c8f46 100644 --- a/new/pt-ai-fund/6.md +++ b/new/pt-ai-fund/6.md @@ -116,7 +116,7 @@ def forward(self, input): 在此秘籍中,我们进行了变换以将图像转换为张量并对其进行归一化,就像在第 3 章,“用于计算机视觉的卷积神经网络”中所做的一样。 然后,我们确定了机器上的设备:CPU 或 GPU。 然后,我们定义了从`nn.Module`类继承的`Generator_model`类,就像在所有以前的架构中所做的一样。 -在构造函数中,我们传递了`z_dim`参数,这是我们的噪声向量大小。 然后,我们定义了一个全连接单元`self.fc`,我们将噪声向量传递给该单元,并为其提供了`256 * 7 * 7`输出。 然后,我们定义了一个称为`self.gen`的`nn.Sequential`单元,其中包含用于定义生成器的关键组件。 我们使用 PyTorch 中提供的`nn.ConvTranspose2d`,`nn.BatchNorm2d`和`nn.LeakyReLU`使用一组反卷积,批量规范化和激活层。 `ConvTranspose2d`接受输入通道,输出通道,内核大小,步幅和填充等参数。 `BatchNorm2d`接受上一层的要素/通道数作为其参数,而 LeakyReLU 接受负斜率的角度。 +在构造器中,我们传递了`z_dim`参数,这是我们的噪声向量大小。 然后,我们定义了一个全连接单元`self.fc`,我们将噪声向量传递给该单元,并为其提供了`256 * 7 * 7`输出。 然后,我们定义了一个称为`self.gen`的`nn.Sequential`单元,其中包含用于定义生成器的关键组件。 我们使用 PyTorch 中提供的`nn.ConvTranspose2d`,`nn.BatchNorm2d`和`nn.LeakyReLU`使用一组反卷积,批量规范化和激活层。 `ConvTranspose2d`接受输入通道,输出通道,内核大小,步幅和填充等参数。 `BatchNorm2d`接受上一层的要素/通道数作为其参数,而 LeakyReLU 接受负斜率的角度。 与 ReLU 不同,LeakyReLU 允许传递小的梯度信号以获取负值。 它使来自判别器的梯度流入发生器。 我们在输出层中使用了 tanh 激活,但是从 DCGAN 论文中我们观察到,使用有界激活可以使模型学会快速饱和并覆盖训练分布的色彩空间。 tanh 的对称性在这里可能是一个优势,因为网络应该以对称方式处理较深的颜色和较浅的颜色。 diff --git a/new/pt-ai-fund/7.md b/new/pt-ai-fund/7.md index 3e03a82887185fe8cb2b8feec58966249926e0dd..c3616e5c97224fe249d4dbb2547317e905a725c5 100644 --- a/new/pt-ai-fund/7.md +++ b/new/pt-ai-fund/7.md @@ -7,12 +7,12 @@ RL 是**人工智能**(**AI**)的领域,与我们在前面各章中介绍 在本章中,我们将介绍以下秘籍: * OpenAI Gym 简介– CartPole -* 引入 DQN +* DQN 简介 * 实现 DQN 类 * 训练 DQN -* 引入深度 GA -* 生成代理 -* 选择代理商 +* 深度 GA 简介 +* 生成智能体 +* 选择智能体 * 使智能体突变 * 训练深度 GA @@ -162,7 +162,7 @@ Q 值可以更新如下: >>import torch.nn as nn ``` -2. 接下来,定义一个函数以返回模型: +2. 接下来,定义一个函数来返回模型: ```py def cartpole_model(observation_space, action_space): @@ -216,7 +216,7 @@ def cartpole_model(observation_space, action_space): >>class DQN: ``` -3. 然后,我们将定义构造函数: +3. 然后,我们将定义构造器: ```py >>def __init__(self, observation_space, action_space): @@ -300,7 +300,7 @@ loss.backward() self.optimizer.step() ``` -2. 我们还将更新探查率: +2. 我们还将更新探索率: ```py if not self.explore_limit: @@ -314,7 +314,7 @@ if not self.explore_limit: # 工作原理 -在本秘籍中,我们完成了 DQN 类,并添加了所有必需的功能来训练 DQN。 在构造函数中,我们初始化了探索的初始状态,观察空间和动作空间,然后定义了一个存储单元来保存 DQN 的经验。 我们创建了称为`policy_net`和`target_net`的软骨模型的两个实例。 我们需要两个网络,因为在训练的每个步骤中,Q 网络的值都会移动,并且如果我们使用不断变化的目标值来调整我们的网络,则该网络可能会由于陷入此变化的目标与估计的 Q 值之间的反馈回路而变得不稳定。 网络值。 如果发生这种情况,价值估计将失去控制。 因此,我们使用了两个网络并将`target_net`保持在`eval`模式。 然后,我们使用`MSELoss()`作为损失函数以及`Adam`优化器来更新权重。 +在本秘籍中,我们完成了 DQN 类,并添加了所有必需的功能来训练 DQN。 在构造器中,我们初始化了探索的初始状态,观察空间和动作空间,然后定义了一个存储单元来保存 DQN 的经验。 我们创建了称为`policy_net`和`target_net`的软骨模型的两个实例。 我们需要两个网络,因为在训练的每个步骤中,Q 网络的值都会移动,并且如果我们使用不断变化的目标值来调整我们的网络,则该网络可能会由于陷入此变化的目标与估计的 Q 值之间的反馈回路而变得不稳定。 网络值。 如果发生这种情况,价值估计将失去控制。 因此,我们使用了两个网络并将`target_net`保持在`eval`模式。 然后,我们使用`MSELoss()`作为损失函数以及`Adam`优化器来更新权重。 在`load_memory()`方法中,我们从环境中存储了状态,操作,奖励,下一个状态和终端,以用于训练网络。 我们使用的下一个方法是`predict_action`。 在此方法中,我们使用`np.random.rand()`选择了`random_number`,这为我们提供了`[0,1)`的值。 如果此`random_number`小于当前的`exploration_rate`,则我们选择一个随机动作,该动作由`exploration_rate`控制。 这就是我们合并探索的方式。 但是,如果`random_number`大于`exploration_rate`,则`target_net`会预测`q_values`并选择具有最大 Q 值的动作。 @@ -555,7 +555,7 @@ Rewards: 160.0 module.bias.data.fill_(0.00) ``` -2. 现在,我们将定义一个将创建代理的函数: +2. 现在,我们将定义一个将创建智能体的函数: ```py >>def create_agents(num_agents, observation_space, action_space): @@ -570,7 +570,7 @@ for _ in range(num_agents): agent.apply(init_weight) ``` -4. 我们将关闭每个代理层的梯度: +4. 我们将关闭智能体的每个层的梯度: ```py for param in agent.parameters(): @@ -580,7 +580,7 @@ agent.eval() agents.append(agent) ``` -5. 最后,我们将退回代理商: +5. 最后,我们将返回智能体: ```py return agents @@ -634,7 +634,7 @@ for _ in range(MAX_STEP): return total_reward ``` -4. 然后,我们需要定义平均座席得分: +4. 然后,我们需要定义智能体的平均得分: ```py >>def agent_score(agent, env, runs): @@ -645,7 +645,7 @@ return total_reward return score/runs ``` -5. 最后,我们评估所有代理商的分数: +5. 最后,我们评估所有智能体的分数: ```py >>def all_agent_score(agents, env, runs): @@ -686,7 +686,7 @@ return total_reward child_agent = copy.deepcopy(agent) ``` -3. 接下来,我们将遍历代理的参数: +3. 接下来,我们将遍历智能体的参数: ```py for param in agent.parameters(): @@ -712,7 +712,7 @@ return child_agent top_id = None ``` -6. 接下来,找到`elite`代理: +6. 接下来,找到`elite`智能体: ```py for agent_id in selected_elites: @@ -724,7 +724,7 @@ for agent_id in selected_elites: return copy.deepcopy(agents[top_id]) ``` -7. 获取子代理: +7. 获取子智能体: ```py >>def child_agents(agents, top_parents_id, env, elite_id=None): @@ -741,7 +741,7 @@ return copy.deepcopy(agents[top_id]) return child_agents, elite_id ``` -8. 获取顶级父母: +8. 获取顶级父级: ```py >>def top_parents(scores, num_top_parents): @@ -791,13 +791,13 @@ return copy.deepcopy(agents[top_id]) >>env = gym.make(ENV_NAME) ``` -4. 现在,创建代理: +4. 现在,创建智能体: ```py >>agents = create_agents(num_agents, env.observation_space.shape[0], env.action_space.n) ``` -5. 接下来,遍历几代人: +5. 接下来,遍历几代: ```py >>print(f'| Generation | Score |') diff --git a/new/pt-ai-fund/8.md b/new/pt-ai-fund/8.md index 0f0d0b6168a0c021f70983c90421ca174bac6bd6..4e31df05cb89dcb156af119914a0294be98e193f 100644 --- a/new/pt-ai-fund/8.md +++ b/new/pt-ai-fund/8.md @@ -6,7 +6,7 @@ * 使用 Flask 部署模型 * 创建一个 TorchScript -* 汇出至 ONNX +* 导出至 ONNX # 技术要求 @@ -105,7 +105,7 @@ pip install flask >>model = create_model() ``` -0. 现在,让我们创建路线: +0. 现在,让我们创建路由: ```py >>@app.route('/predict', methods=['POST']) @@ -238,7 +238,7 @@ tensor([[ 0.4238, -0.0524, 0.5719, 0.4747], grad_fn=) ``` -6. 我们可以使用以下代码访问图形: +6. 我们可以使用以下代码访问图: ```py >>traced_cell.graph diff --git a/new/pt-tut-17/38.md b/new/pt-tut-17/38.md index 6d972e2ebbdcbc5a8b99af9595593fcdaa0a5b6e..e4e94e85fa4ed213400c86f74f4c6bb9f4eb501c 100644 --- a/new/pt-tut-17/38.md +++ b/new/pt-tut-17/38.md @@ -40,8 +40,8 @@ print(torch.__version__) 首先定义一个简单的`Module`。 `Module`是 PyTorch 中组成的基本单位。 它包含: -1. 构造函数,为调用准备模块 -2. 一组`Parameters`和子`Modules`。 这些由构造函数初始化,并且可以在调用期间由模块使用。 +1. 构造器,为调用准备模块 +2. 一组`Parameters`和子`Modules`。 这些由构造器初始化,并且可以在调用期间由模块使用。 3. `forward`函数。 这是调用模块时运行的代码。 我们来看一个小例子: @@ -76,7 +76,7 @@ print(my_cell(x, h)) 因此,我们已经: 1. 创建了一个子类`torch.nn.Module`的类。 -2. 定义一个构造函数。 构造函数没有做很多事情,只是调用`super`的构造函数。 +2. 定义一个构造器。 构造器没有做很多事情,只是调用`super`的构造器。 3. 定义了`forward`函数,该函数具有两个输入并返回两个输出。 `forward`函数的实际内容并不是很重要,但它是一种伪造的 [RNN 单元](https://colah.github.io/posts/2015-08-Understanding-LSTMs/),即,该函数应用于循环。 我们实例化了该模块,并制作了`x`和`y`,它们只是`3x4`随机值矩阵。 然后,我们使用`my_cell(x, h)`调用该单元格。 这依次调用我们的`forward`函数。 diff --git a/new/pt-tut-17/44.md b/new/pt-tut-17/44.md index ad775d63c6c7c1dac3ff36ae1705ba1cd8c09616..2f46429f11619a65b53538dcc2d671e128659186 100644 --- a/new/pt-tut-17/44.md +++ b/new/pt-tut-17/44.md @@ -195,7 +195,7 @@ struct Net : torch::nn::Module { ``` -就像在 Python 中一样,我们定义了一个名为`Net`的类(为简单起见,这里是`struct`而不是`class`),然后从模块基类派生它。 在构造函数内部,我们使用`torch::randn`创建张量,就像在 Python 中使用`torch.randn`一样。 一个有趣的区别是我们如何注册参数。 在 Python 中,我们用`torch.nn.Parameter`类包装了张量,而在 C++ 中,我们不得不通过`register_parameter`方法传递张量。 这样做的原因是 Python API 可以检测到属性为`torch.nn.Parameter`类型并自动注册此类张量。 在 C++ 中,反射非常受限制,因此提供了一种更传统(且不太神奇)的方法。 +就像在 Python 中一样,我们定义了一个名为`Net`的类(为简单起见,这里是`struct`而不是`class`),然后从模块基类派生它。 在构造器内部,我们使用`torch::randn`创建张量,就像在 Python 中使用`torch.randn`一样。 一个有趣的区别是我们如何注册参数。 在 Python 中,我们用`torch.nn.Parameter`类包装了张量,而在 C++ 中,我们不得不通过`register_parameter`方法传递张量。 这样做的原因是 Python API 可以检测到属性为`torch.nn.Parameter`类型并自动注册此类张量。 在 C++ 中,反射非常受限制,因此提供了一种更传统(且不太神奇)的方法。 #### 注册子模块并遍历模块层次结构 @@ -251,7 +251,7 @@ struct Net : torch::nn::Module { 您可以在[`torch::nn`命名空间的文档](https://pytorch.org/cppdocs/api/namespace_torch__nn.html)中找到可用的内置模块的完整列表,例如`torch::nn::Linear`,`torch::nn::Dropout`或`torch::nn::Conv2d`。 -关于上述代码的一个微妙之处在于,为什么在构造函数的初始值设定项列表中创建子模块,而在构造函数的主体内部创建参数。 这是有充分的理由的,我们将在下面有关“C++ 前端所有权模型”的部分中对此进行介绍。 但是,最终结果是,就像 Python 中一样,我们可以递归访问模块树的参数。 调用`parameters()`返回一个`std::vector`,我们可以对其进行迭代: +关于上述代码的一个微妙之处在于,为什么在构造器的初始值设定项列表中创建子模块,而在构造器的主体内部创建参数。 这是有充分的理由的,我们将在下面有关“C++ 前端所有权模型”的部分中对此进行介绍。 但是,最终结果是,就像 Python 中一样,我们可以递归访问模块树的参数。 调用`parameters()`返回一个`std::vector`,我们可以对其进行迭代: ```py int main() { @@ -422,7 +422,7 @@ TORCH_MODULE(Linear); ``` -简而言之:该模块不是`Linear`,而是`LinearImpl`。 然后,宏`TORCH_MODULE`定义了实际的`Linear`类。 这个“生成的”类实际上是`std::shared_ptr`的包装。 它是一个包装器,而不是简单的`typedef`,因此,除其他事项外,构造函数仍可按预期工作,即,您仍然可以编写`torch::nn::Linear(3, 4)`而不是`std::make_shared(3, 4)`。 我们将由宏创建的类称为模块*所有者*。 与(共享)指针一样,您可以使用箭头运算符(例如`model->forward(...)`)访问基础对象。 最终结果是一个所有权模型,该模型非常类似于 Python API。 引用语义成为默认语义,但是没有额外输入`std::shared_ptr`或`std::make_shared`。 对于我们的`Net`,使用模块持有人 API 如下所示: +简而言之:该模块不是`Linear`,而是`LinearImpl`。 然后,宏`TORCH_MODULE`定义了实际的`Linear`类。 这个“生成的”类实际上是`std::shared_ptr`的包装。 它是一个包装器,而不是简单的`typedef`,因此,除其他事项外,构造器仍可按预期工作,即,您仍然可以编写`torch::nn::Linear(3, 4)`而不是`std::make_shared(3, 4)`。 我们将由宏创建的类称为模块*所有者*。 与(共享)指针一样,您可以使用箭头运算符(例如`model->forward(...)`)访问基础对象。 最终结果是一个所有权模型,该模型非常类似于 Python API。 引用语义成为默认语义,但是没有额外输入`std::shared_ptr`或`std::make_shared`。 对于我们的`Net`,使用模块持有人 API 如下所示: ```py struct NetImpl : torch::nn::Module {}; @@ -437,7 +437,7 @@ int main() { ``` -这里有一个微妙的问题值得一提。 默认构造的`std::shared_ptr`为“空”,即包含空指针。 什么是默认构造的`Linear`或`Net`? 好吧,这是一个棘手的选择。 我们可以说它应该是一个空(`null`)`std::shared_ptr`。 但是,请记住`Linear(3, 4)`与`std::make_shared(3, 4)`相同。 这意味着如果我们已确定`Linear linear;`应该为空指针,则将无法构造不采用任何构造函数参数或都不使用所有缺省构造函数的模块。 因此,在当前的 API 中,默认构造的模块持有人(如`Linear()`)将调用基础模块的默认构造函数(`LinearImpl()`)。 如果基础模块没有默认构造函数,则会出现编译器错误。 要构造空持有人,可以将`nullptr`传递给持有人的构造函数。 +这里有一个微妙的问题值得一提。 默认构造的`std::shared_ptr`为“空”,即包含空指针。 什么是默认构造的`Linear`或`Net`? 好吧,这是一个棘手的选择。 我们可以说它应该是一个空(`null`)`std::shared_ptr`。 但是,请记住`Linear(3, 4)`与`std::make_shared(3, 4)`相同。 这意味着如果我们已确定`Linear linear;`应该为空指针,则将无法构造不采用任何构造器参数或都不使用所有缺省构造器的模块。 因此,在当前的 API 中,默认构造的模块持有人(如`Linear()`)将调用基础模块的默认构造器(`LinearImpl()`)。 如果基础模块没有默认构造器,则会出现编译器错误。 要构造空持有人,可以将`nullptr`传递给持有人的构造器。 实际上,这意味着您可以使用如先前所示的子模块,在*初始化程序列表*中注册并构造该模块: @@ -451,7 +451,7 @@ struct Net : torch::nn::Module { ``` -或者,您可以先使用空指针构造持有人,然后在构造函数中为其分配值(Python 爱好者更熟悉): +或者,您可以先使用空指针构造持有人,然后在构造器中为其分配值(Python 爱好者更熟悉): ```py struct Net : torch::nn::Module { @@ -815,7 +815,7 @@ torch::Device device(torch::kCUDA) ``` -现在,所有张量都将驻留在 GPU 上,并调用快速 CUDA 内核进行所有操作,而无需我们更改任何下游代码。 如果我们想指定一个特定的设备索引,则可以将其作为第二个参数传递给`Device`构造函数。 如果我们希望不同的张量驻留在不同的设备上,则可以传递单独的设备实例(例如,一个在 CUDA 设备 0 上,另一个在 CUDA 设备 1 上)。 我们甚至可以动态地进行此配置,这通常对于使我们的训练脚本更具可移植性很有用: +现在,所有张量都将驻留在 GPU 上,并调用快速 CUDA 内核进行所有操作,而无需我们更改任何下游代码。 如果我们想指定一个特定的设备索引,则可以将其作为第二个参数传递给`Device`构造器。 如果我们希望不同的张量驻留在不同的设备上,则可以传递单独的设备实例(例如,一个在 CUDA 设备 0 上,另一个在 CUDA 设备 1 上)。 我们甚至可以动态地进行此配置,这通常对于使我们的训练脚本更具可移植性很有用: ```py torch::Device device = torch::kCPU; diff --git a/new/pt-tut-17/46.md b/new/pt-tut-17/46.md index de36887fa05b6d208b40557741d5879445ec281a..d268cf6b837270a114d6149f1fb2e058dd14f32f 100644 --- a/new/pt-tut-17/46.md +++ b/new/pt-tut-17/46.md @@ -61,7 +61,7 @@ TorchScript 编译器了解固定数量的类型。 只有这些类型可以用 ``` -我们正在调用 [OpenCV `Mat`类的构造函数](https://docs.opencv.org/trunk/d3/d63/classcv_1_1Mat.html#a922de793eabcec705b3579c5f95a643e),将张量转换为`Mat`对象。 我们向其传递原始`image`张量的行数和列数,数据类型(在此示例中,我们将其固定为`float32`),最后是指向基础数据的原始指针– `float*`。 `Mat`类的此构造函数的特殊之处在于它不会复制输入数据。 取而代之的是,它将简单地引用此存储器来执行`Mat`上的所有操作。 如果在`image_mat`上执行原地操作,这将反映在原始`image`张量中(反之亦然)。 即使我们实际上将数据存储在 PyTorch 张量中,这也使我们能够使用库的本机矩阵类型调用后续的 OpenCV 例程。 我们重复此过程将`warp` PyTorch 张量转换为`warp_mat` OpenCV 矩阵: +我们正在调用 [OpenCV `Mat`类的构造器](https://docs.opencv.org/trunk/d3/d63/classcv_1_1Mat.html#a922de793eabcec705b3579c5f95a643e),将张量转换为`Mat`对象。 我们向其传递原始`image`张量的行数和列数,数据类型(在此示例中,我们将其固定为`float32`),最后是指向基础数据的原始指针– `float*`。 `Mat`类的此构造器的特殊之处在于它不会复制输入数据。 取而代之的是,它将简单地引用此存储器来执行`Mat`上的所有操作。 如果在`image_mat`上执行原地操作,这将反映在原始`image`张量中(反之亦然)。 即使我们实际上将数据存储在 PyTorch 张量中,这也使我们能够使用库的本机矩阵类型调用后续的 OpenCV 例程。 我们重复此过程将`warp` PyTorch 张量转换为`warp_mat` OpenCV 矩阵: ```py cv::Mat warp_mat(/*rows=*/warp.size(0), diff --git a/new/pt-tut-17/47.md b/new/pt-tut-17/47.md index 952100d2cf4c978f286806701e164a171b17e806..2eb64a59a78d68ab77e850759c9e887e40ac89bb 100644 --- a/new/pt-tut-17/47.md +++ b/new/pt-tut-17/47.md @@ -383,8 +383,8 @@ $ ./infer 也可能需要将自定义类从自定义 C++ 类实例移入或移出`IValue`, such as when you take or return IValues from TorchScript methods or you want to instantiate a custom class attribute in C++. For creating an IValue: -* `torch::make_custom_class()`提供类似于`c10::intrusive_ptr`的 API,因为它将采用您提供给它的任何参数集,调用与该参数集匹配的`T`的构造函数,并包装该实例 然后退回 但是,它不仅返回指向自定义类对象的指针,还返回包装对象的`IValue`。 然后,您可以将此`IValue`直接传递给 TorchScript。 -* 如果您已经有一个指向类的`intrusive_ptr`,则可以使用构造函数`IValue(intrusive_ptr)`直接从其构造`IValue`。 +* `torch::make_custom_class()`提供类似于`c10::intrusive_ptr`的 API,因为它将采用您提供给它的任何参数集,调用与该参数集匹配的`T`的构造器,并包装该实例 然后退回 但是,它不仅返回指向自定义类对象的指针,还返回包装对象的`IValue`。 然后,您可以将此`IValue`直接传递给 TorchScript。 +* 如果您已经有一个指向类的`intrusive_ptr`,则可以使用构造器`IValue(intrusive_ptr)`直接从其构造`IValue`。 要将`IValue`转换回自定义类: diff --git a/new/pt-tut-17/48.md b/new/pt-tut-17/48.md index 2bd749a48cfdea5c58c198877acd4f4f9366749e..00c1d9c30614ddc2653024fbc189e930e4f1bd23 100644 --- a/new/pt-tut-17/48.md +++ b/new/pt-tut-17/48.md @@ -73,7 +73,7 @@ print(example(torch.ones([]))) 注意 -当我们初始化一个空的期货列表时,我们需要在`futures`上添加一个显式类型注释。 在 TorchScript 中,空容器默认假定它们包含张量值,因此我们将列表构造函数#注释为`List[torch.jit.Future[torch.Tensor]]`类型 +当我们初始化一个空的期货列表时,我们需要在`futures`上添加一个显式类型注释。 在 TorchScript 中,空容器默认假定它们包含张量值,因此我们将列表构造器#注释为`List[torch.jit.Future[torch.Tensor]]`类型 本示例使用`fork()`启动函数`foo`的 100 个实例,等待 100 个任务完成,然后对结果求和,返回`-100.0`。 diff --git a/new/pt-tut-17/54.md b/new/pt-tut-17/54.md index c01e98ac76d79a3789369830810d7920db55bfb1..f3c06d22abb5806e8a6969568039b013c87a328f 100644 --- a/new/pt-tut-17/54.md +++ b/new/pt-tut-17/54.md @@ -706,7 +706,7 @@ Global sparsity: 20.00% ## 使用自定义剪裁函数扩展`torch.nn.utils.prune` -要实现自己的剪裁功能,可以通过继承`BasePruningMethod`基类的子类来扩展`nn.utils.prune`模块,这与所有其他剪裁方法一样。 基类为您实现以下方法:`__call__`,`apply_mask`,`apply`,`prune`和`remove`。 除了一些特殊情况外,您无需为新的剪裁技术重新实现这些方法。 但是,您将必须实现`__init__`(构造函数)和`compute_mask`(有关如何根据剪裁技术的逻辑为给定张量计算掩码的说明)。 另外,您将必须指定此技术实现的剪裁类型(支持的选项为`global`,`structured`和`unstructured`)。 需要确定在迭代应用剪裁的情况下如何组合蒙版。 换句话说,当剪裁预剪裁的参数时,当前的剪裁技术应作用于参数的未剪裁部分。 指定`PRUNING_TYPE`将使`PruningContainer`(处理剪裁掩码的迭代应用)正确识别要剪裁的参数。 +要实现自己的剪裁功能,可以通过继承`BasePruningMethod`基类的子类来扩展`nn.utils.prune`模块,这与所有其他剪裁方法一样。 基类为您实现以下方法:`__call__`,`apply_mask`,`apply`,`prune`和`remove`。 除了一些特殊情况外,您无需为新的剪裁技术重新实现这些方法。 但是,您将必须实现`__init__`(构造器)和`compute_mask`(有关如何根据剪裁技术的逻辑为给定张量计算掩码的说明)。 另外,您将必须指定此技术实现的剪裁类型(支持的选项为`global`,`structured`和`unstructured`)。 需要确定在迭代应用剪裁的情况下如何组合蒙版。 换句话说,当剪裁预剪裁的参数时,当前的剪裁技术应作用于参数的未剪裁部分。 指定`PRUNING_TYPE`将使`PruningContainer`(处理剪裁掩码的迭代应用)正确识别要剪裁的参数。 例如,假设您要实现一种剪裁技术,以剪裁张量中的所有其他条目(或者-如果先前已剪裁过张量,则剪裁张量的其余未剪裁部分)。 这将是`PRUNING_TYPE='unstructured'`,因为它作用于层中的单个连接,而不作用于整个单元/通道(`'structured'`),或作用于不同的参数(`'global'`)。 diff --git a/new/pt-tut-17/62.md b/new/pt-tut-17/62.md index 74db5b36eabcdacbc3911f44161bae2f61853e72..f95161e93884342dd778f813223f97eddba45c21 100644 --- a/new/pt-tut-17/62.md +++ b/new/pt-tut-17/62.md @@ -71,7 +71,7 @@ def cleanup(): ``` -现在,让我们创建一个玩具模块,将其与 DDP 封装在一起,并提供一些虚拟输入数据。 请注意,由于 DDP 会将模型状态从等级 0 进程广播到 DDP 构造函数中的所有其他进程,因此您不必担心不同的 DDP 进程从不同的模型参数初始值开始。 +现在,让我们创建一个玩具模块,将其与 DDP 封装在一起,并提供一些虚拟输入数据。 请注意,由于 DDP 会将模型状态从等级 0 进程广播到 DDP 构造器中的所有其他进程,因此您不必担心不同的 DDP 进程从不同的模型参数初始值开始。 ```py class ToyModel(nn.Module): @@ -115,7 +115,7 @@ def run_demo(demo_fn, world_size): ## 带偏差的处理速度 -在 DDP 中,构造函数,正向传递和反向传递都是分布式同步点。 预期不同的进程将启动相同数量的同步,并以相同的顺序到达这些同步点,并在大致相同的时间进入每个同步点。 否则,快速流程可能会提早到达,并在等待流浪者时超时。 因此,用户负责平衡流程之间的工作负载分配。 有时,由于例如网络延迟,资源争夺,不可预测的工作量峰值,不可避免地会出现处理速度偏差。 为了避免在这种情况下超时,请在调用[`init_process_group`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.init_process_group)时传递足够大的`timeout`值。 +在 DDP 中,构造器,正向传递和反向传递都是分布式同步点。 预期不同的进程将启动相同数量的同步,并以相同的顺序到达这些同步点,并在大致相同的时间进入每个同步点。 否则,快速流程可能会提早到达,并在等待流浪者时超时。 因此,用户负责平衡流程之间的工作负载分配。 有时,由于例如网络延迟,资源争夺,不可预测的工作量峰值,不可避免地会出现处理速度偏差。 为了避免在这种情况下超时,请在调用[`init_process_group`](https://pytorch.org/docs/stable/distributed.html#torch.distributed.init_process_group)时传递足够大的`timeout`值。 ## 保存和加载检查点 diff --git a/new/pt-tut-17/64.md b/new/pt-tut-17/64.md index 63cc5a8ac338496ed7b169d75a10bb9bd2806804..5cff1ac976d425ca9e936757f086dcb8ec27c531 100644 --- a/new/pt-tut-17/64.md +++ b/new/pt-tut-17/64.md @@ -105,7 +105,7 @@ class Observer: ``` -agent 的代码稍微复杂一点,我们将其分成多个部分。 在此示例中,代理既充当训练者又充当主角色,以便它向多个分布式观察者发送命令以运行情节,并且还记录本地的所有动作和奖励,这些动作和奖赏将在每个情节之后的训练阶段使用。 下面的代码显示了`Agent`构造函数,其中大多数行都在初始化各种组件。 最后的循环在其他工作者上远程初始化观察者,并在本地将`RRefs`保留给这些观察者。 代理稍后将使用那些观察者`RRefs`发送命令。 应用无需担心`RRefs`的寿命。 每个`RRef`的所有者维护一个参考计数图以跟踪其生命周期,并保证只要该`RRef`的任何活动用户都不会删除远程数据对象。 有关详细信息,请参考`RRef` [设计文档](https://pytorch.org/docs/master/notes/rref.html)。 +agent 的代码稍微复杂一点,我们将其分成多个部分。 在此示例中,代理既充当训练者又充当主角色,以便它向多个分布式观察者发送命令以运行情节,并且还记录本地的所有动作和奖励,这些动作和奖赏将在每个情节之后的训练阶段使用。 下面的代码显示了`Agent`构造器,其中大多数行都在初始化各种组件。 最后的循环在其他工作者上远程初始化观察者,并在本地将`RRefs`保留给这些观察者。 代理稍后将使用那些观察者`RRefs`发送命令。 应用无需担心`RRefs`的寿命。 每个`RRef`的所有者维护一个参考计数图以跟踪其生命周期,并保证只要该`RRef`的任何活动用户都不会删除远程数据对象。 有关详细信息,请参考`RRef` [设计文档](https://pytorch.org/docs/master/notes/rref.html)。 ```py import gym @@ -307,7 +307,7 @@ Solved! Running reward is now 475.3163778435275! 在本节中,我们将使用 RNN 模型来展示如何使用 RPC API 构建分布式模型并行训练。 示例 RNN 模型非常小,可以轻松地放入单个 GPU 中,但是我们仍将其层划分为两个不同的工人来演示这一想法。 开发人员可以应用类似的技术在多个设备和机器上分布更大的模型。 -RNN 模型设计是从 PyTorch [示例](https://github.com/pytorch/examples/tree/master/word_language_model)存储库中的词语言模型中借用的,该存储库包含三个主要组件,一个嵌入表,一个`LSTM`层和一个解码器。 下面的代码将嵌入表和解码器包装到子模块中,以便它们的构造函数可以传递给 RPC API。 在`EmbeddingTable`子模块中,我们有意将`Embedding`层放在 GPU 上以涵盖用例。 在 v1.4 中,RPC 始终在目标工作线程上创建 CPU 张量参数或返回值。 如果函数使用 GPU 张量,则需要将其显式移动到适当的设备。 +RNN 模型设计是从 PyTorch [示例](https://github.com/pytorch/examples/tree/master/word_language_model)存储库中的词语言模型中借用的,该存储库包含三个主要组件,一个嵌入表,一个`LSTM`层和一个解码器。 下面的代码将嵌入表和解码器包装到子模块中,以便它们的构造器可以传递给 RPC API。 在`EmbeddingTable`子模块中,我们有意将`Embedding`层放在 GPU 上以涵盖用例。 在 v1.4 中,RPC 始终在目标工作线程上创建 CPU 张量参数或返回值。 如果函数使用 GPU 张量,则需要将其显式移动到适当的设备。 ```py class EmbeddingTable(nn.Module): @@ -336,7 +336,7 @@ class Decoder(nn.Module): ``` -使用上述子模块,我们现在可以使用 RPC 将它们组合在一起以创建 RNN 模型。 在下面的代码中,`ps`代表参数服务器,该服务器托管嵌入表和解码器的参数。 构造函数使用[远程](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.remote) API 在参数服务器上创建`EmbeddingTable`对象和`Decoder`对象,并在本地创建`LSTM`子模块。 在前进过程中,训练器使用`EmbeddingTable` `RRef`查找远程子模块,然后使用 RPC 将输入数据传递到`EmbeddingTable`,并获取查找结果。 然后,它通过本地`LSTM`层运行嵌入,最后使用另一个 RPC 将输出发送到`Decoder`子模块。 通常,要实现分布式模型并行训练,开发人员可以将模型分为多个子模块,调用 RPC 远程创建子模块实例,并在必要时使用`RRef`查找它们。 正如您在下面的代码中看到的那样,它看起来与单机模型并行训练非常相似。 主要区别是用 RPC 功能替换了`Tensor.to(device)`。 +使用上述子模块,我们现在可以使用 RPC 将它们组合在一起以创建 RNN 模型。 在下面的代码中,`ps`代表参数服务器,该服务器托管嵌入表和解码器的参数。 构造器使用[远程](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.remote) API 在参数服务器上创建`EmbeddingTable`对象和`Decoder`对象,并在本地创建`LSTM`子模块。 在前进过程中,训练器使用`EmbeddingTable` `RRef`查找远程子模块,然后使用 RPC 将输入数据传递到`EmbeddingTable`,并获取查找结果。 然后,它通过本地`LSTM`层运行嵌入,最后使用另一个 RPC 将输出发送到`Decoder`子模块。 通常,要实现分布式模型并行训练,开发人员可以将模型分为多个子模块,调用 RPC 远程创建子模块实例,并在必要时使用`RRef`查找它们。 正如您在下面的代码中看到的那样,它看起来与单机模型并行训练非常相似。 主要区别是用 RPC 功能替换了`Tensor.to(device)`。 ```py class RNNModel(nn.Module): diff --git a/new/pt-tut-17/66.md b/new/pt-tut-17/66.md index dee7736c9b37291d4c09f04ce6687676951f23f8..da25c6c65fa372bcaf07ae3ad8e12a2c71983a9c 100644 --- a/new/pt-tut-17/66.md +++ b/new/pt-tut-17/66.md @@ -83,7 +83,7 @@ class ResNetBase(nn.Module): ``` -现在,我们准备定义两个模型碎片。 对于构造函数,我们只需将所有 ResNet50 层分为两部分,然后将每个部分移至提供的设备中。 两个分片的`forward`函数获取输入数据的`RRef`,在本地获取数据,然后将其移至所需的设备。 将所有层应用于输入后,它将输出移至 CPU 并返回。 这是因为当调用方和被调用方中的设备数量不匹配时,RPC API 要求张量驻留在 CPU 上,以避免无效的设备错误。 +现在,我们准备定义两个模型碎片。 对于构造器,我们只需将所有 ResNet50 层分为两部分,然后将每个部分移至提供的设备中。 两个分片的`forward`函数获取输入数据的`RRef`,在本地获取数据,然后将其移至所需的设备。 将所有层应用于输入后,它将输出移至 CPU 并返回。 这是因为当调用方和被调用方中的设备数量不匹配时,RPC API 要求张量驻留在 CPU 上,以避免无效的设备错误。 ```py class ResNetShard1(ResNetBase): @@ -138,7 +138,7 @@ class ResNetShard2(ResNetBase): ## 第 2 步:将 ResNet50 模型片段拼接到一个模块中 -然后,我们创建一个`DistResNet50`模块来组装两个分片并实现流水线并行逻辑。 在构造函数中,我们使用两个`rpc.remote`调用分别将两个分片放在两个不同的 RPC 工作器上,并保持`RRef`到两个模型部分,以便可以在正向传递中引用它们。 `forward`函数将输入批量分为多个微批量,并将这些微批量以流水线方式馈送到两个模型部件。 它首先使用`rpc.remote`调用将第一个分片应用于微批量,然后将返回的中间输出`RRef`转发到第二个模型分片。 之后,它将收集所有微输出的`Future`,并在循环后等待所有它们。 请注意,`remote()`和`rpc_async()`都立即返回并异步运行。 因此,整个循环是非阻塞的,并将同时启动多个 RPC。 中间输出`y_rref`保留了两个模型零件上一个微批量的执行顺序。 微批量的执行顺序无关紧要。 最后,正向函数将所有微批量的输出连接到一个单一的输出张量中并返回。 `parameter_rrefs`函数是简化分布式优化器构造的助手,将在以后使用。 +然后,我们创建一个`DistResNet50`模块来组装两个分片并实现流水线并行逻辑。 在构造器中,我们使用两个`rpc.remote`调用分别将两个分片放在两个不同的 RPC 工作器上,并保持`RRef`到两个模型部分,以便可以在正向传递中引用它们。 `forward`函数将输入批量分为多个微批量,并将这些微批量以流水线方式馈送到两个模型部件。 它首先使用`rpc.remote`调用将第一个分片应用于微批量,然后将返回的中间输出`RRef`转发到第二个模型分片。 之后,它将收集所有微输出的`Future`,并在循环后等待所有它们。 请注意,`remote()`和`rpc_async()`都立即返回并异步运行。 因此,整个循环是非阻塞的,并将同时启动多个 RPC。 中间输出`y_rref`保留了两个模型零件上一个微批量的执行顺序。 微批量的执行顺序无关紧要。 最后,正向函数将所有微批量的输出连接到一个单一的输出张量中并返回。 `parameter_rrefs`函数是简化分布式优化器构造的助手,将在以后使用。 ```py class DistResNet50(nn.Module): diff --git a/new/pt-tut-17/67.md b/new/pt-tut-17/67.md index 9dcc45134cca0a58a19c8ba68277f48db441b53c..98e7012658d0bfb31998035a257511f5b508c393 100644 --- a/new/pt-tut-17/67.md +++ b/new/pt-tut-17/67.md @@ -130,7 +130,7 @@ class Trainer(object): ## 批量 CartPole 求解器 -本节以 [OpenAI Gym](https://gym.openai.com/) 中的 CartPole-v1 为例,说明批量 RPC 的性能影响。 请注意,我们的目标是演示[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)的用法,而不是构建最佳的 CartPole 求解器或解决大多数不同的 RL 问题,我们使用非常简单的策略和奖励计算策略,并将重点放在 多观察者单代理批量 RPC 实现。 我们使用与前面的教程类似的`Policy`模型,如下所示。 与上一教程相比,不同之处在于其构造函数使用了一个附加的`batch`参数来控制`F.softmax`的`dim`参数,因为进行批量时,`forward`函数中的`x`参数包含来自多个观察者的状态 因此尺寸需要适当更改。 其他所有内容保持不变。 +本节以 [OpenAI Gym](https://gym.openai.com/) 中的 CartPole-v1 为例,说明批量 RPC 的性能影响。 请注意,我们的目标是演示[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)的用法,而不是构建最佳的 CartPole 求解器或解决大多数不同的 RL 问题,我们使用非常简单的策略和奖励计算策略,并将重点放在 多观察者单代理批量 RPC 实现。 我们使用与前面的教程类似的`Policy`模型,如下所示。 与上一教程相比,不同之处在于其构造器使用了一个附加的`batch`参数来控制`F.softmax`的`dim`参数,因为进行批量时,`forward`函数中的`x`参数包含来自多个观察者的状态 因此尺寸需要适当更改。 其他所有内容保持不变。 ```py import argparse @@ -165,7 +165,7 @@ class Policy(nn.Module): ``` -`Observer`的构造函数也会相应地进行调整。 它还带有`batch`参数,该参数控制用于选择动作的`Agent`函数。 在批量模式下,它将调用`Agent`上的`select_action_batch`函数,该函数将很快出现,并且该函数将以[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰。 +`Observer`的构造器也会相应地进行调整。 它还带有`batch`参数,该参数控制用于选择动作的`Agent`函数。 在批量模式下,它将调用`Agent`上的`select_action_batch`函数,该函数将很快出现,并且该函数将以[`@rpc.functions.async_execution`](https://pytorch.org/docs/master/rpc.html#torch.distributed.rpc.functions.async_execution)装饰。 ```py import gym @@ -220,7 +220,7 @@ class Observer: ``` -`Agent`的构造函数还采用`batch`参数,该参数控制如何对动作概率进行批量。 在批量模式下,`saved_log_probs`包含一张张量列表,其中每个张量包含一个步骤中所有观察者的动作抢夺。 如果不进行批量,则`saved_log_probs`是字典,其中的键是观察者 ID,值是该观察者的动作概率列表。 +`Agent`的构造器还采用`batch`参数,该参数控制如何对动作概率进行批量。 在批量模式下,`saved_log_probs`包含一张张量列表,其中每个张量包含一个步骤中所有观察者的动作抢夺。 如果不进行批量,则`saved_log_probs`是字典,其中的键是观察者 ID,值是该观察者的动作概率列表。 ```py import threading diff --git a/new/rl-tf/05.md b/new/rl-tf/05.md index 1909e9422d31b3a75bb503f8ffcb111476d02b3a..3ab8f861a0ac441fcd945e2db9b8c6d74d657012 100644 --- a/new/rl-tf/05.md +++ b/new/rl-tf/05.md @@ -439,7 +439,7 @@ import gym 让我们讨论一下 DQN 类,其中包含深度 Q 网络的架构: -* `__init__`(`self`,`learning_rate`,`gamma`,`n_features`,`n_actions`,`epsilon`,`parameter_changing_pointer`,`memory_size`):默认构造函数,用于分配超参数,例如: +* `__init__`(`self`,`learning_rate`,`gamma`,`n_features`,`n_actions`,`epsilon`,`parameter_changing_pointer`,`memory_size`):默认构造器,用于分配超参数,例如: * `learning_rate` * 伽马,即折现因子 * `n_feature`:状态中的要素数,即状态中的尺寸数 @@ -472,7 +472,7 @@ if __name__ == "__main__": .... ``` -`__init__`:在以下代码片段中解释了默认构造函数以及注释: +`__init__`:在以下代码片段中解释了默认构造器以及注释: ```py def __init__(self,learning_rate,gamma,n_features,n_actions,epsilon,parameter_changing_pointer,memory_size): @@ -939,7 +939,7 @@ if __name__ == "__main__": 让我们讨论 DQN 类及其参数,它包含一个深度 Q 网络的架构: -* `__init__(self,learning_rate,gamma,n_features,n_actions,epsilon,parameter_changing_pointer,memory_size)`:分配超参数的默认构造函数,例如: +* `__init__(self,learning_rate,gamma,n_features,n_actions,epsilon,parameter_changing_pointer,memory_size)`:分配超参数的默认构造器,例如: * `learning_rate` * `gamma`:即折扣系数 * `n_feature`:状态下的要素数量,即状态下的尺寸数 @@ -956,7 +956,7 @@ if __name__ == "__main__": * `fit(self)`:用于训练我们的深度 Q 网络 * `epsilon_greedy(self,obs)`:它可以帮助我们针对给定的观察状态选择正确的操作,即按照现有策略利用操作或随机探索新操作 -现在,使用以下代码定义`__init__ default`构造函数: +现在,使用以下代码定义`__init__ default`构造器: ```py def __init__(self,learning_rate,gamma,n_features,n_actions,epsilon,parameter_changing_pointer,