提交 b29e3ba3 编写于 作者: W wizardforcel

2021-01-24 22:53:21

上级 0c6a2d5c
......@@ -18,7 +18,7 @@ PyTorch 于 2017 年推出,其主要特点是它使用**图形处理单元**
**深度学习**是机器学习的子集,它使用多层神经网络(大型神经网络),受人脑的生物结构启发,其中一层中的神经元接收一些输入数据,对其进行处理, 并将输出发送到下一层。 这些神经网络可以由成千上万个相互连接的节点(神经元)组成,大多数情况下组织在不同的层中,其中一个节点连接到上一层中的多个节点,从那里接收输入数据,还连接到上一层中的几个节点。 下一层,在处理完输出数据后,它将输出数据发送到下一层。
深度学习的普及是由于其准确率。 对于诸如**自然语言处理****NLP**)之类的复杂数据问题,它已达到比其他算法更高的准确。 深度学习的出色表现能力已经达到了机器可以胜过人类的水平,例如在欺诈检测中。 深度学习模型不仅可以优化流程,而且可以提高其质量。 这意味着在诸如安全性之类的出于安全原因至关重要的革命性领域(例如自动驾驶汽车)的进步。
深度学习的普及是由于其准确率。 对于诸如**自然语言处理****NLP**)之类的复杂数据问题,它已达到比其他算法更高的准确。 深度学习的出色表现能力已经达到了机器可以胜过人类的水平,例如在欺诈检测中。 深度学习模型不仅可以优化流程,而且可以提高其质量。 这意味着在诸如安全性之类的出于安全原因至关重要的革命性领域(例如自动驾驶汽车)的进步。
尽管神经网络在几十年前就已经理论化了,但神经网络最近变得流行有两个主要原因:
......@@ -312,7 +312,7 @@ model = nn.Sequential(nn.Linear(input_units, hidden_units), \
loss_funct = nn.MSELoss()
```
首先,导入模块。 然后,定义模型架构。 `input_units`表示输入数据包含的要素数量,`hidden_​​units`表示隐藏层的节点数量, `output_units`表示输出层的节点数量。
首先,导入模块。 然后,定义模型架构。 `input_units`表示输入数据包含的特征数量,`hidden_​​units`表示隐藏层的节点数量, `output_units`表示输出层的节点数量。
从前面的代码中可以看出,网络的架构包含一个隐藏层,其后是 ReLU 激活函数和一个输出层,然后是一个 Sigmoid 激活函数,从而使其成为两层网络。
......
......@@ -409,9 +409,9 @@ EDA 流程很有用,因为它有助于开发人员发现对于定义操作过
识别异常值的一种同样有效的方法是选择第 99 个百分点和第 1 个百分点的值。
当此类值代表要素数据的 5% 以上时,处理此类值非常重要,因为不这样做可能会给模型带来偏差。 与其他任何机器学习算法一样,处理这些值的方法是使用均值或回归插补技术删除异常值或分配新值。
当此类值代表特征数据的 5% 以上时,处理此类值非常重要,因为不这样做可能会给模型带来偏差。 与其他任何机器学习算法一样,处理这些值的方法是使用均值或回归插补技术删除异常值或分配新值。
4. **缺失值**:类似于上述内容,考虑到不同的模型会对这些值做出不同的假设,因此具有许多缺失值的数据集会给模型带来偏差。 同样,当缺失值占要素值的 5% 以上时,应再次使用均值或回归插补技术,通过消除或替换它们来处理它们。
4. **缺失值**:类似于上述内容,考虑到不同的模型会对这些值做出不同的假设,因此具有许多缺失值的数据集会给模型带来偏差。 同样,当缺失值占特征值的 5% 以上时,应再次使用均值或回归插补技术,通过消除或替换它们来处理它们。
5. **定性特征**:最后,考虑到删除或编码数据可能会导致更准确的模型,因此检查数据集是否包含定性数据也是关键的一步。
此外,在许多研究开发中,对同一数据测试了几种算法,以确定哪种算法表现更好,并且其中某些算法不能容忍使用定性数据,就像神经网络一样。 这证明了转换或编码它们以便能够向所有算法提供相同数据的重要性。
......@@ -536,7 +536,7 @@ EDA 流程很有用,因为它有助于开发人员发现对于定义操作过
可以在这里找到这两种方法的简要说明:
* **规范化**:这包括重新缩放值,以便所有要素的所有值都介于零和一之间。 使用以下公式完成此操作:
* **规范化**:这包括重新缩放值,以便所有特征的所有值都介于零和一之间。 使用以下公式完成此操作:
![Figure 2.29: Data normalization ](img/B15778_02_29.jpg)
......@@ -556,7 +556,7 @@ EDA 流程很有用,因为它有助于开发人员发现对于定义操作过
使用与上一练习相同的 Jupyter 笔记本。
1. 将特征与目标分开。 我们这样做只是为了重新特征要素数据:
1. 将特征与目标分开。 我们这样做只是为了重新特征特征数据:
```py
X = data.iloc[:, 1:]
......@@ -633,7 +633,7 @@ EDA 流程很有用,因为它有助于开发人员发现对于定义操作过
使用Pandas`sample`函数,可以对特征和目标矩阵中的元素进行混洗。 通过将`frac`设置为 1,我们确保所有实例都经过改组并在函数的输出中返回。 使用`random_state`参数,我们确保两个数据集均被混洗。
4. 使用索引将经过改组的数据集分为要素和目标数据这三组:
4. 使用索引将经过改组的数据集分为特征和目标数据这三组:
```py
x_train = X_shuffle.iloc[:train_end,:]
......@@ -686,7 +686,7 @@ EDA 流程很有用,因为它有助于开发人员发现对于定义操作过
代码的第一行执行初始拆分。 该函数将以下内容作为参数:
`X_shuffle`,`Y_shuffle`:要拆分的数据集,即要素数据集,以及目标数据集(也称为`X`和`Y`)
`X_shuffle`,`Y_shuffle`:要拆分的数据集,即特征数据集,以及目标数据集(也称为`X`和`Y`)
`test_size`:测试集中要包含的实例的百分比
......@@ -778,7 +778,7 @@ PyTorch 的构建考虑了该领域许多开发人员的意见,其优点是可
在随后的章节中将解释用于其他类型的架构(例如 CNN 和 RNN)的模块。
* **线性层**:这将线性变换应用于输入数据,同时保持内部张量来容纳权重和偏差。 它接收输入样本的大小(数据集的要素数量或上一层的输出数量),输出样本的大小(当前层中的单位数量,即输出数量) ),以及是否在训练过程中使用偏差张量(默认设置为`True`)作为参数。
* **线性层**:这将线性变换应用于输入数据,同时保持内部张量来容纳权重和偏差。 它接收输入样本的大小(数据集的特征数量或上一层的输出数量),输出样本的大小(当前层中的单元数量,即输出数量) ),以及是否在训练过程中使用偏差张量(默认设置为`True`)作为参数。
* **激活函数**:它们接收线性层的输出作为输入,以破坏线性。 如前所述,有几个激活函数可以添加到顺序容器中。 最常用的解释如下:
**ReLU**:这将校正后的线性单元函数应用于包含输入数据的张量。 它接受的唯一参数是是否应在原位进行操作,默认情况下将其设置为`False`。
......@@ -824,7 +824,7 @@ PyTorch 的构建考虑了该领域许多开发人员的意见,其优点是可
3. 使用`sequential()`容器定义网络架构。 确保创建四层网络。 考虑到我们正在处理回归问题,请在前三层使用 ReLU 激活函数,而在最后一层不使用激活函数。
每层的单数应为 100、50、25 和 1:
每层的单数应为 100、50、25 和 1:
```py
model = nn.Sequential(nn.Linear(x_train.shape[1], 100), \
......@@ -911,7 +911,7 @@ PyTorch 的构建考虑了该领域许多开发人员的意见,其优点是可
1. 导入所需的库。
2. 从目标中为我们在上一个活动中创建的所有三组数据拆分函数。 将`DataFrame`转换为张量。
3. 定义网络的架构。 随意尝试层数和每层单数的不同组合。
3. 定义网络的架构。 随意尝试层数和每层单数的不同组合。
4. 定义损失函数和优化器算法。
5. 使用循环对训练网络进行 3,000 个迭代步骤。
6. 通过对测试集的第一个实例执行预测并将其与基本事实进行比较来测试模型。
......
......@@ -152,7 +152,7 @@ print("rows:",data.shape[0]," columns:", data.shape[1])
图 3.4:删除无关特征后的 DCCC 数据集的标题
* **检查缺失值**:接下来,是时候检查数据集是否缺失任何值,如果是,则计算它们代表每个要素的百分比,这可以使用以下代码行完成 :
* **检查缺失值**:接下来,是时候检查数据集是否缺失任何值,如果是,则计算它们代表每个特征的百分比,这可以使用以下代码行完成 :
```py
total = data_clean.isnull().sum()
......@@ -162,7 +162,7 @@ print("rows:",data.shape[0]," columns:", data.shape[1])
          keys=['Total', 'Percent']).transpose()
```
第一行对数据集的每个要素执行缺失值的总和。 接下来,我们计算每个特征缺失值的参与度。 最后,我们将先前计算的两个值连接起来,并将结果显示在表中。 结果如下:
第一行对数据集的每个特征执行缺失值的总和。 接下来,我们计算每个特征缺失值的参与度。 最后,我们将先前计算的两个值连接起来,并将结果显示在表中。 结果如下:
![Figure 3.5: The count of missing values in the DCCC dataset ](img/B15778_03_05.jpg)
......@@ -188,11 +188,11 @@ print("rows:",data.shape[0]," columns:", data.shape[1])
print(outliers)
```
这将导致一个字典,其中包含每个要素名称作为键,并且该值表示该要素离群值的比例。 从这些结果中,可以观察到包含更多异常值的特征是`BILL_AMT1`和`BILL_AMT4`,它们各自占总数的 2.3%。
这将导致一个字典,其中包含每个特征名称作为键,并且该值表示该特征离群值的比例。 从这些结果中,可以观察到包含更多异常值的特征是`BILL_AMT1`和`BILL_AMT4`,它们各自占总数的 2.3%。
这意味着,鉴于异常值对每个特征的参与度太低,因此不需要采取进一步的措施,因此它们不太可能对最终模型产生影响。
* **检查类不平衡**:当目标要素中的类标签未均等表示时,发生类不平衡; 例如,一个数据集包含 90% 的未拖欠下次付款的客户,而 10% 的客户未拖欠下一次付款,则被认为是不平衡的。
* **检查类不平衡**:当目标特征中的类标签未均等表示时,发生类不平衡; 例如,一个数据集包含 90% 的未拖欠下次付款的客户,而 10% 的客户未拖欠下一次付款,则被认为是不平衡的。
有几种处理类不平衡的方法,其中一些方法在这里说明:
......@@ -252,9 +252,9 @@ print("rows:",data.shape[0]," columns:", data.shape[1])
最后, `concat()`函数用于连接过度代表的类的`DataFrame`和大小相同的新创建的`DataFrame`,以便创建要在后续步骤中使用的最终数据集。
使用新创建的数据集,可以再次计算整个数据集中目标要素中每个类标签的参与度,这现在应该反映出具有相同参与度的两个类标签的均等表示的数据集。 此时,数据集的最终形状应等于`(46728,23)`
使用新创建的数据集,可以再次计算整个数据集中目标特征中每个类标签的参与度,这现在应该反映出具有相同参与度的两个类标签的均等表示的数据集。 此时,数据集的最终形状应等于`(46728,23)`
* **从目标拆分特征**:我们将数据集拆分为要素矩阵和目标矩阵,以避免重新调整目标值:
* **从目标拆分特征**:我们将数据集拆分为特征矩阵和目标矩阵,以避免重新调整目标值:
```py
data_resampled = data_resampled.reset_index(drop=True)
......@@ -262,7 +262,7 @@ print("rows:",data.shape[0]," columns:", data.shape[1])
y = data_resampled ["default payment next month"]
```
* **重新缩放数据**:最后,我们重新缩放要素矩阵的值,以避免对模型造成偏差:
* **重新缩放数据**:最后,我们重新缩放特征矩阵的值,以避免对模型造成偏差:
```py
X = (X - X.min())/(X.max() - X.min())
......@@ -300,7 +300,7 @@ final_data.to_csv("dccc_prepared.csv", index=False)
鉴于此,要测量与此类模型相关的表现,您应该计算真实情况值和预测值之间的差,例如,计算 125.3(预测)与 126.38(真实情况值)之间的距离 。 如前所述,有许多方法可以测量此差异,例如**均方误差****MSE**),或另一种变化是**均方根误差****RMSE**),是最常用的指标。
与此相反,分类任务的输出是属于每个输出标签或类的某些输入要素集合的概率,这是使用 Sigmoid(用于二分类)或 softmax(用于多类分类)完成的 )激活函数。 对于二元分类任务,输出层应包含一个(对于 Sigmoid)或两个(对于 softmax)输出节点,而对于多类分类任务,输出层应等于类标签的数量。
与此相反,分类任务的输出是属于每个输出标签或类的某些输入特征集合的概率,这是使用 Sigmoid(用于二分类)或 softmax(用于多类分类)完成的 )激活函数。 对于二元分类任务,输出层应包含一个(对于 Sigmoid)或两个(对于 softmax)输出节点,而对于多类分类任务,输出层应等于类标签的数量。
计算属于每个输出类别的输入特征的似然性的这种能力,再加上`argmax`函数,将以较高的概率检索类别作为最终预测。
......@@ -320,14 +320,14 @@ final_data.to_csv("dccc_prepared.csv", index=False)
考虑到所有这些,将解释以下一组惯例和经验法则,以帮助决策过程定义 ANN 的初始架构:
* **输入层**:这很简单; 只有一个输入层,其单位数量取决于训练数据的形状。 具体来说,输入层中的单位数应等于输入数据包含的要素数。
* **输入层**:这很简单; 只有一个输入层,其单元数量取决于训练数据的形状。 具体来说,输入层中的单元数应等于输入数据包含的特征数。
* **隐藏层**:隐藏层的数量可能有所不同。 ANN 可以有一个隐藏层,也可以没有,也可以没有。 要选择正确的号码,请考虑以下几点:
数据问题越简单,所需的隐藏层就越少。 请记住,线性可分离的简单数据问题应该只有一个隐藏层。 另一方面,可以并且应该使用许多隐藏层(没有限制)解决更复杂的数据问题。
隐藏单元的数量应介于输入层中的单元数和输出层中的单元数之间。
* **输出层**:同样,任何 ANN 仅具有一个输出层。 它包含的单元数取决于要开发的学习任务以及数据问题。 对于回归任务,将只有一个单位,即预测值。 但是,对于分类问题,考虑到模型的输出应该是属于每个类别标签的一组要素的概率,单位数量应等于可用的类别标签的数量。
* **输出层**:同样,任何 ANN 仅具有一个输出层。 它包含的单元数取决于要开发的学习任务以及数据问题。 对于回归任务,将只有一个单元,即预测值。 但是,对于分类问题,考虑到模型的输出应该是属于每个类别标签的一组特征的概率,单元数量应等于可用的类别标签的数量。
* **其他参数**:对于网络的第一种配置,其他参数应保留其默认值。 这主要是因为,在考虑可能表现相同或较差但需要更多资源的更复杂的近似值之前,最好先对数据问题进行最简单的模型测试。
一旦定义了初始架构,就该训练和测量模型的表现以进行进一步分析了,这很可能导致网络架构或其他参数值的更改,例如更改学习率或增加正则化项。
......@@ -436,7 +436,7 @@ class Classifier(torch.nn.Module):
重要的是要提到,交叉熵损失函数要求网络的输出是原始的(在通过使用`softmax`激活函数获得概率之前),这就是为什么通常会发现,用于分类问题的神经网络架构,没有针对输出层的激活函数。 此外,为了通过这种方法进行预测,必须在训练模型后将`softmax`激活函数应用于网络的输出。
解决此问题的另一种方法是对输出层使用`log_softmax`激活函数。 这样,损失函数可以定义为负对数似然损失(`nn.NLLLoss`)。 最后,可以通过从网络输出中获取指数来获得属于每个类别标签的一组要素的概率。 这是本章活动中将使用的方法。
解决此问题的另一种方法是对输出层使用`log_softmax`激活函数。 这样,损失函数可以定义为负对数似然损失(`nn.NLLLoss`)。 最后,可以通过从网络输出中获取指数来获得属于每个类别标签的一组特征的概率。 这是本章活动中将使用的方法。
一旦定义了模型架构,下一步将是对负责根据训练数据进行模型训练的部分进行编码,并在训练和验证集上测量其表现。
......@@ -554,7 +554,7 @@ batch_size = 100
2. 读取先前准备的数据集,该数据集应已命名为`dccc_prepared.csv`
3. 将特征与目标分开。
4. 使用 scikit-learn 的`train_test_split`函数,将数据集分为训练,验证和测试集。 使用 60:20:20 的分配比例。 将`random_state`设置为`0`
5. 考虑到要素矩阵应为浮点型,而目标矩阵则应为非浮点型,将验证和测试集转换为张量。 目前暂时不要转换训练集,因为它们将进行进一步的转换。
5. 考虑到特征矩阵应为浮点型,而目标矩阵则应为非浮点型,将验证和测试集转换为张量。 目前暂时不要转换训练集,因为它们将进行进一步的转换。
6. 构建用于定义网络层的自定义模块类。 包括一个正向函数,该函数指定将应用于每层输出的激活函数。 对于除输出之外的所有层,请使用 **ReLU**,在此处应使用`log_softmax`
7. 实例化模型并定义训练模型所需的所有变量。 将时期数设置为`50`,并将批大小设置为`128`。 使用`0.001`的学习率。
8. 使用训练集的数据训练网络。 使用验证集来衡量表现。 为此,请保存每个时期中训练集和验证集的损失和准确率。
......@@ -673,8 +673,8 @@ batch_size = 100
为此活动使用其他 Jupyter 笔记本。 在那里,您将再次加载数据集并执行与上一个活动中类似的步骤,不同之处在于,将多次执行训练过程以训练不同的架构和训练时间。
1. 导入与上一个活动相同的库。
2. 加载数据并从目标拆分要素。 接下来,使用 60:20:20 的分割比例将数据分割为三个子集(训练,验证和测试)。 最后,将验证和测试集转换为 PyTorch 张量,就像在上一个活动中一样。
3. 考虑到该模型存在较高的偏差,因此重点应放在通过向每个层添加其他层或单元来增加时期数或网络规模。 目的应该是将测试范围内的准确近似为 80%。
2. 加载数据并从目标拆分特征。 接下来,使用 60:20:20 的分割比例将数据分割为三个子集(训练,验证和测试)。 最后,将验证和测试集转换为 PyTorch 张量,就像在上一个活动中一样。
3. 考虑到该模型存在较高的偏差,因此重点应放在通过向每个层添加其他层或单元来增加时期数或网络规模。 目的应该是将测试范围内的准确近似为 80%。
注意
......@@ -714,7 +714,7 @@ batch_size = 100
              "state_dict": model.state_dict()}
```
这会将输入层中的单数保存到检查点中,这在加载模型时会派上用场。
这会将输入层中的单数保存到检查点中,这在加载模型时会派上用场。
2. 使用 PyTorch 的`save()`函数保存模型。
......
......@@ -563,14 +563,14 @@ test_loader = torch.utils.data.DataLoader(test_data, \
展平图像后,滤除项设置为 20%。
Linear1:一个全连接层,接收上一层的展平矩阵作为输入,并生成 100 个单的输出。 为此层使用 ReLU 激活函数。 此处,丢弃期限设置为 20%。
Linear1:一个全连接层,接收上一层的展平矩阵作为输入,并生成 100 个单的输出。 为此层使用 ReLU 激活函数。 此处,丢弃期限设置为 20%。
Linear2:一个全连接层,可生成 10 个输出,每个类标签一个。 将`log_softmax`激活函数用于输出层。
7. 定义训练模型所需的所有参数。 将周期数设置为 50。
8. 训练您的网络,并确保保存训练和验证集的损失和准确率值。
9. 绘制两组的损失和准确率。
0. 在测试集上检查模型的准确--它应该在 72% 左右。
0. 在测试集上检查模型的准确--它应该在 72% 左右。
注意
......@@ -674,7 +674,7 @@ test_data = datasets.CIFAR10('data', train=False, download=True, \
对于测试集,请勿添加任何其他转换。
3. 训练模型 100 个周期。由此得到的训练集和验证集的损失和准确图应与这里所示的相似。
3. 训练模型 100 个周期。由此得到的训练集和验证集的损失和准确图应与这里所示的相似。
![Figure 4.18: Resulting plot showing the loss of the sets ](img/B15778_04_18.jpg)
......@@ -760,7 +760,7 @@ class CNN(nn.Module):
1. 复制上一个活动中的笔记本。
2. 将批量归一化添加到每个卷积层以及第一个 FC 层。
3. 训练模型 100 个周期。由此得到的训练集和验证集的损失和准确图应该与这里的图相似。
3. 训练模型 100 个周期。由此得到的训练集和验证集的损失和准确图应该与这里的图相似。
![Figure 4.21: Resulting plot showing the loss of the sets ](img/B15778_04_21.jpg)
......@@ -770,7 +770,7 @@ class CNN(nn.Module):
图 4.22:结果图显示了集合的丢失
4. 计算结果模型在测试集上的准确--它应该是 78% 左右。
4. 计算结果模型在测试集上的准确--它应该是 78% 左右。
注意
......
......@@ -266,7 +266,7 @@ transforms.Compose([transforms.Normalize((-0.5/0.25, \
要探索 PyTorch 中可用的其他预训练模型,请访问[这里](https://pytorch.org/docs/stable/torchvision/models.html)。
根据前面的信息,仅应加载模型的特征部分,以便提取内容和样式图像的必要特征。 加载模型包括调用`model`子包,然后调用模型名称,并确保将`pretrained`参数设置为`True`(为了加载先前训练过程中的参数),并按照以下代码片段仅加载要素层:
根据前面的信息,仅应加载模型的特征部分,以便提取内容和样式图像的必要特征。 加载模型包括调用`model`子包,然后调用模型名称,并确保将`pretrained`参数设置为`True`(为了加载先前训练过程中的参数),并按照以下代码片段仅加载特征层:
```py
model = models.vgg19(pretrained=True).features
......@@ -348,7 +348,7 @@ for index, layer in model._modules.items():
在前面的代码段中,`layers`是一个字典,将所有相关层的位置(在网络中)映射到将用于识别它们的名称以及`model._modules`包含保存网络各层的字典。
通过使用循环遍历不同层,我们将图像传递到不同层,并保存感兴趣的层的输出(我们先前创建的`layers`词典中的层) 进入`features`词典。 输出字典由包含层名称的键和包含该层的输出要素的值组成。
通过使用循环遍历不同层,我们将图像传递到不同层,并保存感兴趣的层的输出(我们先前创建的`layers`词典中的层) 进入`features`词典。 输出字典由包含层名称的键和包含该层的输出特征的值组成。
为了确定目标图像是否包含与内容图像相同的内容,我们需要检查两个图像中是否存在某些特征。 但是,为了检查目标图像和样式图像的样式表示,必须检查相关性而不是两个图像的特征是否严格存在。 这是因为两个图像的样式特征都不精确,而是近似的。
......@@ -395,7 +395,7 @@ for index, layer in model._modules.items():
    return features
```
输出应该是字典,键是层的名称,值是该层的输出要素
输出应该是字典,键是层的名称,值是该层的输出特征
5. 在我们在本章第一个练习中加载的内容和样式图片上调用`features_extractor`函数。
......
......@@ -573,7 +573,7 @@ onehot = onehot_flat.reshape((batch.shape[0],\
如我们所见,LSTM 层在一行中定义,将以下内容作为参数:
* 输入数据中的要素数量(即,非重复字符的数量)
* 输入数据中的特征数量(即,非重复字符的数量)
* 隐藏维数(神经元)
* LSTM 层数
......@@ -687,7 +687,7 @@ while starter[-1] != "." and counter < 50:
5. 创建一个接受批量并将其编码为单热点矩阵的函数。
6. 创建一个定义网络架构的类。 该类应包含一个用于初始化 LSTM 层状态的附加函数。
7. 请确定要从数据集中创建的批量数量,请记住每个批量应包含 100 个序列,每个批量的长度应为 50。接下来,将编码数据拆分为 100 个序列。
8. 使用 256 作为隐藏单数(总共两个循环层)实例化模型。
8. 使用 256 作为隐藏单数(总共两个循环层)实例化模型。
9. 定义损失函数和优化算法。使用 Adam 优化器和交叉熵损失。训练网络 20 个周期。
注意
......
......@@ -132,7 +132,7 @@
data.isnull().sum().sum()
```
输出应为`0`,这意味着所有要素均不包含缺失值。
输出应为`0`,这意味着所有特征均不包含缺失值。
5. 检查是否有异常值。
......@@ -152,7 +152,7 @@
print(outliers)
```
输出字典应显示所有要素均不包含代表超过 5% 数据的离群值。
输出字典应显示所有特征均不包含代表超过 5% 数据的离群值。
6. 将特征从目标数据中分离出来。
......@@ -172,7 +172,7 @@
![Figure 2.34: Rescaled features data ](img/B15778_02_34.jpg)
图 2.34:重新缩放的要素数据
图 2.34:重新缩放的特征数据
8. 将数据分成三组:训练、验证和测试。使用你喜欢的方法。
......@@ -518,7 +518,7 @@
y_test_torch = torch.tensor(y_test.values)
```
3. 考虑到该模型存在较高的偏差,重点应放在增加周期的数量上,或通过在每层中增加额外的层或单位来增加网络的规模。目标应该是将验证集的准确度近似到 80%。
3. 考虑到该模型存在较高的偏差,重点应放在增加周期的数量上,或通过在每层中增加额外的层或单元来增加网络的规模。目标应该是将验证集的准确率近似到 80%。
之后,将显示表现最佳的模型,该模型是在几次微调尝试之后实现的。 首先,定义模型架构和正向传播,如以下代码片段所示:
......@@ -642,7 +642,7 @@
图 3.18:显示集合精度的图
5. 使用表现最好的模型,对测试集(在微调过程中不应该使用)进行预测。通过计算模型在该集上的准确,将预测结果与基本事实进行比较。
5. 使用表现最好的模型,对测试集(在微调过程中不应该使用)进行预测。通过计算模型在该集上的准确,将预测结果与基本事实进行比较。
```py
model.eval()
......@@ -674,7 +674,7 @@
图 3.19:`final_model.py`的屏幕截图
3. 在 Jupyter 笔记本中,保存表现最好的模型。请务必保存与输入单相关的信息,以及模型的参数。将其命名为`checkpoint.pth`
3. 在 Jupyter 笔记本中,保存表现最好的模型。请务必保存与输入单相关的信息,以及模型的参数。将其命名为`checkpoint.pth`
```py
checkpoint = {"input": X_train.shape[1], \
......@@ -883,7 +883,7 @@
展平图像后,使用掉落项设置为 20%。
Linear1:一个全连接层,接收上一层的展平矩阵作为输入,并生成 100 个单的输出。 为此层使用 ReLU 激活函数。 此处的丢弃期限设置为 20%。
Linear1:一个全连接层,接收上一层的展平矩阵作为输入,并生成 100 个单的输出。 为此层使用 ReLU 激活函数。 此处的丢弃期限设置为 20%。
Linear2:一个全连接层,可生成 10 个输出,每个类标签一个。 将`log_softmax`激活函数用于输出层:
......
......@@ -51,7 +51,7 @@
# 可视化参数
神经网络通过梯度下降学习,但是它们学到什么呢? 答案是参数,但我们希望了解这些参数的含义。 在下图中,如果我们看一下前几层,将看到简单易懂的提取特征,例如边缘和兴趣点,而更深层的特征则更复杂。 例如,如果我们查看下图中的最后一层,将观察到与初始层要素相比,要素是不可识别的。 这是因为随着我们进入更深的层次,越来越多的信息丰富的特征正在通过各种矩阵运算来提取。 这使得高维信息可以压缩到低维损失函数空间中,并得到训练后的模型:
神经网络通过梯度下降学习,但是它们学到什么呢? 答案是参数,但我们希望了解这些参数的含义。 在下图中,如果我们看一下前几层,将看到简单易懂的提取特征,例如边缘和兴趣点,而更深层的特征则更复杂。 例如,如果我们查看下图中的最后一层,将观察到与初始层特征相比,特征是不可识别的。 这是因为随着我们进入更深的层次,越来越多的信息丰富的特征正在通过各种矩阵运算来提取。 这使得高维信息可以压缩到低维损失函数空间中,并得到训练后的模型:
![](img/2ea3be34-ced7-4c60-a302-98d1f0c35e3e.jpeg)
......@@ -78,7 +78,7 @@
我们不单独训练层的主要原因有两个:
* 对于每一层,我们都添加了数千个参数。 因此,类似于我们在共享参数的卷积神经网络方法中所做的工作,我们可以更快地优化网络。
* 权重共享确保两个相似的图像不会映射到要素嵌入空间中的不同位置。
* 权重共享确保两个相似的图像不会映射到特征嵌入空间中的不同位置。
特征嵌入是将特征投影到某个更高维度的空间(也称为**特征嵌入空间**),具体取决于我们要实现的任务。
......
......@@ -48,7 +48,7 @@
# 了解有向图模型
现在,在深入研究用于单次学习的概率模型之前,我们将简要研究有向图模型。 有向图模型(也称为贝叶斯网络)由与有向边相连的随机变量定义,如在父子关系中。 下图显示了一个这样的贝叶斯网络:
现在,在深入研究用于单次学习的概率模型之前,我们将简要研究有向图模型。 有向图模型(也称为贝叶斯网络)由与有向边相连的随机变量定义,如在父子关系中。 下图显示了一个这样的贝叶斯网络:
![](img/169cea75-5669-4783-a7c4-a4b77f185c91.png)
......@@ -56,7 +56,7 @@
![](img/9511985a-1153-4134-8e00-3c8126a5dc83.png)
前面方程右侧的条件分布具有大量参数。 这是因为每个分布都以许多变量为条件,并且每个条件变量都有其自己的结果空间。 如果我们在有大量条件变量的情况下在图中走得更远,则这种影响会更加突出。 因此,要学习每种条件分布的庞大参数集,我们需要大量的标记数据,这在现代机器学习任务中通常是不可用的。
前面方程右侧的条件分布具有大量参数。 这是因为每个分布都以许多变量为条件,并且每个条件变量都有其自己的结果空间。 如果我们在有大量条件变量的情况下在图中走得更远,则这种影响会更加突出。 因此,要学习每种条件分布的庞大参数集,我们需要大量的标记数据,这在现代机器学习任务中通常是不可用的。
这是有向图模型进入图片的地方。 它断言了概率的一些条件独立性,从而简化了前面描述的方程式。 有向图模型中的每个变量在条件上独立于给定其父对象的非后代。 有向图模型不过是条件独立性的表示。 更正式地讲,如果`X[i]`是有向图中的顶点,则`V`是顶点数,`X[pa(t)]`都是顶点`X[t]`的父级,则所有顶点上的联合概率分布可写为:
......@@ -149,13 +149,13 @@ K 次学习的一种非常常见的方法是训练具有相关任务的大型模
# 权重的概率模型
假设由于最大数据集`D_tilde`而在第一阶段获知的 softmax 权重`W_tilde`的不确定性很小。 将此近似值与上图中的图模型结构结合起来,我们可以摆脱原始数据集`D_tilde`,并使用`W_tilde`的 MAP 估计值(`W_MAP`)处于概念学习和 K 次学习阶段。 完整的概率模型遵循以下步骤:
假设由于最大数据集`D_tilde`而在第一阶段获知的 softmax 权重`W_tilde`的不确定性很小。 将此近似值与上图中的图模型结构结合起来,我们可以摆脱原始数据集`D_tilde`,并使用`W_tilde`的 MAP 估计值(`W_MAP`)处于概念学习和 K 次学习阶段。 完整的概率模型遵循以下步骤:
1. K 次学习过程将信息合并到两个数据集`D_tilde``D`中,以在`W`上生成后验分布:
![](img/3f0ac346-6f71-413c-9364-4da122454208.png)
2. 从图模型,在上图中,我们知道给定父级`W`的情况,`D`有条件地独立于`D_tilde`我们有以下内容:
2. 从图模型,在上图中,我们知道给定父级`W`的情况,`D`有条件地独立于`D_tilde`我们有以下内容:
![](img/93b309a8-288c-4cd2-883f-f166d5f51c7d.png)
......@@ -171,7 +171,7 @@ K 次学习的一种非常常见的方法是训练具有相关任务的大型模
# 选择权重模型
给定图模型,我们可以写出概念超参数(`θ`)和模型权重(`W``W_tilde`)的联合分布如下:
给定图模型,我们可以写出概念超参数(`θ`)和模型权重(`W``W_tilde`)的联合分布如下:
![](img/cd64030c-1e6b-4a97-bc41-e5043bf94a5e.png)
......@@ -220,7 +220,7 @@ K 次测试时间`P(y*, x*, D, W_tilde_MAP) = ∫p(y* | x*, W)P(W | D, W_tilde_M
在本章中,我们学习了在贝叶斯框架内开发概率模型的方法,该模型可以极大地减少数据需求并达到人类水平的表现。 从前面讨论的手写字符的示例中,我们还观察到概率模型不仅可以学习如何对字符进行分类,还可以学习基本概念,即以新的方式应用获得的知识,例如从集合中仅有的几个字符生成全新的字符,以及将字符解析为部分和关系。
但是,人类学习器需要从具有丰富重叠结构的许多经验中获得的广泛的先前经验来完成新的学习任务。 为了模仿人类学习,图形结构需要具有更多的依赖性,并且需要在模型中内置丰富的归纳偏差。 还应注意,人类在很小的时候就对物体的物理特性(形状,运动和其他力学)有很好的认识。 学习模型不会隐式地捕获对象的直观物理特性,也不会显式地将其嵌入对象中。 直观物理(类似于游戏引擎中嵌入的物理)与概率模型和深度学习的集成,是朝着更健壮的单发学习迈出的重要一步。 最后,由于先验知识以强先验和图形结构的形式嵌入到概率模型中,因此与必须从头学习任务的深度学习模型相比,它们的数据消耗更少。 但这是以在概率模型中进行有效推理的计算挑战为代价的。 在推断时,这些模型必须搜索巨大的概率空间,这对于现代计算机而言是不实际的。 相反,深度学习模型具有精确且计算上便宜的推断。 最近的工作通过使用前馈映射对*摊销*概率推理计算来解决图形模型中的这一推理挑战,可以使用成对的生成/识别网络来学习。 这提供了另一条有希望的研究领域,使深度学习和概率模型更加接近。
但是,人类学习器需要从具有丰富重叠结构的许多经验中获得的广泛的先前经验来完成新的学习任务。 为了模仿人类学习,图结构需要具有更多的依赖性,并且需要在模型中内置丰富的归纳偏差。 还应注意,人类在很小的时候就对物体的物理特性(形状,运动和其他力学)有很好的认识。 学习模型不会隐式地捕获对象的直观物理特性,也不会显式地将其嵌入对象中。 直观物理(类似于游戏引擎中嵌入的物理)与概率模型和深度学习的集成,是朝着更健壮的单发学习迈出的重要一步。 最后,由于先验知识以强先验和图结构的形式嵌入到概率模型中,因此与必须从头学习任务的深度学习模型相比,它们的数据消耗更少。 但这是以在概率模型中进行有效推理的计算挑战为代价的。 在推断时,这些模型必须搜索巨大的概率空间,这对于现代计算机而言是不实际的。 相反,深度学习模型具有精确且计算上便宜的推断。 最近的工作通过使用前馈映射对*摊销*概率推理计算来解决图模型中的这一推理挑战,可以使用成对的生成/识别网络来学习。 这提供了另一条有希望的研究领域,使深度学习和概率模型更加接近。
# 进一步阅读
......
......@@ -164,7 +164,7 @@
每个输入节点都连接到另一层中的每个节点。 这被称为**全连接层**。 然后,将来自的全连接层的输出乘以其自身的附加权重,以便预测`y`。 因此,我们的预测不再只是`X[i]θ[i]`的函数,而是现在包括针对每个参数的多个学习权重。 特征`X[1]`不再仅受`θ[1]`影响。 现在,它也受到`θ[1,1], θ[2,1], θ[2,2], θ[2,3]`的影响。 参数。
由于全连接层中的每个节点都将`X`的所有值作为输入,因此神经网络能够学习输入特征之间的交互特征。 多个全连接层可以链接在一起,以学习更复杂的特征。 在本书中,我们将看到我们构建的所有神经网络都将使用该概念。 将不同品种的多层链接在一起,以构建更复杂的模型。 但是,在我们完全理解神经网络之前,还有另外一个关键素要涵盖:激活函数。
由于全连接层中的每个节点都将`X`的所有值作为输入,因此神经网络能够学习输入特征之间的交互特征。 多个全连接层可以链接在一起,以学习更复杂的特征。 在本书中,我们将看到我们构建的所有神经网络都将使用该概念。 将不同品种的多层链接在一起,以构建更复杂的模型。 但是,在我们完全理解神经网络之前,还有另外一个关键素要涵盖:激活函数。
## 激活函数
......
......@@ -230,7 +230,7 @@ class MNISTClassifier(nn.Module):
我们像从 Python PyTorch 中继承`nn.Module`一样,在 Python 中构建普通类,从而构建分类器。 在我们的`__init__`方法中,我们定义了神经网络的每一层。 在这里,我们定义了大小可变的全连接线性层。
我们的第一层接受`784`输入,因为这是我们要分类的每个图像的大小(`28x28`)。 然后,我们看到一层的输出必须与下一层的输入具有相同的值,这意味着我们的第一个全连接层输出`392`个单位,而我们的第二层则采用`392`单位作为输入。 对每一层都重复一次,每次它们具有一半的单位数量,直到我们到达最终的全连接层为止,该层输出`10`个单位。 这是我们分类层的长度。
我们的第一层接受`784`输入,因为这是我们要分类的每个图像的大小(`28x28`)。 然后,我们看到一层的输出必须与下一层的输入具有相同的值,这意味着我们的第一个全连接层输出`392`个单元,而我们的第二层则采用`392`单元作为输入。 对每一层都重复一次,每次它们具有一半的单元数量,直到我们到达最终的全连接层为止,该层输出`10`个单元。 这是我们分类层的长度。
我们的网络现在看起来像这样:
......@@ -238,7 +238,7 @@ class MNISTClassifier(nn.Module):
图 2.12 –我们的神经网络
在这里,我们可以看到我们的最后一层输出了`10`个单。 这是因为我们希望预测每个图像是否为 0 到 9 之间的数字,总共是 10 种不同的可能分类。 我们的输出是长度为`10`的向量,并且包含图像的 10 种可能值中的每一个的预测。 在进行最终分类时,我们将数值最高的数字分类作为模型的最终预测。 例如,对于给定的预测,我们的模型可能会预测图像类型为 1 的概率为 10%,类型 2 的概率为 10%,类型 3 的概率为 80%。 因此,我们将类型 3 作为预测,因为它以最高概率被预测。
在这里,我们可以看到我们的最后一层输出了`10`个单。 这是因为我们希望预测每个图像是否为 0 到 9 之间的数字,总共是 10 种不同的可能分类。 我们的输出是长度为`10`的向量,并且包含图像的 10 种可能值中的每一个的预测。 在进行最终分类时,我们将数值最高的数字分类作为模型的最终预测。 例如,对于给定的预测,我们的模型可能会预测图像类型为 1 的概率为 10%,类型 2 的概率为 10%,类型 3 的概率为 80%。 因此,我们将类型 3 作为预测,因为它以最高概率被预测。
## 实现丢弃
......@@ -291,7 +291,7 @@ Loss(y) = -log(y)
然后将其汇总到数据集中所有正确的类中,以计算总损失。 请注意,我们在构建分类器时定义了对数 softmax,因为它已经应用了 softmax 函数(将预测输出限制在 0 到 1 之间)并获取了日志。 这意味着`log(y)`已经被计算出来,因此我们要计算网络上的总损失所需要做的就是计算输出的负和。
我们还将优化器定义为 Adam 优化器。 优化器控制模型中的**学习率**。 模型的学习率定义了每次训练期间参数更新的大小。 学习速率的大小越大,梯度下降期间参数更新的大小越大。 优化器动态控制该学习速率,以便在初始化模型时,参数更新很大。 但是,随着模型的学习和向损失最小化点的靠近,优化器将控制学习率,因此参数更新变得更小,可以更精确地定位局部最小值。
我们还将优化器定义为 Adam 优化器。 优化器控制模型中的**学习率**。 模型的学习率定义了每次训练期间参数更新的大小。 学习率的大小越大,梯度下降期间参数更新的大小越大。 优化器动态控制该学习率,以便在初始化模型时,参数更新很大。 但是,随着模型的学习和向损失最小化点的靠近,优化器将控制学习率,因此参数更新变得更小,可以更精确地定位局部最小值。
## 训练我们的网络
......@@ -367,7 +367,7 @@ print(preds[0])
图 2.15 –预测输出
在这里,我们可以看到我们的预测是一个长度为 10 的向量,并且对每个可能的类别(0 到 9 之间的数字)进行了预测。 预测值最高的是我们的模型选择的预测值。 在这种情况下,它是向量的第十个单,等于数字 9。请注意,由于我们较早使用对数 softmax,因此我们的预测是对数而非原始概率。 要将它们转换回概率,我们可以使用`x`对其进行转换。
在这里,我们可以看到我们的预测是一个长度为 10 的向量,并且对每个可能的类别(0 到 9 之间的数字)进行了预测。 预测值最高的是我们的模型选择的预测值。 在这种情况下,它是向量的第十个单,等于数字 9。请注意,由于我们较早使用对数 softmax,因此我们的预测是对数而非原始概率。 要将它们转换回概率,我们可以使用`x`对其进行转换。
现在,我们可以构造一个摘要`DataFrame`,其中包含我们的真实测试数据标签以及模型预测的标签:
......
......@@ -123,7 +123,7 @@ CNN 背后的基本概念是卷积。 **卷积**本质上是一个滑动窗口
通过这种方式,我们的模型现在将能够在多个类上执行分类任务,并且我们不再局限于我们之前看过的 0 或 1 二分类。 具有更多类的模型可能会因预测而受到影响,因为有更多不同的类可以区分。
在二元分类模型中,假设我们有一个平衡的数据集,我们希望我们的模型仅执行随机猜测就可以达到 50% 的准确率,而具有五个不同类别的多类模型只能具有基线精度 20%。 这意味着仅仅因为多类模型的准确远低于 100%,并不意味着模型本身固有地在做出预测方面就很糟糕。 当涉及从数百个不同类别进行预测的训练模型时,尤其如此。 在这些情况下,仅具有 50% 准确率的模型将被认为表现良好。
在二元分类模型中,假设我们有一个平衡的数据集,我们希望我们的模型仅执行随机猜测就可以达到 50% 的准确率,而具有五个不同类别的多类模型只能具有基线精度 20%。 这意味着仅仅因为多类模型的准确远低于 100%,并不意味着模型本身固有地在做出预测方面就很糟糕。 当涉及从数百个不同类别进行预测的训练模型时,尤其如此。 在这些情况下,仅具有 50% 准确率的模型将被认为表现良好。
现在我们已经定义了多类分类问题,我们需要加载数据以训练模型。
......
......@@ -561,7 +561,7 @@ def forward(self, input, h, cell):
图 7.19 –翻译输出第二部分
我们还可以看到一些似乎被误解的示例。 在下面的示例中,我们预测的德语句子的英语等同词为`A woman climbs through one`,这不等于`Young woman climbing rock face`。 但是,该模型仍然设法翻译了英语句子(女性和攀岩)的关键素:
我们还可以看到一些似乎被误解的示例。 在下面的示例中,我们预测的德语句子的英语等同词为`A woman climbs through one`,这不等于`Young woman climbing rock face`。 但是,该模型仍然设法翻译了英语句子(女性和攀岩)的关键素:
![Figure 7.20 – Translation output part three ](img/B12365_07_20.jpg)
......
......@@ -574,7 +574,7 @@ A: No
虽然返回目标文档的相关区域是有用的训练模型,但它与真实的机器理解模型并不相同。 为此,我们必须合并较大语言模型的元素。
在任何机器理解任务中,实际上都有三个素在起作用。 我们已经知道存在一个问题和答案,但是也有一个可以确定给定问题答案的相关上下文。 例如,我们可以问以下问题:
在任何机器理解任务中,实际上都有三个素在起作用。 我们已经知道存在一个问题和答案,但是也有一个可以确定给定问题答案的相关上下文。 例如,我们可以问以下问题:
```py
What day is it today?
......
......@@ -20,7 +20,7 @@
第 4 章,“用于 NLP 的循环神经网络”探索循环神经网络,并研究 RNN 中的各种修改以及最佳实践。
第 5 章,“迁移学习和 TensorBoard”显示了如何使用经过训练的 ResNet-50 模型训练图像分类器以区分正常和肺炎的胸部 X 射线。 我们将替换分类器,并使用两个输出单来代表正常和肺炎类别。
第 5 章,“迁移学习和 TensorBoard”显示了如何使用经过训练的 ResNet-50 模型训练图像分类器以区分正常和肺炎的胸部 X 射线。 我们将替换分类器,并使用两个输出单来代表正常和肺炎类别。
第 6 章,“探索生成对抗网络”探索生成对抗网络,以及如何实现 PyTorch 的组件并训练端到端网络。 我们将探索 DCGAN,并通过渐进式 GAN 网络进一步改善 DCGAN 的局限性。
......
......@@ -4,7 +4,7 @@
PyTorch 是 Python 中的一个开源深度学习框架,它使我们能够从研究问题开始,提出原型解决方案,并在开发此解决方案的过程中一直进行到创建分布式计算集群为止。 它使您从研究到生产都可以覆盖。 PyTorch 改编自 Torch,后者是一个科学计算框架,广泛支持机器学习算法,使用 Lua 编写,可为您提供强大的功能(使用 GPU)。 那为什么要用 PyTorch?
PyTorch 与 Python 深度集成,具有命令式风格,使用类似 Python 的语法,并且在 Eager 模式下易于使用且灵活。 它的学习曲线很浅,可以让您专注于功能而不是框架的样板和语法。 Python 命令的纯命令执行将失去很多优化机会,因此,随着**即时****JIT**)编译器的引入,PyTorch 允许过渡到图形 C++ 运行时环境中用于速度,功能和优化的模式。 它得到了来自不同领域的专业人员的大力社区支持,并且与库打交道。 它具有与框架互操作性的本地**开放神经网络交换****ONNX**)支持。 它是分布式的,可扩展到生产环境,与 TensorBoard 集成,并具有出色的文档和 API,您可以轻松编写针对 CPU 和 GPU 的自定义扩展。 我们将在接下来的章节中探索这些以及更多内容。
PyTorch 与 Python 深度集成,具有命令式风格,使用类似 Python 的语法,并且在 Eager 模式下易于使用且灵活。 它的学习曲线很浅,可以让您专注于功能而不是框架的样板和语法。 Python 命令的纯命令执行将失去很多优化机会,因此,随着**即时****JIT**)编译器的引入,PyTorch 允许过渡到 C++ 运行时的图环境中用于速度,功能和优化的模式。 它得到了来自不同领域的专业人员的大力社区支持,并且与库打交道。 它具有与框架互操作性的本地**开放神经网络交换****ONNX**)支持。 它是分布式的,可扩展到生产环境,与 TensorBoard 集成,并具有出色的文档和 API,您可以轻松编写针对 CPU 和 GPU 的自定义扩展。 我们将在接下来的章节中探索这些以及更多内容。
在本章中,我们将介绍以下秘籍:
......@@ -314,7 +314,7 @@ tensor([[3, 3],
# 工作原理
在本秘籍中,我们介绍了从各种数据源创建张量的各种方法。 在我们开始探索使用 PyTorch 进行深度学习的概念及其原理之前,必须了解一些最常用的功能来处理数据的基本单位张量。 我们可以使用`torch.tensor()`方法创建具有各种值和形状的张量。 我们甚至可以从均匀分布或标准正态分布中得出张量,这对于初始化神经网络以获得最佳表现和训练时间至关重要,所有这些张量都具有默认的`torch.FloatTensor` 数据类型,并使用`dtype`更新数据类型。 参数。
在本秘籍中,我们介绍了从各种数据源创建张量的各种方法。 在我们开始探索使用 PyTorch 进行深度学习的概念及其原理之前,必须了解一些最常用的功能来处理数据的基本单位张量。 我们可以使用`torch.tensor()`方法创建具有各种值和形状的张量。 我们甚至可以从均匀分布或标准正态分布中得出张量,这对于初始化神经网络以获得最佳表现和训练时间至关重要,所有这些张量都具有默认的`torch.FloatTensor` 数据类型,并使用`dtype`更新数据类型。 参数。
`.ones()`方法创建一个包含给定形状的张量的张量,`.zeros()`用所有零填充该张量,`full()`方法将给定形状的张量填充。 `.empty()`方法创建一个空张量,`.rand()``[0, 1]`的均匀分布中绘制一个具有随机值的张量,`.randn()`从正态分布中绘制均值为 0 和方差 1 的一个具有随机值的张量 ,也称为标准正态分布。
......
......@@ -142,7 +142,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
我们可以用任何名称定义模型类,但是重要的是它是`nn.Module`的子类并具有`super().__init__()`,该类为模型提供了许多有用的方法和属性,并保留了架构的知识。
我们使用`nn.Linear()`通过输入和输出尺寸来定义全连接层。 我们将 softmax 层用于最后一层输出,因为有 10 个输出类。 我们在输出层之前的层中使用 ReLU 激活来学习数据中的非线性。 `hidden1`层采用 784 个输入单元,并给出 256 个输出单元。 `hidden2`短语输出 128 个单位,输出层有 10 个输出单位,代表 10 个输出类别。 softmax 层将激活转换为概率,以便沿维度 1 加 1。
我们使用`nn.Linear()`通过输入和输出尺寸来定义全连接层。 我们将 softmax 层用于最后一层输出,因为有 10 个输出类。 我们在输出层之前的层中使用 ReLU 激活来学习数据中的非线性。 `hidden1`层采用 784 个输入单元,并给出 256 个输出单元。 `hidden2`短语输出 128 个单元,输出层有 10 个输出单元,代表 10 个输出类别。 softmax 层将激活转换为概率,以便沿维度 1 加 1。
# 更多
......@@ -154,7 +154,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
# 创建一个全连接网络
在本秘籍中,我们将扩展在先前秘籍“定义神经网络类”中定义的类。 在“定义神经网络类”秘籍中,我们仅创建了所需架构的组件; 现在我们将把所有这些部分捆绑在一起,以建立一个明智的网络。 我们各层的进度将从 784 个单位增加到 256 个,然后是 128 个,最后是 10 个单位的输出层。
在本秘籍中,我们将扩展在先前秘籍“定义神经网络类”中定义的类。 在“定义神经网络类”秘籍中,我们仅创建了所需架构的组件; 现在我们将把所有这些部分捆绑在一起,以建立一个明智的网络。 我们各层的进度将从 784 个单元增加到 256 个,然后是 128 个,最后是 10 个单元的输出层。
在本秘籍中,我们将使用类的构造器中定义的组件来研究网络架构。 然后,我们将完成网络类定义并创建其对象。
......@@ -232,7 +232,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
当传递输入时,将引用模型对象的名称自动调用 forward 方法。 `nn.Module`自动创建将在正向方法中使用的权重和偏差张量。 线性单元本身定义了线性函数,例如`xW + B`; 要具有非线性函数,我们需要插入非线性激活函数,在这里我们使用最流行的激活函数之一 ReLU,尽管您可以在 PyTorch 中使用其他可用的激活函数。
我们的输入层有 784 个单位(从`28 x 28`像素开始),第一层具有 ReLU 激活的 256 个单位,然后具有 ReLU 激活的 128 个单位,最后有 softmax 激活的 10 个单位。 我们通过 softmax 压缩最终层输出的原因是因为我们希望有 1 个输出类的概率高于所有其他类,并且输出概率之和应等于 1。softmax 函数的参数`dim=1`是为了确保在输出的各列中采用 softmax。 然后,我们使用模型类创建一个对象,并使用`print(model)`打印该类的详细信息。
我们的输入层有 784 个单元(从`28 x 28`像素开始),第一层具有 ReLU 激活的 256 个单元,然后具有 ReLU 激活的 128 个单元,最后有 softmax 激活的 10 个单元。 我们通过 softmax 压缩最终层输出的原因是因为我们希望有 1 个输出类的概率高于所有其他类,并且输出概率之和应等于 1。softmax 函数的参数`dim=1`是为了确保在输出的各列中采用 softmax。 然后,我们使用模型类创建一个对象,并使用`print(model)`打印该类的详细信息。
# 更多
......@@ -325,7 +325,7 @@ TorchVision 的`datasets`模块附带了许多受欢迎的数据集; 如果机
在本秘籍中,我们将学习优化器。 在先前的秘籍“定义损失函数”中,我们谈到了误差和误差函数,并了解到,为了获得一个好的模型,我们需要最小化计算出的误差。 **反向传播**是神经网络从误差中学习的一种方法。 误差用于修改权重,以使误差最小化。 优化函数负责修改权重以减少误差。 优化函数计算相对于权重的误差的偏导数。 导数显示正斜率的方向,因此我们需要反转梯度的方向。 **优化器**函数将模型参数和损失函数结合在一起,以迭代方式修改模型参数以减少模型误差。 可以考虑将优化器摆在模型权重的基础上,根据模型与实际输出的预测差异来获得最佳模型,而损失函数则通过指示优化器是对还是错来充当指导。
学习率是优化器的超参数,它控制权重的更新量。 学习速度确保了权重不会大量更新,从而使算法根本无法收敛,并且误差越来越大。 然而,与此同时,权重的更新不应太低,以至于永远需要花费成本函数/误差函数的最小值。
学习率是优化器的超参数,它控制权重的更新量。 学习速度确保了权重不会大量更新,从而使算法根本无法收敛,并且误差越来越大。 然而,与此同时,权重的更新不应太低,以至于永远需要花费成本函数/误差函数的最小值。
下面显示了学习率的影响:
......@@ -546,7 +546,7 @@ Training loss: 0.2596
# 工作原理
在此秘籍中,我们更改了`__init__()`方法,以 0.25 的丢失率添加了该丢失层,这意味着将应用该丢失的层中 25% 的神经元将被随机关闭。 然后,我们编辑`forward`函数,将其应用于其中具有 256 个单位的第一个隐藏层,然后对第二个层(具有 128 个单位)应用该滤除。 在完成激活函数之后,我们在两个层中都应用了激活。 我们必须牢记,必须仅在隐藏层上应用丢弃,以防止我们丢失输入数据和丢失输出。
在此秘籍中,我们更改了`__init__()`方法,以 0.25 的丢失率添加了该丢失层,这意味着将应用该丢失的层中 25% 的神经元将被随机关闭。 然后,我们编辑`forward`函数,将其应用于其中具有 256 个单元的第一个隐藏层,然后对第二个层(具有 128 个单元)应用该滤除。 在完成激活函数之后,我们在两个层中都应用了激活。 我们必须牢记,必须仅在隐藏层上应用丢弃,以防止我们丢失输入数据和丢失输出。
# 更多
......
......@@ -863,7 +863,7 @@ valid_loss = valid_loss/len(valid_loader.sampler)
在此秘籍中,我们找到并训练了我们的模型。 为此,我们进行了导入,首先要确定模型并将模型分配给我们在计算机上拥有的适当设备。 我们使用`model.to(device)`方法移动模型,这比使用`model.cuda()``model.cpu()`更为优雅。
然后,我们定义了损失函数,也称为`criterion`。 由于这是一个分类问题,因此我们使用了交叉熵损失。 然后,我们选择 SGD 优化器在反向传播时更新模型权重,学习率为 0.01,并使用`model.parameters()`传入模型参数。 然后,我们将模型运行了 30 个周期,尽管我们可以选择任何合理的数目来执行此操作。 在循环中,我们将训练和验证损失重置为 0,并将模型设置为训练模式,然后遍历训练数据集中的每个批量。 我们首先将批量移至设备,这样,如果我们的 GPU 内存有限,则并非所有数据都不会完全加载到 GPU 内存中。 然后,我们将输入张量传递到模型中,并获取输出,并将其传递到损失函数中,以评估预测标签和真实标签之间的差异。
然后,我们定义了损失函数,也称为`criterion`。 由于这是一个分类问题,因此我们使用了交叉熵损失。 然后,我们选择 SGD 优化器在反向传播时更新模型权重,学习率为 0.01,并使用`model.parameters()`传入模型参数。 然后,我们将模型运行了 30 个周期,尽管我们可以选择任何合理的数目来执行此操作。 在循环中,我们将训练和验证损失重置为 0,并将模型设置为训练模式,然后遍历训练数据集中的每个批量。 我们首先将批量移至设备,这样,如果我们的 GPU 内存有限,则并非所有数据都不会完全加载到 GPU 内存中。 然后,我们将输入张量传递到模型中,并获取输出,并将其传递到损失函数中,以评估预测标签和真实标签之间的差异。
此后,我们使用`loss.backward()`进行了反向传播,并使用`optimizer.step()`步骤更新了模型权重。 然后,我们使用总历时损失来汇总批量中的损失。 然后,我们使用`model.eval()`将模型转换为评估模型,因为该模型的表现需要在验证集上进行评估,并且该模型在此阶段中不会学习,因此我们也需要关闭退出项。 遍历验证批量,我们获得了模型输出,并在整个时期累积了验证批量之间的损失。 此后,我们格式化了模型表现,以查看每个时期模型的变化。 我们注意到,模型训练和验证损失随时间的推移而减少,这表明模型正在学习。
......
......@@ -405,7 +405,7 @@ tensorboard --logdir=log_dir/ --port 6006
# 训练模型和解冻层
在本秘籍中,我们将为数据集的预定义迭代次数完成模型训练。 我们将在模型训练期间保存最佳模型。 一旦针对给定的时期数训练了模型,我们将使用最佳模型的权重加载模型。 然后,我们将解冻模型的先前冻结的 ResNet 层,并训练模型以较低的学习率微调权重。
在本秘籍中,我们将为数据集的预定义迭代次数完成模型训练。 我们将在模型训练期间保存最佳模型。 一旦针对给定的时期数训练了模型,我们将使用最佳模型的权重加载模型。 然后,我们将解冻模型的先前冻结的 ResNet 层,并训练模型以较低的学习率微调权重。
# 操作步骤
......
......@@ -79,7 +79,7 @@ GAN 中的两个模型称为生成器和判别器,其中生成器负责创建
super().__init__()
```
4.然后,我们将定义生成器的单
4.然后,我们将定义生成器的单
```py
self.fc = nn.Linear(z_dim, 256 * 7 * 7)
......@@ -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 的对称性在这里可能是一个优势,因为网络应该以对称方式处理较深的颜色和较浅的颜色。
......@@ -156,7 +156,7 @@ def forward(self, input):
super().__init__()
```
3.接下来,我们定义鉴别单
3.接下来,我们定义鉴别单
```py
self.disc = nn.Sequential(
......
......@@ -375,7 +375,7 @@ def forward(self,
在本秘籍中,我们使用了跟踪方法来创建 TorchScript。 我们定义了一个简单的模块`MyCell`转换为`Torchscript`,并创建了两个采样张量`x``h`传递给网络模块的正向方法。 然后,我们使用`jit.trace`跟踪 Python 代码并创建 TorchScript。
我们使用跟踪将`PyTorch`模型转换为 TorchScript,并传递了我们的模型实例。 `jit.trace`通过在模块的前向方法内跟踪模型评估中的操作来创建`torch.jit.ScriptModule`对象。 `jit.trace`运行网络模块,记录运行该模块时发生的操作,并创建`torch.jit.ScriptModule`对象的实例。 TorchScript 以中间表示形式(在深度学习中称为图形)记录其定义。 然后,我们检查了具有`.graph`属性的图形,并使用`.code`生成了更具可读性的版本,这是代码的 Python 语法解释。
我们使用跟踪将`PyTorch`模型转换为 TorchScript,并传递了我们的模型实例。 `jit.trace`通过在模块的前向方法内跟踪模型评估中的操作来创建`torch.jit.ScriptModule`对象。 `jit.trace`运行网络模块,记录运行该模块时发生的操作,并创建`torch.jit.ScriptModule`对象的实例。 TorchScript 以中间表示形式(在深度学习中称为图)记录其定义。 然后,我们检查了具有`.graph`属性的图,并使用`.code`生成了更具可读性的版本,这是代码的 Python 语法解释。
然后,我们探索了使用脚本编译器创建 TorchScript 的下一种方法。 为此,我们使用以下代码定义了具有控制流的子模块:
......@@ -575,9 +575,9 @@ CNN(
然后,我们使用了一个随机变量,其形状与输入张量的形状相同,在本例中为三通道`32 x 32`像素图像。 我们将此随机输入传递到模型中并获得输出。 然后,我们使用输出将其与模型的 ONNX 版本中的模型进行比较。
在 PyTorch 中使用跟踪或脚本导出模型。 在本秘籍中,我们在`torch.onnx.export()`的帮助下使用了跟踪。 跟踪跟踪用于获取输出的操作。 这就是为什么我们提供`x`的原因-因此可以进行跟踪。 `x`必须具有正确的类型和大小。 输入尺寸在导出的 ONNX 图中固定为所有输入尺寸,我们必须指定所有动态轴。 在此秘籍中,我们使用第一维的输入导出模型,将批量大小设置为 1,并在`torch.onnx.export()``dynamic_axes`参数中将第一维指定为动态。
在 PyTorch 中使用跟踪或脚本导出模型。 在本秘籍中,我们在`torch.onnx.export()`的帮助下使用了跟踪。 跟踪跟踪用于获取输出的操作。 这就是为什么我们提供`x`的原因-因此可以进行跟踪。 `x`必须具有正确的类型和大小。 输入尺寸在导出的 ONNX 图中固定为所有输入尺寸,我们必须指定所有动态轴。 在此秘籍中,我们使用第一维的输入导出模型,将批量大小设置为 1,并在`torch.onnx.export()``dynamic_axes`参数中将第一维指定为动态。
第一个参数是 PyTorch 模型,第二个参数是随机变量。 然后,我们有了`onnx`格式的路径; `export_params`用于将训练后的参数权重存储在模型文件中; `opset_version``onnx`导出版本; `do_constant_folding`用于执行常量折叠以进行优化; `input_names`是模型的输入名称,`output_names`是模型的输出名称。 然后,我们加载了导出的`onnx`模型,并检查了模型结构并使用`onnx.checker.check_model(onnx_model)`验证了架构。 通过检查模型版本,图形的结构,节点及其输入和输出来验证 ONNX 图形
第一个参数是 PyTorch 模型,第二个参数是随机变量。 然后,我们有了`onnx`格式的路径; `export_params`用于将训练后的参数权重存储在模型文件中; `opset_version``onnx`导出版本; `do_constant_folding`用于执行常量折叠以进行优化; `input_names`是模型的输入名称,`output_names`是模型的输出名称。 然后,我们加载了导出的`onnx`模型,并检查了模型结构并使用`onnx.checker.check_model(onnx_model)`验证了架构。 通过检查模型版本,图的结构,节点及其输入和输出来验证 ONNX 图
然后,我们将模型加载到`onnx`运行时中,并为模型创建一个推理会话。 创建会话后,我们使用`run()` API 评估了模型,其中第一个参数是输出名称的列表,第二个参数是输入字典。 此调用的输出是计算 ONNX 运行时之后模型输出的列表。 最后,我们使用`numpy.testing.assert_allclose()`比较了 PyTorch 模型和`onnx`模型的输出值,如果两个对象不等于期望的公差,则会提高`AssertionError`
......
......@@ -20,7 +20,7 @@ Python 在深度学习社区中的广泛接受使一些研究人员和开发人
深度学习的前端开发人员发现符号图的概念很困难。 不幸的是,几乎所有的深度学习框架都是在此基础上构建的。 实际上,一些开发人员小组试图通过动态图来改变这种方法。 哈佛智能概率系统集团的 Autograd 是第一个这样做的流行框架。 然后,Twitter 上的 Torch 社区采纳了这个想法,并实现了 torch-autograd。
接下来,来自**卡内基梅隆大学****CMU**)的研究小组提出了 DyNet,然后 Chainer 提出了动态图的功能和可解释的开发环境。
接下来,来自**卡内基梅隆大学****CMU**)的研究小组提出了 DyNet,然后 Chainer 提出了动态图的功能和可解释的开发环境。
所有这些事件都是启动惊人的框架 PyTorch 的巨大灵感,事实上,PyTorch 最初是 Chainer 的分支。 它最初是由 Torch 的核心开发人员 Soumith Chintala 领导的 Adam Paszke 的实习项目开始的。 然后,PyTorch 聘请了另外两名核心开发人员以及来自不同公司和大学的约 100 位 Alpha 测试人员。
......@@ -34,7 +34,7 @@ Python 在深度学习社区中的广泛接受使一些研究人员和开发人
基于磁带的**自动微分**系统使 PyTorch 具有**动态图**功能。 这是 PyTorch 与其他流行的符号图框架之间的主要区别之一。 基于磁带的 Autograd 也支持 Chainer,Autograd 和 Torch-Autograd 的反向传播算法。 具有动态图功能,您的图将在 Python 解释器到达相应行时创建。 与 TensorFlow 的*定义并运行*方法不同,这称为*通过运行定义*
基于磁带的 Autograd 使用反向模式自动微分,在前进过程中,图将每个操作保存到磁带中,然后在磁带中向后移动以进行反向传播。 动态图和 Python 优先方法使**易于调试**,您可以在其中使用常用的 Python 调试器,例如 Pdb 或基于编辑器的调试器。
基于磁带的 Autograd 使用反向模式自动微分,在前进过程中,图将每个操作保存到磁带中,然后在磁带中向后移动以进行反向传播。 动态图和 Python 优先方法使**易于调试**,您可以在其中使用常用的 Python 调试器,例如 Pdb 或基于编辑器的调试器。
PyTorch 核心社区不仅为 Torch 的 C 二进制文件构建了 Python 包装器,还优化了内核并对其进行了改进。 PyTorch 根据输入数据智能地选择要为定义的每个操作运行的算法。
......@@ -58,9 +58,9 @@ PyTorch 核心社区不仅为 Torch 的 C 二进制文件构建了 Python 包装
PyTorch 在研究界获得了广泛的接受,因为大多数人已经在使用 Torch,并且可能对 TensorFlow 之类的框架在没有提供太多灵活性的情况下的发展感到沮丧。 PyTorch 的动态性质对许多人来说是一个好处,并帮助他们在早期阶段接受 PyTorch。
PyTorch 允许用户定义 Python 在向前传递中允许他们执行的任何操作。 向后遍历自动找到遍历图直到根节点的路径,并在向后遍历时计算梯度。 尽管这是一个革命性的想法,但是产品开发社区并未接受 PyTorch,就像他们不能接受遵循类似实现的其他框架一样。 但是,随着时间的流逝,越来越多的人开始迁移到 PyTorch。 Kaggle 目睹了所有顶级玩家都使用 PyTorch 进行的比赛,并且如前所述,大学开始在 PyTorch 中开设课程。 这有助于学生避免像使用基于符号图的框架时那样学习新的图语言。
PyTorch 允许用户定义 Python 在向前传递中允许他们执行的任何操作。 向后遍历自动找到遍历图直到根节点的路径,并在向后遍历时计算梯度。 尽管这是一个革命性的想法,但是产品开发社区并未接受 PyTorch,就像他们不能接受遵循类似实现的其他框架一样。 但是,随着时间的流逝,越来越多的人开始迁移到 PyTorch。 Kaggle 目睹了所有顶级玩家都使用 PyTorch 进行的比赛,并且如前所述,大学开始在 PyTorch 中开设课程。 这有助于学生避免像使用基于符号图的框架时那样学习新的图语言。
在 Caffe2 发布之后,自社区宣布 PyTorch 模型向 Caffe2 的迁移策略以来,甚至产品开发人员也开始尝试 PyTorch。 Caffe2 是一个静态图形框架,即使在移动电话中也可以运行您的模型,因此使用 PyTorch 进行原型设计是一种双赢的方法。 构建网络时,您可以获得 PyTorch 的灵活性,并且可以将其传输到 Caffe2 并在任何生产环境中使用。 但是,在 1.0 版本说明中,PyTorch 团队从让人们学习两个框架(一个用于生产,一个用于研究)到学习在原型阶段具有动态图形功能并且可以突然转换为一个框架的巨大跃进。 需要速度和效率的静态优化图。 PyTorch 团队将 Caffe2 的后端与 PyTorch 的 Aten 后端合并在一起,这使用户可以决定是要运行优化程度较低但高度灵活的图形,还是运行优化程度较不灵活的图形而无需重写代码库。
在 Caffe2 发布之后,自社区宣布 PyTorch 模型向 Caffe2 的迁移策略以来,甚至产品开发人员也开始尝试 PyTorch。 Caffe2 是一个静态图框架,即使在移动电话中也可以运行您的模型,因此使用 PyTorch 进行原型设计是一种双赢的方法。 构建网络时,您可以获得 PyTorch 的灵活性,并且可以将其传输到 Caffe2 并在任何生产环境中使用。 但是,在 1.0 版本说明中,PyTorch 团队从让人们学习两个框架(一个用于生产,一个用于研究)到学习在原型阶段具有动态图功能并且可以突然转换为一个框架的巨大跃进。 需要速度和效率的静态优化图。 PyTorch 团队将 Caffe2 的后端与 PyTorch 的 Aten 后端合并在一起,这使用户可以决定是要运行优化程度较低但高度灵活的图,还是运行优化程度较不灵活的图而无需重写代码库。
ONNX 和 DLPack 是 AI 社区看到的下两个“大事情”。 微软和 Facebook 共同宣布了 **开放神经网络交换****ONNX**)协议,该协议旨在帮助开发人员将任何模型从任何框架迁移到任何其他框架。 ONNX 与 PyTorch,Caffe2,TensorFlow,MXNet 和 CNTK 兼容,并且社区正在构建/改善对几乎所有流行框架的支持。
......@@ -68,9 +68,9 @@ ONNX 内置在 PyTorch 的核心中,因此将模型迁移到 ONNX 表单不需
## 使用计算图
通过的演变,人类发现对神经网络进行图绘制可以使我们将复杂性降低到最低限度。 计算图通过操作描述了网络中的数据流。
通过的演变,人类发现对神经网络进行图绘制可以使我们将复杂性降低到最低限度。 计算图通过操作描述了网络中的数据流。
由一组节点和连接它们的边组成的图是一种已有数十年历史的数据结构,仍然在几种不同的实现方式中大量使用,并且该数据结构可能一直有效,直到人类不复存在。 在计算图中,节点表示张量,边表示它们之间的关系。
由一组节点和连接它们的边组成的图是一种已有数十年历史的数据结构,仍然在几种不同的实现方式中大量使用,并且该数据结构可能一直有效,直到人类不复存在。 在计算图中,节点表示张量,边表示它们之间的关系。
计算图可帮助我们解决数学问题并使大型网络变得直观。 神经网络,无论它们有多复杂或多大,都是一组数学运算。 解决方程的明显方法是将方程分成较小的单元,并将一个输出传递给另一个,依此类推。 图方法背后的想法是相同的。 您将网络内部的操作视为节点,并将它们映射到一个图,图中节点之间的关系表示从一个操作到另一个操作的过渡。
......@@ -84,13 +84,13 @@ ONNX 内置在 PyTorch 的核心中,因此将模型迁移到 ONNX 表单不需
图 1.2:等式的图形表示
但是,当您将映射到图时,一切都变得清晰起来。 您可以可视化并了解正在发生的事情,并轻松编写代码,因为流程就在您的眼前。
但是,当您将映射到图时,一切都变得清晰起来。 您可以可视化并了解正在发生的事情,并轻松编写代码,因为流程就在您的眼前。
所有深度学习框架都建立在自动微分和计算图的基础上,但是有两种固有的实现方法–静态图和动态图。
### 使用静态图
处理神经网络架构的传统方法是使用静态图。 在对给出的数据进行任何处理之前,该程序将构建图的正向和反向传递。 不同的开发小组尝试了不​​同的方法。 有些人先构建正向传播,然后将相同的图实例用于正向传播和后向传递。 另一种方法是先构建前向静态图,然后创建后向图并将其附加到前向图的末尾,以便可以将整个前向-后向传递作为单个图执行来执行。 按时间顺序排列节点。
处理神经网络架构的传统方法是使用静态图。 在对给出的数据进行任何处理之前,该程序将构建图的正向和反向传递。 不同的开发小组尝试了不​​同的方法。 有些人先构建正向传播,然后将相同的图实例用于正向传播和后向传递。 另一种方法是先构建前向静态图,然后创建后向图并将其附加到前向图的末尾,以便可以将整个前向-后向传递作为单个图执行来执行。 按时间顺序排列节点。
![Using static graphs](img/B09475_01_03.jpg)
......@@ -102,9 +102,9 @@ ONNX 内置在 PyTorch 的核心中,因此将模型迁移到 ONNX 表单不需
图 1.5:静态图:正向和反向传递的不同图
静态图具有相对于其他方法的某些固有优势。 由于要限制程序的动态变化,因此程序可以在执行图时做出与内存优化和并行执行有关的假设。 内存优化是框架开发人员在整个开发过程中都会担心的关键方面,原因是优化内存的范围非常庞大,并且伴随着这些优化的微妙之处。 Apache MXNet 开发人员已经写了一个很棒的博客[3],详细讨论了这个问题。
静态图具有相对于其他方法的某些固有优势。 由于要限制程序的动态变化,因此程序可以在执行图时做出与内存优化和并行执行有关的假设。 内存优化是框架开发人员在整个开发过程中都会担心的关键方面,原因是优化内存的范围非常庞大,并且伴随着这些优化的微妙之处。 Apache MXNet 开发人员已经写了一个很棒的博客[3],详细讨论了这个问题。
TensorFlow 静态图 API 中用于预测 XOR 输出的神经网络如下所示。 这是静态图如何执行的典型示例。 最初,我们声明所有输入的占位符,然后构建图。 如果仔细看,我们在图定义中的任何地方都不会将数据传递给它。 输入变量实际上是占位符,期望在将来的某个时间获取数据。 尽管图定义看起来像我们在对数据执行数学操作,但实际上是在定义流程,这就是 TensorFlow 使用内部引擎构建优化的图实现的时候:
TensorFlow 静态图 API 中用于预测 XOR 输出的神经网络如下所示。 这是静态图如何执行的典型示例。 最初,我们声明所有输入的占位符,然后构建图。 如果仔细看,我们在图定义中的任何地方都不会将数据传递给它。 输入变量实际上是占位符,期望在将来的某个时间获取数据。 尽管图定义看起来像我们在对数据执行数学操作,但实际上是在定义流程,这就是 TensorFlow 使用内部引擎构建优化的图实现的时候:
```py
x = tf.placeholder(tf.float32, shape=[None, 2], name='x-input')
......@@ -120,7 +120,7 @@ train_step = tf.train.GradientDescentOptimizer(lr).minimize(cost)
prediction = tf.argmax(tf.nn.softmax(hyp), 1)
```
解释器读取完图定义后,我们就开始遍历数据:
解释器读取完图定义后,我们就开始遍历数据:
```py
with tf.Session() as sess:
......@@ -129,7 +129,7 @@ with tf.Session() as sess:
sess.run(train_step, feed_dict={x_: XOR_X, y_: XOR_Y})
```
接下来我们开始 TensorFlow 会话。 这是与预先构建的图形进行交互的唯一方法。 在会话内部,您可以遍历数据,并使用`session.run`方法将数据传递到图形。 因此,输入的大小应与图中定义的大小相同。
接下来我们开始 TensorFlow 会话。 这是与预先构建的图进行交互的唯一方法。 在会话内部,您可以遍历数据,并使用`session.run`方法将数据传递到图。 因此,输入的大小应与图中定义的大小相同。
如果您忘记了什么是 XOR,则下表应为您提供足够的信息以从内存中重新收集它:
......@@ -143,9 +143,9 @@ with tf.Session() as sess:
### 使用动态图
势在必行的编程风格始终拥有较大的用户群,因为程序流程对于任何开发人员都是直观的。 动态能力是命令式图形构建的良好副作用。 与静态图不同,动态图架构不会在数据传递之前构建图。 程序将等待数据到达并在遍历数据时构建图形。 结果,每次数据迭代都会构建一个新的图实例,并在完成反向传播后销毁它。 由于图形是为每次迭代构建的,因此它不依赖于数据大小,长度或结构。 自然语言处理是需要这种方法的领域之一。
势在必行的编程风格始终拥有较大的用户群,因为程序流程对于任何开发人员都是直观的。 动态能力是命令式图构建的良好副作用。 与静态图不同,动态图架构不会在数据传递之前构建图。 程序将等待数据到达并在遍历数据时构建图。 结果,每次数据迭代都会构建一个新的图实例,并在完成反向传播后销毁它。 由于图为每次迭代构建的,因此它不依赖于数据大小,长度或结构。 自然语言处理是需要这种方法的领域之一。
例如,如果您试图对成千上万的句子进行情感分析,则需要使用静态图形来破解并采取变通办法。 在普通的**循环神经网络****RNN**)模型中,每个单词都经过一个 RNN 单元,该单元生成输出和隐藏状态。 该隐藏状态将提供给下一个 RNN,后者处理句子中的下一个单词。 由于您在构建静态图形时做了一个固定长度的插槽,因此您需要增加短句并减少长句。
例如,如果您试图对成千上万的句子进行情感分析,则需要使用静态图来破解并采取变通办法。 在普通的**循环神经网络****RNN**)模型中,每个单词都经过一个 RNN 单元,该单元生成输出和隐藏状态。 该隐藏状态将提供给下一个 RNN,后者处理句子中的下一个单词。 由于您在构建静态图时做了一个固定长度的插槽,因此您需要增加短句并减少长句。
![Using dynamic graphs](img/B09475_01_06.jpg)
......@@ -174,9 +174,9 @@ for epoch in range(epochs):
cost.backward()
```
在 PyTorch 代码中,输入变量定义未创建占位符。 而是将变量对象包装到您的输入上。 图形定义不会执行一次; 相反,它在循环内,并且每次迭代都在构建图形。 您在每个图实例之间共享的唯一信息是您要优化的权重矩阵。
在 PyTorch 代码中,输入变量定义未创建占位符。 而是将变量对象包装到您的输入上。 图定义不会执行一次; 相反,它在循环内,并且每次迭代都在构建图。 您在每个图实例之间共享的唯一信息是您要优化的权重矩阵。
在这种方法中,如果您在遍历数据时改变了数据大小或形状,则在图形中运行新形状的数据绝对好,因为新创建的图形可以接受新形状。 可能性不止于此。 如果要动态更改图形的行为,也可以这样做。 在第 5 章,“序列数据处理”中的循环神经网络会话中给出的示例均基于此思想。
在这种方法中,如果您在遍历数据时改变了数据大小或形状,则在图中运行新形状的数据绝对好,因为新创建的图可以接受新形状。 可能性不止于此。 如果要动态更改图的行为,也可以这样做。 在第 5 章,“序列数据处理”中的循环神经网络会话中给出的示例均基于此思想。
## 探索深度学习
......
......@@ -87,7 +87,7 @@ for i in epoch:
network_execution_over_whole_dataset()
```
**学习率**决定了我们希望我们的网络从每次迭代的误差中获取反馈的速度。 它通过忘记网络从所有先前迭代中学到的知识来决定从当前迭代中学到的知识。 将学习率保持为 1 可使网络考虑完全误差,并根据完全误差调整权重。 学习率为零意味着向网络传递的信息为零。 学习率将是神经网络中梯度更新方程式中的选择因子。 对于每个神经元,我们运行以下公式来更新神经元的权重:
**学习率**决定了我们希望我们的网络从每次迭代的误差中获取反馈的速度。 它通过忘记网络从所有先前迭代中学到的知识来决定从当前迭代中学到的知识。 将学习率保持为 1 可使网络考虑完全误差,并根据完全误差调整权重。 学习率为零意味着向网络传递的信息为零。 学习率将是神经网络中梯度更新方程式中的选择因子。 对于每个神经元,我们运行以下公式来更新神经元的权重:
```py
weight -= lr * loss
......@@ -166,7 +166,7 @@ tensor([1.])
#### 张量的 Autograd 属性
当成为图的一部分时,张量需要存储 Autograd 自动区分所需的信息。 张量充当计算图中的一个节点,并通过函数式模块实例连接到其他节点。 张量实例主要具有支持 Autograd 的三个属性:`.grad``.data``grad_fn()`(注意字母大小写:`Function`代表 PyTorch `Function`模块,而`function`代表 Python 函数)。
当成为图的一部分时,张量需要存储 Autograd 自动区分所需的信息。 张量充当计算图中的一个节点,并通过函数式模块实例连接到其他节点。 张量实例主要具有支持 Autograd 的三个属性:`.grad``.data``grad_fn()`(注意字母大小写:`Function`代表 PyTorch `Function`模块,而`function`代表 Python 函数)。
`.grad`属性在任何时间点存储梯度,所有向后调用将当前梯度累积到`.grad`属性。 `.data`属性可访问其中包含数据的裸张量对象。
......@@ -187,7 +187,7 @@ print(w1.grad, w1.grad_fn, w1)
我们的输入`x`和第一层权重矩阵`w1`目前没有`grad``grad_fn`。 我们将很快看到这些属性的更新方式和时间。 `x``.data`属性为`900 x 10`形状,因为我们传递了 900 个数据点,每个数据点的大小均为 10(二进制编码数)。 现在,您可以准备进行数据迭代了。
我们已经准备好输入,权重和偏差,并等待数据输入。如前所述,PyTorch 是一个基于动态图的网络,该网络在每次迭代时构建计算图。 因此,当我们遍历数据时,我们实际上是在动态构建图,并在到达最后一个或根节点时对其进行反向传播。 这是显示此代码段:
我们已经准备好输入,权重和偏差,并等待数据输入。如前所述,PyTorch 是一个基于动态图的网络,该网络在每次迭代时构建计算图。 因此,当我们遍历数据时,我们实际上是在动态构建图,并在到达最后一个或根节点时对其进行反向传播。 这是显示此代码段:
```py
for epoch in range(epochs):
......@@ -236,7 +236,7 @@ for epoch in range(epochs):
图 2.6:网络架构
第一层由批量输入矩阵,权重和偏差之间的矩阵乘法和加法组成。 此时,`a2`张量应具有一个`grad_fn`,这应该是矩阵加法的后向操作。 但是,由于我们还没有进行反向传递,因此`.grad`应该返回`None``.data`,并且将一如既往地返回张量,以及矩阵乘法和偏差加法的结果。 神经元活动由 Sigmoid 激活函数定义,它以`h2`(代表第二层中的隐藏单)的输出形式提供给我们。 第二层采用相同的结构:矩阵乘法,偏差加法和 Sigmoid。 最后得到`hyp`,它具有预期的结果:
第一层由批量输入矩阵,权重和偏差之间的矩阵乘法和加法组成。 此时,`a2`张量应具有一个`grad_fn`,这应该是矩阵加法的后向操作。 但是,由于我们还没有进行反向传递,因此`.grad`应该返回`None``.data`,并且将一如既往地返回张量,以及矩阵乘法和偏差加法的结果。 神经元活动由 Sigmoid 激活函数定义,它以`h2`(代表第二层中的隐藏单)的输出形式提供给我们。 第二层采用相同的结构:矩阵乘法,偏差加法和 Sigmoid。 最后得到`hyp`,它具有预期的结果:
```py
print(a2.grad, a2.grad_fn, a2)
......@@ -304,7 +304,7 @@ SGD 的主要缺点是效率低下。 例如,考虑我们的 *FizzBu​​zz*
我们已经到达了模型构建旅程的最后一部分。 到目前为止,所有操作都很直观,简单,但是最后一部分有点令人困惑。 `zero_grad`做什么? 还记得关于重量`w1.grad`的第一份印刷声明吗? 它是空的,现在具有当前反向传递的梯度。 因此,我们需要在下一次反向传播之前清空梯度,因为梯度会累积而不是被重写。 参数更新后,我们在每个迭代的每个张量上调用`zero_grad()`,然后继续进行下一个迭代。
`.grad_fn`通过连接函数和张量将图形保持在一起。 在`Function`模块中定义了对张量的每种可能的操作。 所有张量的`.grad_fn`始终指向函数对象,除非用户创建了它。 PyTorch 允许您使用`grad_fn`向后浏览图形。 从图形中的任何节点,可以通过在`grad_fn`的返回值上调用`next_functions`来到达任何父节点。
`.grad_fn`通过连接函数和张量将图保持在一起。 在`Function`模块中定义了对张量的每种可能的操作。 所有张量的`.grad_fn`始终指向函数对象,除非用户创建了它。 PyTorch 允许您使用`grad_fn`向后浏览图。 从图中的任何节点,可以通过在`grad_fn`的返回值上调用`next_functions`来到达任何父节点。
```py
# traversing the graph using .grad_fn
......
......@@ -384,7 +384,7 @@ transform = transforms.Compose(
PyTorch 的 Python 优先方法阻止核心团队在的第一年建立一个单独的探查器,但是当模块开始转向 C/C++ 内核时,就很明显需要在 Python 的 cProfiler 上安装一个独立的探查器,这就是 `autograd.profiler`故事的开始。
本节将提供更多的表和统计信息,而不是分步指导,因为 PyTorch 已经使概要分析尽可能简单。 对于概要分析,我们将使用在第二章中开发的相同的 *FizzBu​​zz* 模型。 尽管`autograd.profiler`可以分析图中的所有操作,但是在此示例中,仅分析了主网络的正向传播,而没有损失函数和后向通过。
本节将提供更多的表和统计信息,而不是分步指导,因为 PyTorch 已经使概要分析尽可能简单。 对于概要分析,我们将使用在第二章中开发的相同的 *FizzBu​​zz* 模型。 尽管`autograd.profiler`可以分析图中的所有操作,但是在此示例中,仅分析了主网络的正向传播,而没有损失函数和后向通过。
```py
with torch.autograd.profiler.profile() as prof:
......
......@@ -280,7 +280,7 @@ trainloader, testloader = get_data()
7. 使用优化程序进行梯度更新。
8. 如果需要,可以保存运行损失。
在保存运行损失时要小心,因为 PyTorch 会在变量进行反向传播之前保存整个图形。 增量保存图形只是图形中的另一种操作,其中每次迭代中的图形都使用求和运算将先前的图形附加到图形上,最终导致内存不足。 始终从图形中取出值并将其保存为没有图形历史记录的普通张量。
在保存运行损失时要小心,因为 PyTorch 会在变量进行反向传播之前保存整个图。 增量保存图只是图中的另一种操作,其中每次迭代中的图都使用求和运算将先前的图附加到图上,最终导致内存不足。 始终从图中取出值并将其保存为没有图历史记录的普通张量。
```py
inputs, labels = data
......
......@@ -8,7 +8,7 @@
**循环神经网络****RNN**)是序列数据处理的实际实现。 顾名思义,RNN 重新遍历上一次运行中保存的信息的数据,并试图像人类一样找到序列的含义。
尽管原始 RNN(在输入中为每个单元展开一个简单的 RNN 单元)是一个革命性的想法,但未能提供可用于生产的结果。 主要障碍是长期依赖问题。 当输入序列的长度增加时,网络到达最后一个单元时将无法从初始单(单词,如果是自然语言)中记住信息。 我们将在接下来的部分中看到 RNN 单元包含的内容以及如何将其展开。
尽管原始 RNN(在输入中为每个单元展开一个简单的 RNN 单元)是一个革命性的想法,但未能提供可用于生产的结果。 主要障碍是长期依赖问题。 当输入序列的长度增加时,网络到达最后一个单元时将无法从初始单(单词,如果是自然语言)中记住信息。 我们将在接下来的部分中看到 RNN 单元包含的内容以及如何将其展开。
几次迭代和多年的研究得出了 RNN 架构设计的几种不同方法。 最新的模型现在使用**长短期记忆****LSTM**)实现或**门控循环单元****GRU**)。 这两种实现都将 RNN 单元内的门用于不同目的,例如遗忘门,它使网络忘记不必要的信息。 这些架构具有原始 RNN 所存在的长期依赖性问题,因此使用门不仅要忘记不必要的信息,而且要记住在长距离移动到最后一个单元时所必需的信息。
......
......@@ -270,7 +270,7 @@ WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基
来源: 《WaveNet:原始音频的生成模型》,Aaron van den Oord 等
“图 6.12”中提供的 WaveNet 的结构图显示了所有这些小组件以及它们如何连接在一起。 跳跃连接之后的部分在程序中称为密集层,尽管它不是上一章介绍的密集层。 通常,密集层表示全连接层,以将非线性引入网络并获得所有数据的概览。 但是 WaveNet 的作者发现,正常的致密层可以由一串 ReLU 代替,并且`1x1`卷积可以通过最后的 softmax 层实现更高的精度,该层可以展开为 256 个单(巨大扇出的 8 位`µ`律量化) 音频)。
“图 6.12”中提供的 WaveNet 的结构图显示了所有这些小组件以及它们如何连接在一起。 跳跃连接之后的部分在程序中称为密集层,尽管它不是上一章介绍的密集层。 通常,密集层表示全连接层,以将非线性引入网络并获得所有数据的概览。 但是 WaveNet 的作者发现,正常的致密层可以由一串 ReLU 代替,并且`1x1`卷积可以通过最后的 softmax 层实现更高的精度,该层可以展开为 256 个单(巨大扇出的 8 位`µ`律量化) 音频)。
```py
class WaveNetModule(torch.nn.Module):
......@@ -292,7 +292,7 @@ class WaveNetModule(torch.nn.Module):
return output.contiguous()
```
前面的代码块中给出的程序是主要的父 WaveNet 模块,该模块使用所有子组件来创建图`init`定义了三个主要成分,其中是第一个普通卷积,然后是`res_stack`(它是由所有膨胀卷积和 Sigmoid 正切门组成的残差连接块)。 然后,最后的`convdensnet``1x1`卷积的顶部进行。 `forward`引入一个求和节点,依次执行这些模块。 然后,将`convdensnet`创建的输出通过`contiguous()`移动到存储器的单个块。 这是其余网络所必需的。
前面的代码块中给出的程序是主要的父 WaveNet 模块,该模块使用所有子组件来创建图。 `init`定义了三个主要成分,其中是第一个普通卷积,然后是`res_stack`(它是由所有膨胀卷积和 Sigmoid 正切门组成的残差连接块)。 然后,最后的`convdensnet``1x1`卷积的顶部进行。 `forward`引入一个求和节点,依次执行这些模块。 然后,将`convdensnet`创建的输出通过`contiguous()`移动到存储器的单个块。 这是其余网络所必需的。
`ResidualStack`是需要更多说明的模块,它是 WaveNet 架构的核心。 `ResidualStack``ResidualBlock`的层的栈。 WaveNet 图片中的每个小圆圈都是一个残差块。 在正常卷积之后,数据到达`ResidualBlock`,如前所述。 `ResidualBlock`从膨胀的卷积开始,并且期望得到膨胀。 因此,`ResidualBlock`决定了架构中每个小圆节点的膨胀因子。 如前所述,膨胀卷积的输出然后通过类似于我们在 PixelCNN 中看到的门的门。
......@@ -439,7 +439,7 @@ def train_discriminator(optimizer, real_data, fake_data):
return error_real + error_fake, prediction_real, prediction_fake
```
在前面的代码块中定义的函数`train_generator`接受`optimizer`对象,伪数据和实数据,然后将它们传递给判别器。 函数`fake_data_target`(在下面的代码块中提供)创建一个零张量,该张量的大小与预测大小相同,其中预测是从判别器返回的值。 判别器的训练策略是使任何真实数据被归类为真实分布的概率最大化,并使任何数据点被归类为真实分布的概率最小化。 在实践中,使用了来自判别器或生成器的结果的日志,因为这会严重损害网络的分类错误。 然后在应用`optimizer.step`函数之前将误差反向传播,该函数将通过学习率以梯度更新权重。
在前面的代码块中定义的函数`train_generator`接受`optimizer`对象,伪数据和实数据,然后将它们传递给判别器。 函数`fake_data_target`(在下面的代码块中提供)创建一个零张量,该张量的大小与预测大小相同,其中预测是从判别器返回的值。 判别器的训练策略是使任何真实数据被归类为真实分布的概率最大化,并使任何数据点被归类为真实分布的概率最小化。 在实践中,使用了来自判别器或生成器的结果的日志,因为这会严重损害网络的分类错误。 然后在应用`optimizer.step`函数之前将误差反向传播,该函数将通过学习率以梯度更新权重。
接下来给出用于获得真实数据目标和伪数据目标的函数,这与前面讨论的最小化或最大化概率的概念基本一致。 实际数据生成器返回一个张量为 1s 的张量,该张量是我们作为输入传递的形状。 在训练生成器时,我们正在尝试通过生成图像来最大程度地提高其概率,该图像看起来应该是从真实数据分布中获取的。 这意味着判别器应将 1 预测为图像来自真实分布的置信度分数。
......@@ -594,7 +594,7 @@ Generator(
PyTorch 为用户提供了进入网络并进行操作的完全灵活性。 其中一部分是将模型打印到终端上,以显示其中包含所有模块的地形排序图。
之前我们在 CycleGAN 中看到了生成器的图。 与我们探讨的第一个简单 GAN 不同,A2B 和 B2A 都具有相同的内部结构,内部具有卷积。 整个生成器都包装在以`ReflectionPad2D`开头的单个序列模块中。
之前我们在 CycleGAN 中看到了生成器的图。 与我们探讨的第一个简单 GAN 不同,A2B 和 B2A 都具有相同的内部结构,内部具有卷积。 整个生成器都包装在以`ReflectionPad2D`开头的单个序列模块中。
反射填充涉及填充输入的边界,跳过批量尺寸和通道尺寸。 填充之后是典型的卷积模块布置,即二维卷积。
......
......@@ -6,7 +6,7 @@ PyTorch 以其干净的框架而闻名,因此要获得研究所需的生产能
解决此问题的第一步是使**开放式神经网络交换****ONNX**)格式稳定,并与所有流行的框架兼容(至少与具有良好功能的框架兼容) 模块)。 ONNX 定义了深度学习图所需的基本运算符和标准数据类型。 这引导了 ONNX 进入 PyTorch 核心的道路,并且它与 ONNX 转换器一起为流行的深度学习框架(例如 CNTK,MXNet,TensorFlow 等)构建。
ONNX 很棒,并且每个人都喜欢它,但是 ONNX 的主要缺点之一是其脚本模式。 也就是说,ONNX 运行一次图形以获取有关图形的信息,然后将其转换为 ONNX 格式。 因此,ONNX 无法迁移模型中的控制流(将`for`循环用于循环神经网络(RNN)模型的不同序列长度)。
ONNX 很棒,并且每个人都喜欢它,但是 ONNX 的主要缺点之一是其脚本模式。 也就是说,ONNX 运行一次图以获取有关图的信息,然后将其转换为 ONNX 格式。 因此,ONNX 无法迁移模型中的控制流(将`for`循环用于循环神经网络(RNN)模型的不同序列长度)。
生产 PyTorch 的第二种方法是在 PyTorch 本身中构建高性能后端。 Caffe2 的核心与 PyTorch 核心合并在一起,而不是从头开始构建一个,但 Python API 保持不变。 但是,这并不能解决 Python 语言所具有的问题。
......@@ -233,7 +233,7 @@ graph(%input.1 : Float(1, 10)
表示清楚地表明了整个网络的结构。 前五行显示参数和输入张量,并为每一个标记一个名称。 例如,整个网络将输入张量定为`input.i`,它是形状为`1 x 10`的浮点张量。然后,它显示了我们第一层和第二层的权重和偏差张量。
从第六行开始,显示了图的结构。 每行的第一部分(以`%`符号开头的全冒号之前的字符)是每行的标识符,这是其他行中用来引用这些行的标识符。 例如,以`%5`作为标识符的线对`aten::t(%weight.i)`表示的第一层的权重进行转置,从而输出形状为`10 x 100`的浮点张量。
从第六行开始,显示了图的结构。 每行的第一部分(以`%`符号开头的全冒号之前的字符)是每行的标识符,这是其他行中用来引用这些行的标识符。 例如,以`%5`作为标识符的线对`aten::t(%weight.i)`表示的第一层的权重进行转置,从而输出形状为`10 x 100`的浮点张量。
![ONNX](img/B09475_08_02.jpg)
......@@ -252,9 +252,9 @@ PyTorch 具有内置的 ONNX 导出器,它可以帮助我们创建 ONNX IR,
```
在最后一行,我们调用`export`模块,并传递 PyTorch 的`net`,虚拟输入和输出文件名。 ONNX 通过跟踪图形进行转换; 也就是说,它使用我们提供的虚拟输入执行一次图形
在最后一行,我们调用`export`模块,并传递 PyTorch 的`net`,虚拟输入和输出文件名。 ONNX 通过跟踪图进行转换; 也就是说,它使用我们提供的虚拟输入执行一次图
在执行图形时,它会跟踪我们执行的 PyTorch 操作,然后将每个操作转换为 ONNX 格式。 键值参数`verbose=True`在导出时将输出写入到终端屏幕。 它为我们提供了 ONNX 中相同图形的 IR 表示:
在执行图时,它会跟踪我们执行的 PyTorch 操作,然后将每个操作转换为 ONNX 格式。 键值参数`verbose=True`在导出时将输出写入到终端屏幕。 它为我们提供了 ONNX 中相同图的 IR 表示:
```py
graph(%input.1 : Float(1, 10)
......@@ -269,7 +269,7 @@ graph(%input.1 : Float(1, 10)
}
```
它还显示了图执行所需的所有操作,但比 PyTorch 的图形表示要小。 虽然 PyTorch 向我们显示了每个操作(包括转置操作),但 ONNX 会在高级功能(例如`onnx:Gemm`)下抽象该粒度信息,前提是其他框架的`import`模块可以读取这些抽象。
它还显示了图执行所需的所有操作,但比 PyTorch 的图形表示要小。 虽然 PyTorch 向我们显示了每个操作(包括转置操作),但 ONNX 会在高级功能(例如`onnx:Gemm`)下抽象该粒度信息,前提是其他框架的`import`模块可以读取这些抽象。
PyTorch 的`export`模块将 ONNX 模型保存在`fizbuz.onnx`文件中。 可以从 ONNX 本身或其他框架中内置的 ONNX 导入程序中加载。 在这里,我们将 ONNX 模型加载到 ONNX 本身并进行模型检查。 ONNX 还具有由 Microsoft 管理的高性能运行时,这超出了本书的解释范围,但可在[这个页面](https://github.com/Microsoft/onnxruntime)上获得。
......@@ -283,7 +283,7 @@ netron -b fizbuz.onnx
```
前面的命令将使用 Fizzbuzz 网络的图形可视化来启动 Netron 服务器,如下图所示。 除了可缩放的图形外,Netron 还可以可视化其他基本信息,例如版本,生成器,图形的生成方式等等。 另外,每个节点都是可单击的,它将显示有关该特定节点的信息。 当然,这还不够复杂,无法满足可视化工具所需的所有要求,但足以让我们对整个网络有所了解。
前面的命令将使用 Fizzbuzz 网络的图可视化来启动 Netron 服务器,如下图所示。 除了可缩放的图外,Netron 还可以可视化其他基本信息,例如版本,生成器,图的生成方式等等。 另外,每个节点都是可单击的,它将显示有关该特定节点的信息。 当然,这还不够复杂,无法满足可视化工具所需的所有要求,但足以让我们对整个网络有所了解。
![ONNX](img/B09475_08_03.jpg)
......@@ -566,7 +566,7 @@ class WebsiteUser(HttpLocust):
现在的问题是:这不是我们对 ONNX 所做的吗? 也就是说,从 PyTorch 模型创建另一个 IR? 是的,过程相似,但区别在于 ONNX 使用跟踪创建了优化的 IR; 也就是说,它通过模型传递虚拟输入,并在执行模型时记录 PyTorch 操作,然后将这些操作转换为中间 IR。
这种方法有一个问题:如果模型是数据相关的,例如 RNN 中的循环,或者`if`/`else`条件是基于输入的,那么跟踪就不能真正做到这一点。 跟踪将仅发现在特定执行周期中发生的情况,而忽略其他情况。 例如,如果我们的虚拟输入是 10 个单词的句子,而我们的模型是基于循环的 RNN,则跟踪的图将对 RNN 单元的 10 次执行进行硬编码,如果句子的长度大于 10,或者较短的句子带有更少的单词,则它将中断。 考虑到这一点引入了 TorchScript。
这种方法有一个问题:如果模型是数据相关的,例如 RNN 中的循环,或者`if`/`else`条件是基于输入的,那么跟踪就不能真正做到这一点。 跟踪将仅发现在特定执行周期中发生的情况,而忽略其他情况。 例如,如果我们的虚拟输入是 10 个单词的句子,而我们的模型是基于循环的 RNN,则跟踪的图将对 RNN 单元的 10 次执行进行硬编码,如果句子的长度大于 10,或者较短的句子带有更少的单词,则它将中断。 考虑到这一点引入了 TorchScript。
TorchScript 支持此类 Python 控制流的一个子集,唯一要做的就是将现有程序转换为所有控制流都是 TorchScript 支持的控制流的阶段。 LibTorch 可以读取 TorchScript 创建的中间阶段。 在此会话中,我们将创建 TorchScript 输出并编写一个 C++ 模块以使用 LibTorch 加载它。
......
......@@ -156,7 +156,7 @@ tensor([True, True])
注意
**DAG 在 PyTorch 中是动态的**。要注意的重要一点是,图是从头开始重新创建的; 在每个`.backward()`调用之后,Autograd 开始填充新图。 这正是允许您在模型中使用控制流语句的原因。 您可以根据需要在每次迭代中更改形状,大小和操作。
**DAG 在 PyTorch 中是动态的**。要注意的重要一点是,图是从头开始重新创建的; 在每个`.backward()`调用之后,Autograd 开始填充新图。 这正是允许您在模型中使用控制流语句的原因。 您可以根据需要在每次迭代中更改形状,大小和操作。
### 从 DAG 中排除
......
......@@ -358,7 +358,7 @@ with tqdm(total=n_epoch) as pbar:
```
2 个周期后,测试集的网络准确应超过 65%,而 21 个周期后,网络应达到 85%。 让我们看一下训练集中的最后几句话,看看模型是如何做到的。
2 个周期后,测试集的网络准确应超过 65%,而 21 个周期后,网络应达到 85%。 让我们看一下训练集中的最后几句话,看看模型是如何做到的。
```py
def predict(tensor):
......
......@@ -161,7 +161,7 @@ model = TransformerModel(ntokens, emsize, nhead, nhid, nlayers, dropout).to(devi
## 运行模型
[`CrossEntropyLoss`](https://pytorch.org/docs/master/nn.html?highlight=crossentropyloss#torch.nn.CrossEntropyLoss)用于跟踪损失,[`SGD`](https://pytorch.org/docs/master/optim.html?highlight=sgd#torch.optim.SGD)实现随机梯度下降方法作为优化器。 初始学习率设置为 5.0。 [`StepLR`](https://pytorch.org/docs/master/optim.html?highlight=steplr#torch.optim.lr_scheduler.StepLR)用于通过历时调整学习率。 在训练期间,我们使用[`nn.utils.clip_grad_norm_`](https://pytorch.org/docs/master/nn.html?highlight=nn%20utils%20clip_grad_norm#torch.nn.utils.clip_grad_norm_)函数将所有梯度缩放在一起,以防止爆炸。
[`CrossEntropyLoss`](https://pytorch.org/docs/master/nn.html?highlight=crossentropyloss#torch.nn.CrossEntropyLoss)用于跟踪损失,[`SGD`](https://pytorch.org/docs/master/optim.html?highlight=sgd#torch.optim.SGD)实现随机梯度下降方法作为优化器。 初始学习率设置为 5.0。 [`StepLR`](https://pytorch.org/docs/master/optim.html?highlight=steplr#torch.optim.lr_scheduler.StepLR)用于通过历时调整学习率。 在训练期间,我们使用[`nn.utils.clip_grad_norm_`](https://pytorch.org/docs/master/nn.html?highlight=nn%20utils%20clip_grad_norm#torch.nn.utils.clip_grad_norm_)函数将所有梯度缩放在一起,以防止爆炸。
```py
criterion = nn.CrossEntropyLoss()
......
......@@ -164,7 +164,7 @@ torch.Size([5, 1, 57])
## 创建网络
在进行自动微分之前,在 Torch 中创建一个循环神经网络涉及在多个时间步长上克隆层的参数。 层保留了隐藏状态和梯度,这些层现在完全由图本身处理。 这意味着您可以非常“纯”的方式将 RNN 用作常规前馈层。
在进行自动微分之前,在 Torch 中创建一个循环神经网络涉及在多个时间步长上克隆层的参数。 层保留了隐藏状态和梯度,这些层现在完全由图本身处理。 这意味着您可以非常“纯”的方式将 RNN 用作常规前馈层。
该 RNN 模块(主要从[面向 Torch 用户的 PyTorch 教程](https://pytorch.org/tutorials/beginner/former_torchies/nn_tutorial.html#example-2-recurrent-net)复制)只有两个线性层,它们在输入和隐藏状态下运行,在输出之后是`LogSoftmax`层。
......
......@@ -212,7 +212,7 @@ MyCell(
这到底是做什么的? 它调用了`Module`,记录了运行`Module`时发生的操作,并创建了`torch.jit.ScriptModule`的实例(其中`TracedModule`是实例)
TorchScript 将其定义记录在中间表示(或 IR)中,在深度学习中通常称为*图*。 我们可以检查带有`.graph`属性的图
TorchScript 将其定义记录在中间表示(或 IR)中,在深度学习中通常称为*图*。 我们可以检查带有`.graph`属性的图:
```py
print(traced_cell.graph)
......
......@@ -83,7 +83,7 @@ torch_model.eval()
```
在 PyTorch 中导出模型是通过跟踪或脚本编写的。 本教程将以通过跟踪导出的模型为例。 要导出模型,我们调用`torch.onnx.export()`函数。 这将执行模型,并记录使用什么运算符计算输出的轨迹。 因为`export`运行模型,所以我们需要提供输入张量`x`。 只要是正确的类型和大小,其中的值就可以是随机的。 请注意,除非指定为动态轴,否则输入尺寸将在导出的 ONNX 图中固定为所有输入尺寸。 在此示例中,我们使用输入`batch_size 1`导出模型,但随后在`torch.onnx.export()``dynamic_axes`参数中将第一维指定为动态。 因此,导出的模型将接受大小为`[batch_size, 1, 224, 224]`的输入,其中`batch_size`可以是可变的。
在 PyTorch 中导出模型是通过跟踪或脚本编写的。 本教程将以通过跟踪导出的模型为例。 要导出模型,我们调用`torch.onnx.export()`函数。 这将执行模型,并记录使用什么运算符计算输出的轨迹。 因为`export`运行模型,所以我们需要提供输入张量`x`。 只要是正确的类型和大小,其中的值就可以是随机的。 请注意,除非指定为动态轴,否则输入尺寸将在导出的 ONNX 图中固定为所有输入尺寸。 在此示例中,我们使用输入`batch_size 1`导出模型,但随后在`torch.onnx.export()``dynamic_axes`参数中将第一维指定为动态。 因此,导出的模型将接受大小为`[batch_size, 1, 224, 224]`的输入,其中`batch_size`可以是可变的。
要了解有关 PyTorch 导出接口的更多详细信息,请查看[`torch.onnx`文档](https://pytorch.org/docs/master/onnx.html)
......@@ -108,7 +108,7 @@ torch.onnx.export(torch_model, # model being run
我们还计算了`torch_out`(模型之后的输出),我们将用来验证导出的模型在 ONNX 运行时中运行时是否计算出相同的值。
但是,在通过 ONNX 运行时验证模型的输出之前,我们将使用 ONNX 的 API 检查 ONNX 模型。 首先,`onnx.load("super_resolution.onnx")`将加载保存的模型并输出`onnx.ModelProto`结构(用于捆绑 ML 模型的顶级文件/容器格式。有关更多信息,请参见[`onnx.proto`文档](https://github.com/onnx/onnx/blob/master/onnx/onnx.proto)。 然后,`onnx.checker.check_model(onnx_model)`将验证模型的结构并确认模型具有有效的架构。 通过检查模型的版本,图的结构以及节点及其输入和输出,可以验证 ONNX 图的有效性。
但是,在通过 ONNX 运行时验证模型的输出之前,我们将使用 ONNX 的 API 检查 ONNX 模型。 首先,`onnx.load("super_resolution.onnx")`将加载保存的模型并输出`onnx.ModelProto`结构(用于捆绑 ML 模型的顶级文件/容器格式。有关更多信息,请参见[`onnx.proto`文档](https://github.com/onnx/onnx/blob/master/onnx/onnx.proto)。 然后,`onnx.checker.check_model(onnx_model)`将验证模型的结构并确认模型具有有效的架构。 通过检查模型的版本,图的结构以及节点及其输入和输出,可以验证 ONNX 图的有效性。
```py
import onnx
......
......@@ -292,7 +292,7 @@ True
## 转换现有模型
通道在最后支持不受现有模型的限制,因为只要输入格式正确,任何模型都可以转换为通道在最后,并通过图传播格式。
通道在最后支持不受现有模型的限制,因为只要输入格式正确,任何模型都可以转换为通道在最后,并通过图传播格式。
```py
# Need to be done once, after model initialization (or load)
......
......@@ -428,7 +428,7 @@ graph(%x.1 : Dynamic
```
请特别注意图末尾对`my_ops::warp_perspective`的引用。
请特别注意图末尾对`my_ops::warp_perspective`的引用。
注意
......
......@@ -1698,7 +1698,7 @@ Best trial test set accuracy: 0.5537
如果运行代码,则示例输出如下所示:
为了避免浪费资源,大多数审判​​已提早停止。 效果最好的试验的验证准确约为 58%,可以在测试仪上进行确认。
为了避免浪费资源,大多数审判​​已提早停止。 效果最好的试验的验证准确约为 58%,可以在测试仪上进行确认。
就是这样了! 您现在可以调整 PyTorch 模型的参数。
......
......@@ -276,7 +276,7 @@ num_ftrs = model_fe.fc.in_features
```
此时,您需要修改预训练模型。 该模型在开始和结束时都有量化/去量化块。 但是,由于只使用要素提取器,因此反量化层必须在线性层(头部)之前移动。 最简单的方法是将模型包装在`nn.Sequential`模块中。
此时,您需要修改预训练模型。 该模型在开始和结束时都有量化/去量化块。 但是,由于只使用特征提取器,因此反量化层必须在线性层(头部)之前移动。 最简单的方法是将模型包装在`nn.Sequential`模块中。
第一步是在 ResNet 模型中隔离特征提取器。 尽管在本示例中,您被责成使用`fc`以外的所有层作为特征提取器,但实际上,您可以根据需要选择任意数量的零件。 如果您也想替换一些卷积层,这将很有用。
......
......@@ -390,7 +390,7 @@ class RNNModel(nn.Module):
现在,我们准备实现训练循环。 初始化模型参数后,我们创建`RNNModel``DistributedOptimizer`。 分布式优化器将采用参数`RRefs`的列表,查找所有不同的所有者工作器,并在每个所有者工作器上创建给定的本地优化器(即,在这种情况下,您也可以使用其他本地优化器`SGD`) 使用给定的参数(即`lr=0.05`)。
在训练循环中,它首先创建一个分布式 Autograd 上下文,这将帮助分布式 Autograd 引擎查找梯度和涉及的 RPC 发送/接收函数。 分布式 Autograd 引擎的设计详细信息可以在其[设计说明](https://pytorch.org/docs/master/notes/distributed_autograd.html)中找到。 然后,它像本地模型一样开始正向传播,并运行分布式后向传递。 对于后向分布,您只需要指定一个根列表,在这种情况下,就是损失`Tensor`。 分布式 Autograd 引擎将自动遍历分布式图并正确编写梯度。 接下来,它在分布式优化器上运行`step`函数,该函数将与所有涉及的本地优化器联系以更新模型参数。 与本地训练相比,一个较小的差异是您不需要运行`zero_grad()`,因为每个 Autograd 上下文都有专用的空间来存储梯度,并且在每次迭代创建上下文时,来自不同迭代的那些梯度不会累积到同一组`Tensors`
在训练循环中,它首先创建一个分布式 Autograd 上下文,这将帮助分布式 Autograd 引擎查找梯度和涉及的 RPC 发送/接收函数。 分布式 Autograd 引擎的设计详细信息可以在其[设计说明](https://pytorch.org/docs/master/notes/distributed_autograd.html)中找到。 然后,它像本地模型一样开始正向传播,并运行分布式后向传递。 对于后向分布,您只需要指定一个根列表,在这种情况下,就是损失`Tensor`。 分布式 Autograd 引擎将自动遍历分布式图并正确编写梯度。 接下来,它在分布式优化器上运行`step`函数,该函数将与所有涉及的本地优化器联系以更新模型参数。 与本地训练相比,一个较小的差异是您不需要运行`zero_grad()`,因为每个 Autograd 上下文都有专用的空间来存储梯度,并且在每次迭代创建上下文时,来自不同迭代的那些梯度不会累积到同一组`Tensors`
```py
def run_trainer():
......
......@@ -50,7 +50,7 @@
1. 我们看到传统的机器学习算法的表现在一定时间后收敛,因为它们无法吸收超过阈值的数据量的不同表示形式。
2. 检查图的左下角,靠近原点。 这是算法的相对顺序没有很好定义的区域。 由于数据量小,内部表示形式并没有那么明显。 结果,所有算法的表现指标都一致。 在此级别上,表现与更好的要素工程成正比。 但是这些手工设计的特征随着数据大小的增加而失败。 这就是深度神经网络的来历,因为它们能够从大量数据中捕获更好的表示。
2. 检查图的左下角,靠近原点。 这是算法的相对顺序没有很好定义的区域。 由于数据量小,内部表示形式并没有那么明显。 结果,所有算法的表现指标都一致。 在此级别上,表现与更好的特征工程成正比。 但是这些手工设计的特征随着数据大小的增加而失败。 这就是深度神经网络的来历,因为它们能够从大量数据中捕获更好的表示。
因此,我们可以得出结论,不应该将深度学习架构应用于任何遇到的数据。 所获得数据的数量和种类表明要应用哪种算法。 有时,小数据通过传统的机器学习算法比深度神经网络更有效。
......@@ -78,7 +78,7 @@
上图设置了神经网络的基本方法,即如果我们在第一层中有输入,而在第二层中有输出,则它看起来像。 让我们尝试解释一下。 这里:
* `X1``X2``X3`是输入要素变量,即此处的输入维为 3(考虑到没有偏差变量)。
* `X1``X2``X3`是输入特征变量,即此处的输入维为 3(考虑到没有偏差变量)。
* `W1``W2``W3`是与特征变量关联的相应权重。 当我们谈论神经网络的训练时,我们的意思是说权重的训练。 因此,这些构成了我们小型神经网络的参数。
......@@ -282,7 +282,7 @@ ReLU 的导数图,对于`x <= 0`,`f'(x) = 1`,对于`x > 0`,`f'(x) = 0`
* ![](img/fbdcd2fc-ce0e-4eb7-a681-cc83616c6af7.png)
上式中使用的`α`是指学习率。 学习率是学习智能体适应新知识的速度。 因此,`α`,即学习率是需要作为标量值或时间函数分配的超参数。 这样,在每次迭代中,`W``b`的值都按照上式进行更新,直到成本函数的值达到可接受的最小值为止。
上式中使用的`α`是指学习率。 学习率是学习智能体适应新知识的速度。 因此,`α`,即学习率是需要作为标量值或时间函数分配的超参数。 这样,在每次迭代中,`W``b`的值都按照上式进行更新,直到成本函数的值达到可接受的最小值为止。
梯度下降算法意味着沿斜率向下移动。 曲线的斜率由关于参数的成本函数`J`表示。 斜率(即斜率)给出了正斜率(如果为正)和负斜率的方向。 因此,我们必须使用负号与斜率相乘,因为我们必须与增加斜率的方向相反并朝减小斜率的方向相反。
......@@ -308,7 +308,7 @@ ReLU 的导数图,对于`x <= 0`,`f'(x) = 1`,对于`x > 0`,`f'(x) = 0`
![](img/5f23715e-3539-463e-abfc-3c9c24407512.png)
假设我们有两个输入要素,即二维和`m`样本数据集。 因此,将是以下情况:
假设我们有两个输入特征,即二维和`m`样本数据集。 因此,将是以下情况:
1. `X = {x[1], x[2]}`
......@@ -387,7 +387,7 @@ Xavier 初始化是神经网络中权重的初始化,是遵循高斯分布的
* 对聚合信号进行激活以创建更深层的内部表示,这些表示又是相应隐藏节点的值
参考上图,我们有三个输入特征`x[1], x[2], x[3]`。 显示值为 1 的节点被视为偏置单元。 除输出外,每一层通常都有一个偏置单元。 偏差单位可以看作是一个拦截项,在左右激活函数中起着重要作用。 请记住,隐藏层和其中的节点的数量是我们一开始定义的超参数。 在这里,我们将隐藏层数定义为 1,将隐藏节点的数数定义为 3,`a[1], a[2], a[3]`。 因此,可以说我们有三个输入单元,三个隐藏单元和三个输出单元(`h[1], h[2], h[3]`,因为我们要预测的类别是三类)。 这将为我们提供与层关联的权重和偏差的形状。 例如,第 0 层具有 3 个单位,第 1 层具有 3 个单位。与第`i`层相关联的权重矩阵和偏差向量的形状如下:
参考上图,我们有三个输入特征`x[1], x[2], x[3]`。 显示值为 1 的节点被视为偏置单元。 除输出外,每一层通常都有一个偏置单元。 偏置单元可以看作是一个拦截项,在左右激活函数中起着重要作用。 请记住,隐藏层和其中的节点的数量是我们一开始定义的超参数。 在这里,我们将隐藏层数定义为 1,将隐藏节点的数数定义为 3,`a[1], a[2], a[3]`。 因此,可以说我们有三个输入单元,三个隐藏单元和三个输出单元(`h[1], h[2], h[3]`,因为我们要预测的类别是三类)。 这将为我们提供与层关联的权重和偏差的形状。 例如,第 0 层具有 3 个单元,第 1 层具有 3 个单元。与第`i`层相关联的权重矩阵和偏差向量的形状如下:
![](img/491169f7-46c4-469b-93cd-1cb8f4f01162.png)
......@@ -419,7 +419,7 @@ Xavier 初始化是神经网络中权重的初始化,是遵循高斯分布的
其中,`f`函数是指激活函数。 记住逻辑回归,其中我们分别使用 Sigmoid 和 softmax a 激活函数进行二进制和多类逻辑回归。
类似地,我们可以这样计算输出单
类似地,我们可以这样计算输出单
![](img/89fd6d5b-2b5c-4f51-be1a-3fd44e83eddd.png)
......@@ -750,7 +750,7 @@ Q 学习涉及的步骤:
7. 运行多个剧集来训练智能体
为简化起见,我们可以说,给定状态`s`和动作`a`的 Q 值由当前奖励`r`以及新状态在其所有操作中的折扣(`γ`)最大`Q`最大值。 与当前奖励相比,折扣因子延迟了来自未来的奖励。 例如,今天的 100 奖励在将来值将超过 100。 同样,将来的 100 奖励的当前值必须不到 100。 因此,我们将折扣未来的奖励。 连续重复此更新过程会导致 Q 表值收敛到给定状态下给定操作的预期未来奖励的准确量。
为简化起见,我们可以说,给定状态`s`和动作`a`的 Q 值由当前奖励`r`以及新状态在其所有操作中的折扣(`γ`)最大`Q`最大值。 与当前奖励相比,折扣因子延迟了来自未来的奖励。 例如,今天的 100 奖励在将来值将超过 100。 同样,将来的 100 奖励的当前值必须不到 100。 因此,我们将折扣未来的奖励。 连续重复此更新过程会导致 Q 表值收敛到给定状态下给定操作的预期未来奖励的准确量。
当状态空间和动作空间的数量增加时,很难维护 Q 表。 在现实世界中,状态空间无限大。 因此,需要另一种无需 Q 表即可生成`Q(s, a)`方法。 一种解决方案是用函数替换 Q 表。 该函数将状态作为向量形式的输入,并输出给定​​状态下所有动作的 Q 值向量。 该函数逼近器可以由神经网络表示,以预测 Q 值。 因此,当状态和动作空间变大时,我们可以添加更多的层并适合于深度神经网络,以更好地预测 Q 值,这对于 Q 表来说似乎是不可能的。 这样就产生了 Q 网络,如果使用了更深层的神经网络(例如卷积神经网络),那么它会导致**深度 Q 网络****DQN**)。
......@@ -970,7 +970,7 @@ array([[[ 1., 1.],
[ 1., 1.]]], dtype=float32)
```
TensorFlow 中的计算流程表示为一个计算图,作为`tf.Graph`的实例。 该图包含张量和操作对象,并跟踪涉及的一系列操作和张量。 图的默认实例可以通过`tf.get_default_graph()`获取:
TensorFlow 中的计算流程表示为一个计算图,作为`tf.Graph`的实例。 该图包含张量和操作对象,并跟踪涉及的一系列操作和张量。 图的默认实例可以通过`tf.get_default_graph()`获取:
```py
>>> tf.get_default_graph()
......
......@@ -46,7 +46,7 @@ DeepMind 在研究期刊 **Nature** 上发表了他们的论文[《通过深度
# 基于模型的学习和无模型学习
在第 3 章,“马尔可夫决策过程”中,我们使用状态,动作,奖励,转移模型和折扣因子来解决我们的马尔可夫决策过程,即 MDP 问题。 因此,如果 MDP 问题的所有这些素均可用,我们可以轻松地使用规划算法为目标提出解决方案。 这种类型的学习称为**基于模型的学习**,其中 AI 智能体将与环境交互,并基于其交互,将尝试近似环境的模型,即状态转换模型。 给定模型,现在智能体可以尝试通过值迭代或策略迭代找到最佳策略。
在第 3 章,“马尔可夫决策过程”中,我们使用状态,动作,奖励,转移模型和折扣因子来解决我们的马尔可夫决策过程,即 MDP 问题。 因此,如果 MDP 问题的所有这些素均可用,我们可以轻松地使用规划算法为目标提出解决方案。 这种类型的学习称为**基于模型的学习**,其中 AI 智能体将与环境交互,并基于其交互,将尝试近似环境的模型,即状态转换模型。 给定模型,现在智能体可以尝试通过值迭代或策略迭代找到最佳策略。
但是,对于我们的 AI 智能体来说,学习环境的显式模型不是必需的。 它可以直接从与环境的交互中得出最佳策略,而无需构建模型。 这种学习称为**无模型学习**。 无模型学习涉及在没有具体环境模型的情况下预测某个策略的值函数。
......@@ -442,7 +442,7 @@ import gym
* `__init__``self``learning_rate``gamma``n_features``n_actions``epsilon``parameter_changing_pointer``memory_size`):默认构造器,用于分配超参数,例如:
* `learning_rate`
* `gamma`,即折扣因子
* `n_feature`:状态中的要素数,即状态中的尺寸数
* `n_feature`:状态中的特征数,即状态中的尺寸数
* `epsilon`:ε 贪婪条件的阈值,以利用或探索动作
* `build_networks()`:使用 Tensorflow 创建主要和目标网络
* `target_params_replaced(self)`:用主要网络参数替换目标网络参数
......@@ -942,7 +942,7 @@ if __name__ == "__main__":
* `__init__(self,learning_rate,gamma,n_features,n_actions,epsilon,parameter_changing_pointer,memory_size)`:分配超参数的默认构造器,例如:
* `learning_rate`
* `gamma`:即折扣系数
* `n_feature`:状态下的要素数量,即状态下的尺寸数
* `n_feature`:状态下的特征数量,即状态下的尺寸数
* `epsilon`:利用或探索行为的ε贪婪条件的阈值
* `parameter_changing_pointer`:一个整数值(例如`n`),指定在每`n`次迭代之后,将主网络的参数复制到目标网络
* `memory_size`:体验回复的最大长度
......
......@@ -80,7 +80,7 @@
![](img/a439e6b9-b14f-40fb-84e3-2d8ef4bf84ca.png)
* 识别周围环境的组成部分,其中包括人行道,人,交通信号灯,任何建筑,道路边界,其他车辆等。 对于 AI,由于使用**卷积神经网络****CNN**)和**生成对抗网络****GAN**)。 CNN 和 GAN 的成功可用于自动驾驶环境要素的识别过程。
* 识别周围环境的组成部分,其中包括人行道,人,交通信号灯,任何建筑,道路边界,其他车辆等。 对于 AI,由于使用**卷积神经网络****CNN**)和**生成对抗网络****GAN**)。 CNN 和 GAN 的成功可用于自动驾驶环境组件的识别过程。
* **预测**环境的未来状态。 识别当前环境状态的环境的当前组成部分很重要,但是将其用作输入并预测未来环境状态对于计划下一步行动也很有必要。 解决此问题的基本方法之一是创建环境图。 此外,我们可以合并深度神经网络,例如循环神经网络的变体,例如**长短期记忆网络****LSTM**)或**门控循环单元****GRU**),以整合和整合过去时间步长以及当前时间步长和预测未来中的数据。 正如我们在第 1 章,“深度学习–架构和框架”中讨论的那样,由于长期依赖以及 LSTM 单元如何解决该问题,围绕梯度消失的问题仍然存在 RNN 的情况。 RNN 是集成时间序列数据的最新技术,它在 [DeepTracking](https://arxiv.org/pdf/1602.00991.pdf)中显示了对象跟踪方面的改进。
* **规划**是整个过程中最难的部分。 该任务包括将识别和预测的结果集成在一起,以计划将来的动作序列以及下一个驾驶动作集(向左或向右转向,加速等等),以使导航安全且成功。 这是一项艰巨的任务,因为整合和规划需要处理不可避免的情况才能安全到达目的地。 强化学习最适合此类控制计划任务。 我们已经了解了如何成功地部署强化学习来控制 50 场 Atari 游戏中的计划任务,以及 Google DeepMind 提供的最先进的 AlphaGo Zero。 在这些情况下,我们目睹了深度学习在进行表示学习的同时进行强化学习的规划。
......
......@@ -75,7 +75,7 @@
机器人与现实世界互动。 因此,机器人强化学习的真正问题是应对这些现实问题。 这是因为在现实世界中机器人组件的定期磨损非常昂贵。 连续的维护和修理在劳力和维护和修理的时间损失方面付出了巨大的代价。 因此,安全探索是机器人强化学习过程中的关键问题。
Perkins 和 Barto(2002)提出了一种基于 Lyapunov 函数构造强化学习主体的方法(附录 A,“强化学习中的其他主题”)。 现实世界带来的挑战包括环境因素的变化,即气候,温度,光线等。 结果,由于温度和气候的极端影响,机器人的动力学将受到影响,并且将避免学习过程的收敛。 现实环境是不确定的。 结果,由于气候,温度,光线等外部因素,无法产生过去的学习时间。 因此,状态是不确定的,因此很难模拟真实的真实场景。 因此,大多数模拟器都没有考虑气候,温度和光的素。 因此,这对要解决的算法提出了严峻的挑战。 除此之外,传感器噪声测量的不确定性导致无法直接用传感器观察所有状态。
Perkins 和 Barto(2002)提出了一种基于 Lyapunov 函数构造强化学习主体的方法(附录 A,“强化学习中的其他主题”)。 现实世界带来的挑战包括环境因素的变化,即气候,温度,光线等。 结果,由于温度和气候的极端影响,机器人的动力学将受到影响,并且将避免学习过程的收敛。 现实环境是不确定的。 结果,由于气候,温度,光线等外部因素,无法产生过去的学习时间。 因此,状态是不确定的,因此很难模拟真实的真实场景。 因此,大多数模拟器都没有考虑气候,温度和光的素。 因此,这对要解决的算法提出了严峻的挑战。 除此之外,传感器噪声测量的不确定性导致无法直接用传感器观察所有状态。
现实世界中的大多数机器人学习任务都需要人工监督,而获取现实世界中的样本在时间,劳动力和金钱方面都非常昂贵。 在机器人强化学习中,无法使用诸如模拟器之类的情景设置,因为它们在时间,维修和金钱上都花费很多。 机器人需要在严格的约束下与现实世界互动,以免造成重大破坏。
......
......@@ -165,7 +165,7 @@ Paulus 等人(2017)在[《用于抽象摘要的深度强化模型》](https:
为了解决这个问题,熊等人发表了他们的研究《DCN+:问答的混合目标和深度残差协作》,*提出了使用混合目标函数的方法,该函数是交叉熵损失和自我批判策略学习的组合。 这个混合目标使用从单词重叠中获得的奖励来解决现有模型中评估与优化之间的脱节问题。
提出的新框架对于需要捕获长期依存关系的长问题表现更好,能够获得 75.1% 的精确匹配准确度和 83.1% 的 F1 分数的强大结果,而集成模型获得 78.9% 的精确匹配准确度和 86.0% F1 分数。
提出的新框架对于需要捕获长期依存关系的长问题表现更好,能够获得 75.1% 的精确匹配准确率和 83.1% 的 F1 分数的强大结果,而集成模型获得 78.9% 的精确匹配准确率和 86.0% F1 分数。
因此,混合目标的方法提供了两个好处:
......
......@@ -50,7 +50,7 @@ The cat is on the mat
There is a cat on the mat
```
如果目标只是一个正确的答案,那么准确度的测量很容易,但是如果存在多个同样正确的可能性,那么在这种情况下如何测量准确度? 在本节中,我们将研究 BLEU 分数,BLEU 分数是一种评估指标,用于在出现多个同等正确答案的情况下,测量准确率。
如果目标只是一个正确的答案,那么准确率的测量很容易,但是如果存在多个同样正确的可能性,那么在这种情况下如何测量准确率? 在本节中,我们将研究 BLEU 分数,BLEU 分数是一种评估指标,用于在出现多个同等正确答案的情况下,测量准确率。
# 什么是 BLEU 分数,它的作用是什么?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册