diff --git a/docs/handson-cnn-tf/2.md b/docs/handson-cnn-tf/2.md index 803787055c6efb9c680f655001bbb9c06c0a8641..e3122fd62c43b8dfc47283858786107143113d74 100644 --- a/docs/handson-cnn-tf/2.md +++ b/docs/handson-cnn-tf/2.md @@ -93,11 +93,11 @@ ML 的新型深度学习方法具有的最酷的功能是,它们不需要( * 隐藏层 * 输出层 -基本的人工神经元通过计算输入及其内部*权重*之间的点积来工作(参见下图),然后将结果传递给非线性激活函数 *f* (S 型) ,在此示例中)。 然后将这些人工神经元连接在一起以形成网络。 在训练该网络期间,目标是找到合适的权重集,这些权重将有助于我们希望网络执行的任何任务: +基本的人工神经元通过计算输入及其内部*权重*之间的点积来工作(参见下图),然后将结果传递给非线性激活函数`f`(S 型) ,在此示例中)。 然后将这些人工神经元连接在一起以形成网络。 在训练该网络期间,目标是找到合适的权重集,这些权重将有助于我们希望网络执行的任何任务: ![](img/7ceed94c-24a7-4e1b-8225-5786d5c92da7.jpg) -接下来,我们有一个 2 层前馈人工神经网络的示例。 想象一下,神经元之间的联系就是训练过程中将学习的权重。 在此示例中,层 *L1* 将是输入层, *L2* 隐藏层,而 *L3* 将是输出层。 按照惯例,在计算层数时,我们仅包括权重可学习的层; 因此,我们不包括输入层。 这就是为什么它只是一个 2 层网络: +接下来,我们有一个 2 层前馈人工神经网络的示例。 想象一下,神经元之间的联系就是训练过程中将学习的权重。 在此示例中,层`L1`将是输入层,`L2`隐藏层,而`L3`将是输出层。 按照惯例,在计算层数时,我们仅包括权重可学习的层; 因此,我们不包括输入层。 这就是为什么它只是一个 2 层网络: ![](img/996c3a5a-a193-414b-b66b-fadb01b58569.png) @@ -125,7 +125,7 @@ ML 的新型深度学习方法具有的最酷的功能是,它们不需要( 在使用人工神经元的早期,人们并不像我们在人工神经网络中那样将各层级联在一起,因此我们最终得到了一个称为感知器的单层: -**![](img/89dc6f56-f3bb-4c95-8a60-eb17810aa8e3.png)** +![](img/89dc6f56-f3bb-4c95-8a60-eb17810aa8e3.png) 感知器实际上只是输入和一组学习的权重之间的点积,这意味着它实际上只是线性分类器。 @@ -143,12 +143,12 @@ ML 的新型深度学习方法具有的最酷的功能是,它们不需要( 当我们说网络学习时,所发生的就是网络参数被更新,网络应该能够为训练数据集中的每个 X 输出正确的 Y。 期望的是,在对网络进行训练之后,它将能够针对训练期间未看到的新输入进行概括并表现良好。 但是,为了做到这一点,您必须有一个足够具有代表性的数据集,以捕获要输出的内容。 例如,如果要分类汽车,则需要具有不同类型,颜色,照度等的数据集。 -通常,当我们没有足够的数据或者我们的模型不够复杂以至于无法捕获数据的复杂性时,就会出现训练机器学习模型的一个常见错误。 这些错误可能导致过度拟合和拟合不足的问题。 在以后的章节中,您将学习如何在实践中处理这些问题。 +通常,当我们没有足够的数据或者我们的模型不够复杂以至于无法捕获数据的复杂性时,就会出现训练机器学习模型的一个常见错误。 这些错误可能导致过拟合和拟合不足的问题。 在以后的章节中,您将学习如何在实践中处理这些问题。 -在训练期间,*以两种不同的模式执行网络*:** +在训练期间,*以两种不同的模式执行网络*: * **正向传播**:我们通过网络向前工作,为数据集中的当前给定输入生成输出结果。 然后评估损失函数,该函数告诉我们网络在预测正确输出方面的表现如何。 -* **向后传播**:我们通过网络进行反向计算,计算每个权重对产生网络电流损耗的影响。 +* **反向传播**:我们通过网络进行反向计算,计算每个权重对产生网络电流损耗的影响。 此图显示了训练时网络运行的两种不同方式。 @@ -162,7 +162,7 @@ ML 的新型深度学习方法具有的最酷的功能是,它们不需要( # 反向传播和链式规则 -反向传播算法实际上只是微积分中可信赖链规则的一个示例。 它说明了如何找到某个输入对由多个功能组成的系统的影响。 因此,例如在下图中,如果您想知道 *x* 对函数 *g* 的影响,我们只需将 *f* 对 g 的影响乘以 *x* 对 *f* 的影响: +反向传播算法实际上只是微积分中可信赖链规则的一个示例。 它说明了如何找到某个输入对由多个功能组成的系统的影响。 因此,例如在下图中,如果您想知道`x`对函数`g`的影响,我们只需将`f`对`g`的影响乘以`x`对`f`的影响: ![](img/85cb6c18-9cbc-44ff-9db6-c7d90d3c7cf0.png) @@ -176,7 +176,7 @@ ML 的新型深度学习方法具有的最酷的功能是,它们不需要( # 分批 -对于大型数据集而言,将整个数据集存储在内存中以训练网络的想法,例如第 1 章,*设置和 TensorFlow 简介*中的示例。 人们在实践中所做的是,在训练期间,他们将数据集分成小块,称为迷你批次(通常称为批次)。 然后,依次将每个微型批次装入并馈送到网络,在网络中将计算反向传播和梯度下降算法,然后更新权重。 然后,对每个小批量重复此操作,直到您完全浏览了数据集。 +对于大型数据集而言,将整个数据集存储在内存中以训练网络的想法,例如第 1 章,“TensorFlow 简介和设置”中的示例。 人们在实践中所做的是,在训练期间,他们将数据集分成小块,称为迷你批次(通常称为批次)。 然后,依次将每个微型批次装入并馈送到网络,在网络中将计算反向传播和梯度下降算法,然后更新权重。 然后,对每个小批量重复此操作,直到您完全浏览了数据集。 为小批量计算的梯度是对整个训练集的真实梯度的噪声估计,但是通过反复获取这些小的噪声更新,我们最终仍将收敛到足够接近损失函数的最小值。 @@ -186,17 +186,17 @@ ML 的新型深度学习方法具有的最酷的功能是,它们不需要( # 损失函数 -在训练阶段,我们需要使用当前的权重正确预测训练集; 此过程包括评估我们的训练集输入 *X* ,并与所需的输出 *Y* 进行比较。 需要某种机制来量化(返回标量数)我们当前的权重在正确预测我们所需的输出方面有多好。 该机制称为**损失函数。** +在训练阶段,我们需要使用当前的权重正确预测训练集; 此过程包括评估我们的训练集输入 *X* ,并与所需的输出 *Y* 进行比较。 需要某种机制来量化(返回标量数)我们当前的权重在正确预测我们所需的输出方面有多好。 该机制称为**损失函数**。 反向传播算法应返回每个参数相对于损失函数的导数。 这意味着我们将发现更改每个参数将如何影响损耗函数的值。 然后,优化算法的工作就是最小化损失函数,换句话说,就是在训练时减小训练误差。 一个重要方面是为工作选择合适的损失函数。 一些最常见的损失函数及其用途是在此处给出的: -* **对数丢失**-仅具有两个可能结果的分类任务(从有限集中返回标签) -* **交叉熵损失**-具有两个以上结果的分类任务(从有限集返回标签) -* **L1 损失**-回归任务(返回实数值) -* **L2 损失**-回归任务(返回实数值) -* **Huber 损失**-回归任务(返回实数值) +* **对数损失** - 仅具有两个可能结果的分类任务(从有限集中返回标签) +* **交叉熵损失** - 具有两个以上结果的分类任务(从有限集返回标签) +* **L1 损失** - 回归任务(返回实数值) +* **L2 损失** - 回归任务(返回实数值) +* **Huber 损失** - 回归任务(返回实数值) 在本书中,我们将看到损失函数的不同示例。 @@ -212,7 +212,7 @@ TensorFlow 的以下代码行也显示了这一点,因为损失仅需要标签 loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits) ``` -您可能会注意到第三个箭头也连接到损失功能。 这与名为正则化的东西有关,将在第 3 章和 *TensorFlow* 中的图像分类中进行探讨; 因此,现在您可以放心地忽略它。 +您可能会注意到第三个箭头也连接到损失功能。 这与名为正则化的东西有关,将在第 3 章“TensorFlow 中的图像分类”中进行探讨; 因此,现在您可以放心地忽略它。 # 优化器及其超参数 @@ -256,9 +256,9 @@ TensorFlow 的所有不同优化器都可以在`tf.train`类中找到。 例如 如果我们专注于第二点,它使我们了解选择或设计神经网络架构/结构时可能发生的两个问题。 -这些问题中的第一个是模型对于训练数据的数量或复杂性而言是否太大。 由于模型具有如此众多的参数,因此即使在数据中存在噪声的情况下,它也可以轻松轻松地准确地学习其在训练集中看到的内容。 这是一个问题,因为当向网络提供的数据与训练集不完全相同时,网络将无法正常运行,因为它过于精确地了解了数据的外观,而错过了其背后的全局。 这个问题称为**过度拟合**或具有**高变异性**。 +这些问题中的第一个是模型对于训练数据的数量或复杂性而言是否太大。 由于模型具有如此众多的参数,因此即使在数据中存在噪声的情况下,它也可以轻松轻松地准确地学习其在训练集中看到的内容。 这是一个问题,因为当向网络提供的数据与训练集不完全相同时,网络将无法正常运行,因为它过于精确地了解了数据的外观,而错过了其背后的全局。 这个问题称为**过拟合**或具有**高方差**。 -另一方面,您可能选择的网络规模不足以捕获数据复杂性。 现在,我们遇到了相反的问题,由于您的模型没有足够的能力(参数)来充分学习,因此您的模型无法充分捕获数据集背后的基础结构。 网络将再次无法对新数据执行良好的操作。 这个问题称为**不足**或具有**高偏置**。 +另一方面,您可能选择的网络规模不足以捕获数据复杂性。 现在,我们遇到了相反的问题,由于您的模型没有足够的能力(参数)来充分学习,因此您的模型无法充分捕获数据集背后的基础结构。 网络将再次无法对新数据执行良好的操作。 这个问题称为**欠拟合**或具有**高偏差**。 您可能会怀疑,在模型复杂性方面,您总是会寻求适当的平衡,以避免这些问题。 @@ -288,7 +288,7 @@ TensorFlow 的所有不同优化器都可以在`tf.train`类中找到。 例如 组成我们之前看到的 ANN 的神经元层通常称为密集连接层,或**完全连接的**(**FC**)层,或简称为线性层。 诸如 Caffe 之类的一些深度学习库实际上会将它们视为点乘积运算,非线性层可能会或可能不会跟随它们。 它的主要参数将是输出大小,基本上是其输出中神经元的数量。 -在第 1 章,*设置和 TensorFlow* 简介中,我们创建了自己的致密层,但是您可以使用`tf.layers`来更轻松地创建它,如下所示: +在第 1 章,“TensorFlow 简介和设置”中,我们创建了自己的致密层,但是您可以使用`tf.layers`来更轻松地创建它,如下所示: ```py dense_layer = tf.layers.dense(inputs=some_input_layer, units=1024, activation=tf.nn.relu) @@ -296,7 +296,7 @@ dense_layer = tf.layers.dense(inputs=some_input_layer, units=1024, activation=tf 在这里,我们定义了一个具有 1,024 个输出的完全连接层,随后将激活 ReLU。 -重要的是要注意,该层的输入必须仅具有二维,因此,如果您的输入是空间张量,例如形状为[28 * 28 * 3]的图像,则必须在输入之前将其重整为矢量 它: +重要的是要注意,该层的输入必须仅具有二维,因此,如果您的输入是空间张量,例如形状为`[28 * 28 * 3]`的图像,则必须在输入之前将其重整为矢量 它: ```py reshaped_input_to_dense_layer = tf.reshape(spatial_tensor_in, [-1, 28 * 28 * 3]) @@ -393,7 +393,7 @@ CNN 主要由称为**卷积层**的层组成,这些层对其层输入进行过 您可能已经猜到了,在卷积层中要学习的参数是该层内核的权重。 在 CNN 训练期间,这些过滤器的值会自动调整,以便为手头任务提取最有用的信息。 -在传统的神经网络中,我们将必须将任何输入数据转换为单个一维向量,从而在将该向量发送到完全连接的层后丢失所有重要的空间信息。 此外,每个像素每个神经元都有一个参数,导致输入大小或输入深度较大的模型中参数数量激增。 +在传统的神经网络中,我们将必须将任何输入数据转换为单个一维向量,从而在将该向量发送到全连接层后丢失所有重要的空间信息。 此外,每个像素每个神经元都有一个参数,导致输入大小或输入深度较大的模型中参数数量激增。 但是,在卷积层的情况下,每个内核将在整个输入中“滑动”以搜索特定补丁。 CNN 中的内核很小,并且与它们所卷积的大小无关。 结果,就参数而言,使用 conv 层的开销通常比我们之前了解的传统密集层要少得多。 @@ -411,7 +411,7 @@ CNN 主要由称为**卷积层**的层组成,这些层对其层输入进行过 * **内核大小(K)**:滑动窗口的像素大小。 小通常更好,通常使用奇数,例如 1、3、5,有时很少使用 7。 * **跨度(S)**:内核窗口在卷积的每个步骤中将滑动多少像素。 通常将其设置为 1,因此图像中不会丢失任何位置,但是如果我们想同时减小输入大小,则可以增加位置。 -* **零填充(填充)**:要放在图像边框上的零数量。 使用填充使内核可以完全过滤输入图像的每个位置,包括边缘。 +* **零填充(P)**:要放在图像边框上的零数量。 使用填充使内核可以完全过滤输入图像的每个位置,包括边缘。 * **过滤器数(F)**:我们的卷积层将具有多少个过滤器。 它控制卷积层将要查找的图案或特征的数量。 在 TensorFlow 中,我们将在`tf.layers`模块中找到 2-D 卷积层,可以将其添加到模型中,如下所示: @@ -471,7 +471,7 @@ out_height = ceil(float(in_height) / float(strides[1])) ![](img/2b389e68-88be-45b4-95df-a668889ff0be.png) -另一方面,完全连接的层中的参数数量(包括偏置)如下: +另一方面,全连接层中的参数数量(包括偏置)如下: ![](img/1bdd4a61-a6cd-4e05-ba1d-da98caa3801c.png) @@ -496,27 +496,35 @@ out_height = ceil(float(in_height) / float(strides[1])) MAC 的数量可以计算为: -#MAC = [F * F * C *(H + 2 * P-FS + 1)*(W + 2 * P-FS + 1)* M] * B +```py +#MAC = [F * F * C *(H + 2 * P-FS + 1)*(W + 2 * P-FS + 1)* M] * B +``` 例如,让我们考虑一个具有输入 224 x 224 x 3,批处理大小为 1,内核为 3x3、64 个过滤器,跨度为 1 和填充 1 的转换层: -#MAC = 3 * 3 *(224 + 2-31 + 1)*(224 + 2-31 + 1)* 3 * 64 * 1 = 9,462,528 +```py +#MAC = 3 * 3 *(224 + 2-31 + 1)*(224 + 2-31 + 1)* 3 * 64 * 1 = 9,462,528 +``` -相反,完全连接的层具有以下操作数: +相反,全连接层具有以下操作数: -#MAC = [H * W * C * Outputneurons] * B +```py +#MAC = [H * W * C * Outputneurons] * B +``` 让我们重用相同的示例,但现在有 64 个神经元的密集层: -#MAC = [224 * 224 * 3 * 64] * 1 = 9,633,792 +```py +#MAC = [224 * 224 * 3 * 64] * 1 = 9,633,792 +``` (我们已排除了所有运维计算的偏差,但不应增加太多成本。) 通常,在 CNN 中,早期的 conv 层贡献了大部分计算成本,但参数最少。 在网络的末尾,相反的情况是后面的层具有更多的参数,但计算成本却较低。 -# 将卷积层转换为完全连接的层 +# 将卷积层转换为全连接层 -实际上,我们可以将完全连接的层视为卷积层的子集。 如果我们将内核大小设置为与输入大小匹配,则可以将 CNN 层转换为完全连接的层。 设置过滤器的数量与设置完全连接层中输出神经元的数量相同。 检查一下自己,在这种情况下,操作将是相同的。 +实际上,我们可以将全连接层视为卷积层的子集。 如果我们将内核大小设置为与输入大小匹配,则可以将 CNN 层转换为全连接层。 设置过滤器的数量与设置完全连接层中输出神经元的数量相同。 检查一下自己,在这种情况下,操作将是相同的。 例: @@ -526,7 +534,7 @@ MAC 的数量可以计算为: 使用公式来计算输出大小,我们得到大小为 1 x 1 x 4096 的输出。 -这样做的主要原因之一是使您的网络完全卷积。 当网络完全卷积时,决定使用比输入的图像更大的输入大小图像并不重要,因为您没有任何需要固定输入大小的完全连接的层。 +这样做的主要原因之一是使您的网络完全卷积。 当网络完全卷积时,决定使用比输入的图像更大的输入大小图像并不重要,因为您没有任何需要固定输入大小的全连接层。 # 池化层 @@ -592,7 +600,7 @@ tf.layers.max_pooling2d(inputs=some_input_layer, pool_size=[2, 2], strides=2) 在开始之前,有个好消息:使用 TensorFlow,您无需担心编写反向传播或梯度下降代码,而且所有常见类型的层都已实现,因此事情应该更轻松。 -在此处的 TensorFlow 示例中,我们将根据您在第 1 章,*设置和 TensorFlow* 简介中学到的内容进行一些更改,并使用`tf.layers` API 创建整个 我们的网络轻松自如: +在此处的 TensorFlow 示例中,我们将根据您在第 1 章,“TensorFlow 简介和设置”中学到的内容进行一些更改,并使用`tf.layers` API 创建整个 我们的网络轻松自如: ```py import tensorflow as tf @@ -735,7 +743,7 @@ with tf.Session() as sess: 现在,我们将仅按名称和使用位置提及它们: * **深度卷积**:用于 MobileNets,旨在使卷积对移动平台友好 -* **膨胀卷积(Atrous 卷积)**:它们具有称为膨胀率的额外参数,可让您以相同的计算成本获得更大的视野(例如 3x3 CONV 可以具有相同的视野 作为 5x5 CONV) +* **膨胀卷积(Atrous Convolution)**:它们具有称为膨胀率的额外参数,可让您以相同的计算成本获得更大的视野(例如 3x3 CONV 可以具有相同的视野 作为 5x5 CONV) * **转置卷积(Deconvolutions)**:通常用于 CNN 自编码器和语义分割问题 # 摘要 diff --git a/docs/handson-cnn-tf/3.md b/docs/handson-cnn-tf/3.md index 05515d8ea9e29c39fc2e5524e2ccf341c96ba742..9fc99170be3231a850b98a3689e9c098273b8ec0 100644 --- a/docs/handson-cnn-tf/3.md +++ b/docs/handson-cnn-tf/3.md @@ -23,7 +23,7 @@ # CNN 模型架构 -图像分类模型的关键部分是其 CNN 层。 这些层将负责从图像数据中提取特征。 这些 CNN 图层的输出将是一个特征向量,就像以前一样,我们可以将其用作所选分类器的输入。 对于许多 CNN 模型,分类器将只是连接到我们 CNN 输出的完全连接层。 如第 1 章,*设置和 TensorFlow* 简介中所示,我们的线性分类器只是一个完全连接的层; 除了层的大小和输入会有所不同之外,这里就是这种情况。 +图像分类模型的关键部分是其 CNN 层。 这些层将负责从图像数据中提取特征。 这些 CNN 图层的输出将是一个特征向量,就像以前一样,我们可以将其用作所选分类器的输入。 对于许多 CNN 模型,分类器将只是连接到我们 CNN 输出的完全连接层。 如第 1 章,*设置和 TensorFlow* 简介中所示,我们的线性分类器只是一个全连接层; 除了层的大小和输入会有所不同之外,这里就是这种情况。 重要的是要注意,分类或回归问题(例如本地化)(或其他使用图像的其他问题)所使用的 CNN 架构在本质上是相同的。 唯一真正的不同是,在 CNN 层完成特征提取之后会发生什么。 例如,一个差异可能是用于不同任务的损失函数,如下图所示: @@ -560,9 +560,9 @@ bias_initializer=tf.zeros_initializer()) 我们使用的 CNN 架构是可以提高模型泛化能力的方法之一。 要记住的一种简单技术是从设计模型开始就尽可能简单地使用很少的图层或滤镜。 由于非常小的模型很可能无法适应您的数据,因此您可以慢慢增加复杂性,直到不再发生适应不足的情况为止。 如果您以这种方式设计模型,则将限制过拟合的可能性,因为您不允许自己拥有的模型对于数据集而言过大。 -但是,在本节中,我们将探索我们可以做的其他一些事情,以建立更好的机器学习模型,以及如何将它们纳入我们的训练过程中。 以下方法旨在防止过度拟合,并通过这样做,有助于创建更强大的模型,并能更好地进行泛化。 防止模型过度拟合的过程称为**正则化**。 +但是,在本节中,我们将探索我们可以做的其他一些事情,以建立更好的机器学习模型,以及如何将它们纳入我们的训练过程中。 以下方法旨在防止过拟合,并通过这样做,有助于创建更强大的模型,并能更好地进行泛化。 防止模型过拟合的过程称为**正则化**。 -另一个可能也会发生并且看起来与过度拟合非常相似的问题是,如果您的训练数据集没有捕获您想要分类的所有事物。 例如,如果您正在训练狗分类器,但是您的训练图像仅包含贵宾犬的图像。 如果要在 Labradors 上测试此训练有素的分类器,则可能无法分类。 这种数据不平衡是一个单独的问题,将在后面的章节中解决。 +另一个可能也会发生并且看起来与过拟合非常相似的问题是,如果您的训练数据集没有捕获您想要分类的所有事物。 例如,如果您正在训练狗分类器,但是您的训练图像仅包含贵宾犬的图像。 如果要在 Labradors 上测试此训练有素的分类器,则可能无法分类。 这种数据不平衡是一个单独的问题,将在后面的章节中解决。 # L2 和 L1 正则化 @@ -576,13 +576,13 @@ bias_initializer=tf.zeros_initializer()) 在这里,我们添加了对网络所有权重求和的正则化项。 此处,![](img/79c3facc-6820-4331-81de-13ffd441a44e.png)是层索引,![](img/a768718b-3d2d-4584-825b-4b7007032c3b.png)是每一层的权重矩阵的索引。 L2 正则化的表达式看起来类似。 -对于 L1 正则化,此额外项鼓励权重向量变得稀疏,这意味着许多权重值变为零。 结果,该模型变得不受噪声输入的影响,因为权重向量将仅使用重要输入的子集,这有助于避免过度拟合。 +对于 L1 正则化,此额外项鼓励权重向量变得稀疏,这意味着许多权重值变为零。 结果,该模型变得不受噪声输入的影响,因为权重向量将仅使用重要输入的子集,这有助于避免过拟合。 -对于 L2 正则化,除了保持权重之和较低之外,这个额外的项还强制权重值均匀分布在权重向量上,以便模型稍微使用所有权重,而不是大量使用权重。 由于输入和权重之间的乘法交互作用,从直觉上讲,这是一个理想的属性,可帮助模型避免过度拟合。 L2 正则化有时也称为权重衰减; 这是因为在训练期间,您的所有权重都会因该项(L2 正则化项的导数)而线性减少或“衰减”。 +对于 L2 正则化,除了保持权重之和较低之外,这个额外的项还强制权重值均匀分布在权重向量上,以便模型稍微使用所有权重,而不是大量使用权重。 由于输入和权重之间的乘法交互作用,从直觉上讲,这是一个理想的属性,可帮助模型避免过拟合。 L2 正则化有时也称为权重衰减; 这是因为在训练期间,您的所有权重都会因该项(L2 正则化项的导数)而线性减少或“衰减”。 请注意,在正则化期间我们不包括偏差项,而仅包括权重。 这是因为偏差项并不会真正影响模型的过拟合,因为它们以累加的方式影响输出,只是向上或向下移动而不是改变函数的形状。 包含它们没有害处,但是也没有好处,因此包含它们没有意义。 -在下图中,您可能会注意到增加正则强度 lambda 会减少过度拟合。 高正则化项意味着网络变得接近线性,并且无法塑造复杂的决策边界。 +在下图中,您可能会注意到增加正则强度 lambda 会减少过拟合。 高正则化项意味着网络变得接近线性,并且无法塑造复杂的决策边界。 ![](img/4d15337d-40dd-44ad-8e45-39df3674a015.png) @@ -631,7 +631,7 @@ combined_loss = tf.n_add(train_loss, reg_losses) ![](img/eef8f1a2-e6e1-40aa-9c0e-8ef692a60665.png) -通常,辍学仅适用于完全连接的层,但也可以适用于卷积/池化层。 如果这样做,则将使用较低的 *p* (掉线的可能性),接近 0.2。 同样,您将辍学层放置在激活层之后。 +通常,辍学仅适用于全连接层,但也可以适用于卷积/池化层。 如果这样做,则将使用较低的 *p* (掉线的可能性),接近 0.2。 同样,您将辍学层放置在激活层之后。 要在 TensorFlow 模型中使用 dropout,我们在希望将 dropout 应用到的输入层上调用`tf.layers.dropout()`。 我们还必须指定我们要使用的辍学率,更重要的是,使用布尔值让 TensorFlow 知道我们的模型是否在训练中。 请记住,当我们在测试时使用模型时,我们会关闭辍学,而这个布尔值将为我们做到这一点。 因此,带有辍学的代码将如下所示: @@ -665,7 +665,7 @@ fc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training) * 给您的模型某种正则化效果 * 使得可以使用饱和非线性,例如 S 型 -对于更多的数学读者,可以在批处理规范论文“批处理规范化:通过减少内部协变量偏移来加速深层网络训练”中找到更为正式的定义,这是一篇写得很好的论文,易于理解和解释。 更详细的概念。 如果假设我们有一个仅具有完全连接的层的简单神经网络,则正如我们在第 1 章,*设置和 TensorFlow* 简介中所看到的,每一层的激活将是 ![](img/9d0ff275-b662-433d-b367-ac3ac9b46b54.png)表格。 +对于更多的数学读者,可以在批处理规范论文“批处理规范化:通过减少内部协变量偏移来加速深层网络训练”中找到更为正式的定义,这是一篇写得很好的论文,易于理解和解释。 更详细的概念。 如果假设我们有一个仅具有全连接层的简单神经网络,则正如我们在第 1 章,*设置和 TensorFlow* 简介中所看到的,每一层的激活将是 ![](img/9d0ff275-b662-433d-b367-ac3ac9b46b54.png)表格。 假设![](img/c0d727f5-4add-40b7-95df-07d67752638f.png)是非线性的,例如 S 型或 ReLU,然后将批量归一化![](img/fb58ac38-9b3e-4f29-b02e-ee58df896884.png)直接应用于每个单元,例如: diff --git a/docs/handson-cnn-tf/4.md b/docs/handson-cnn-tf/4.md index 7c124ec466f504b34d14d88a0b1ffb8ccd5fdad6..6350ffa44cc4a41eb0e50455049956be8ee13d49 100644 --- a/docs/handson-cnn-tf/4.md +++ b/docs/handson-cnn-tf/4.md @@ -49,7 +49,7 @@ ![](img/6a08d3d3-b216-46bf-9d8a-6ca5e8c715ff.png) -从图中可以清楚地看到三个完全连接的层,每个层都输出不同的损耗(状态,类和框)。 使用的损失是逻辑回归/对数损失,交叉熵/ softmax 损失和 Huber 损失。 胡贝尔损失是我们从未见过的损失。 这是用于回归的损失,是 L1 和 L2 损失的一种组合。 +从图中可以清楚地看到三个全连接层,每个层都输出不同的损耗(状态,类和框)。 使用的损失是逻辑回归/对数损失,交叉熵/ softmax 损失和 Huber 损失。 胡贝尔损失是我们从未见过的损失。 这是用于回归的损失,是 L1 和 L2 损失的一种组合。 局部化的回归损失给出了图像中对象的地面真实边界框坐标与模型预测的边界框坐标之间的某种相似度度量。 我们在这里使用 Huber 损失,但是可以使用各种不同的损失函数,例如 L2,L1 或平滑 L1 损失。 @@ -162,7 +162,7 @@ R-CNN 在计算上仍然很昂贵,因为您必须对大约 2,000 个单独的 2015 年,提出了快速 R-CNN 来解决 R-CNN 的速度问题。 在此方法中,主要的变化是我们在管道中获取投标区域的位置。 首先,我们通过 CNN 运行整个输入图像,而不是从输入图像中直接获取它们,并提取靠近网络末端的生成的特征图。 接下来,再次使用区域提议方法,以与 R-CNN 类似的方式从该特征图中提取候选区域。 -以这种方式获取建议有助于重用和共享昂贵的卷积计算。 网络中位于网络下方的完全连接的层将分类并另外定位,仅接受固定大小的输入。 因此,使用称为 **RoI 池**的新层将特征图中建议的区域扭曲为固定大小(在下一节中进一步讨论)。 RoI 池会将区域大小调整为最后一个 FC 层所需的大小。 下图显示了整个过程: +以这种方式获取建议有助于重用和共享昂贵的卷积计算。 网络中位于网络下方的全连接层将分类并另外定位,仅接受固定大小的输入。 因此,使用称为 **RoI 池**的新层将特征图中建议的区域扭曲为固定大小(在下一节中进一步讨论)。 RoI 池会将区域大小调整为最后一个 FC 层所需的大小。 下图显示了整个过程: ![](img/067ed6db-52ab-4dff-9eac-8bb0f36c174a.jpg) @@ -188,7 +188,7 @@ RPN 的工作是预测我们称为锚点的对象(本质上只是一个边界 # RoI 汇聚层 -RoI 池层只是最大池的一种,池的大小取决于输入的大小。 这样做可以确保输出始终具有相同的大小。 使用该层是因为完全连接的层始终期望输入大小相同,但是 FC 层的输入区域可能具有不同的大小。 +RoI 池层只是最大池的一种,池的大小取决于输入的大小。 这样做可以确保输出始终具有相同的大小。 使用该层是因为全连接层始终期望输入大小相同,但是 FC 层的输入区域可能具有不同的大小。 RoI 层的输入将是建议和最后的卷积层激活。 例如,考虑以下输入图像及其建议: @@ -243,7 +243,7 @@ YOLO 网络的主要思想是在不使用任何滑动窗口的情况下优化输 网络为每个单元格预测类别概率,边界框和这些框的置信度。 -实际的 YOLO 网络具有 24 个卷积层,其后是 2 个完全连接的层。 但是,Fast YOLO 网络是 9 层,如下所示: +实际的 YOLO 网络具有 24 个卷积层,其后是 2 个全连接层。 但是,Fast YOLO 网络是 9 层,如下所示: ![](img/ba26c46a-1c3a-44c6-b82f-88cf0070814e.png) diff --git a/docs/handson-cnn-tf/5.md b/docs/handson-cnn-tf/5.md index f01a78886394f6ac4d60c4e3992da28aca43cbcc..50350690c6c02d54a1987e27e704744b55a36897 100644 --- a/docs/handson-cnn-tf/5.md +++ b/docs/handson-cnn-tf/5.md @@ -108,7 +108,7 @@ VGG 最酷的功能之一是,由于其在 conv 层中的内核较小,因此 到那时为止,这是所有参数的六倍以上! -如前所述,您需要在训练数据集中使用大量样本来消耗模型参数,因此最好避免过度使用完全连接的层来避免参数爆炸。 幸运的是,人们发现,如果最后只有一层而不是三层,那么 VGGNet 的工作原理几乎相同。 因此,删除这些完全连接的层会从模型中删除大量参数,而不会大大降低性能。 因此,如果您决定实施 VGGNet,我们建议您也这样做。 +如前所述,您需要在训练数据集中使用大量样本来消耗模型参数,因此最好避免过度使用全连接层来避免参数爆炸。 幸运的是,人们发现,如果最后只有一层而不是三层,那么 VGGNet 的工作原理几乎相同。 因此,删除这些全连接层会从模型中删除大量参数,而不会大大降低性能。 因此,如果您决定实施 VGGNet,我们建议您也这样做。 # 码 @@ -202,7 +202,7 @@ VGG 最酷的功能之一是,由于其在 conv 层中的内核较小,因此 # 关于 VGG 的更多信息 -2014 年,VGG 在 Imagenet 分类挑战中获得第二名,在 Imagenet 本地化挑战中获得第一名。 正如我们所看到的,VGGNet 的设计选择是堆叠许多小的卷积层,从而可以实现更深的结构,同时具有更少的参数(如果我们删除了不必要的完全连接的层),则性能更好。 这种设计选择在创建强大而高效的网络方面非常有效,以至于几乎所有现代体系结构都复制了这种想法,并且很少(如果有的话)使用大型过滤器。 +2014 年,VGG 在 Imagenet 分类挑战中获得第二名,在 Imagenet 本地化挑战中获得第一名。 正如我们所看到的,VGGNet 的设计选择是堆叠许多小的卷积层,从而可以实现更深的结构,同时具有更少的参数(如果我们删除了不必要的全连接层),则性能更好。 这种设计选择在创建强大而高效的网络方面非常有效,以至于几乎所有现代体系结构都复制了这种想法,并且很少(如果有的话)使用大型过滤器。 事实证明,VGG 模型可以在许多任务中很好地工作,并且由于其简单的体系结构,它是开始尝试或适应问题需求的理想模型。 但是,它确实有以下问题需要注意: diff --git a/docs/handson-cnn-tf/6.md b/docs/handson-cnn-tf/6.md index 2c157645ca97169341f46bc898c884e6e27c374d..36b795a61f8a972da6b971a7a551f01da9e9302d 100644 --- a/docs/handson-cnn-tf/6.md +++ b/docs/handson-cnn-tf/6.md @@ -38,7 +38,7 @@ ![](img/bace7dc4-4820-4dcd-934d-7215a3d8e4ce.png) -传统上,在自编码器中,构成网络的层只是完全连接的层,但是通过使用卷积层,自编码器也可以扩展到图像。 与之前一样,编码器会将输入图像压缩为较小的表示形式,而解码器将尽最大努力恢复信息。 区别在于,编码器现在是将数据压缩为特征向量的 CNN,而不是具有完全连接的层的 ANN,并且解码器将使用转置的卷积层从编码中重新生成图像。 +传统上,在自编码器中,构成网络的层只是全连接层,但是通过使用卷积层,自编码器也可以扩展到图像。 与之前一样,编码器会将输入图像压缩为较小的表示形式,而解码器将尽最大努力恢复信息。 区别在于,编码器现在是将数据压缩为特征向量的 CNN,而不是具有全连接层的 ANN,并且解码器将使用转置的卷积层从编码中重新生成图像。 此处提供了一个自编码器处理图像的示例。 对于解码器部分 @@ -239,7 +239,7 @@ class VAE_CNN(object): tf.summary.histogram("latent_sample", self.__guessed_z) ``` -之后,我们添加网络的解码器部分,该部分包括一个完全连接的层,然后是两个转置的卷积层: +之后,我们添加网络的解码器部分,该部分包括一个全连接层,然后是两个转置的卷积层: ```py with tf.name_scope('DECODER'): @@ -349,7 +349,7 @@ GAN 的一些实际用法如下: # 鉴别器 -我们需要做的第一件事就是创建我们的区分网络。 为此,我们将几个完全连接的层堆叠在一起。 鉴别器将 784 个长度向量作为输入,这是我们的 28x28 MNIST 图像变平。 每个图像的输出将只是一个数字,这是鉴别者对该图像为真实图像的信心程度的分数。 我们使用 Leaky ReLu 作为激活功能,以防止 ReLu 单元死亡。 +我们需要做的第一件事就是创建我们的区分网络。 为此,我们将几个全连接层堆叠在一起。 鉴别器将 784 个长度向量作为输入,这是我们的 28x28 MNIST 图像变平。 每个图像的输出将只是一个数字,这是鉴别者对该图像为真实图像的信心程度的分数。 我们使用 Leaky ReLu 作为激活功能,以防止 ReLu 单元死亡。 我们返回原始 logit,因为损失函数将为我们应用 S 型激活函数,以确保鉴别器输出在 0 到 1 之间: @@ -364,7 +364,7 @@ def discriminator(x): # 发电机 -现在我们创建发电机网络。 生成器的工作是将随机噪声的矢量作为输入,并从中生成输出图像。 在此示例中,我们再次使用完全连接的层,这些层最后将产生 784 个长向量的输出,我们可以对其进行整形以获得 28x28 的图像: +现在我们创建发电机网络。 生成器的工作是将随机噪声的矢量作为输入,并从中生成输出图像。 在此示例中,我们再次使用全连接层,这些层最后将产生 784 个长向量的输出,我们可以对其进行整形以获得 28x28 的图像: ```py def generator(z): @@ -509,7 +509,7 @@ generator_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'generator' # Deep convolutional GAN -**深度卷积 GAN**(**DCGAN**)是我们之前看到的普通 GAN 的扩展。 我们不是使用完全连接的层,而是使用卷积层。 想法是使用卷积层可以帮助生成器形成更好的图像。 以下是这种模型的示例: +**深度卷积 GAN**(**DCGAN**)是我们之前看到的普通 GAN 的扩展。 我们不是使用全连接层,而是使用卷积层。 想法是使用卷积层可以帮助生成器形成更好的图像。 以下是这种模型的示例: ![](img/b9cf2f8e-db74-44ab-8090-d032d5a82d24.jpg) diff --git a/docs/handson-cnn-tf/7.md b/docs/handson-cnn-tf/7.md index aa28ea69bffd0e05abf25345d03b7a294d16cd8c..856a34df881d89d46180c442fbe45083163e1771 100644 --- a/docs/handson-cnn-tf/7.md +++ b/docs/handson-cnn-tf/7.md @@ -1,6 +1,6 @@ # 迁移学习 -迁移学习的作用恰如其名。 这个想法是将从一项任务中学到的东西转移到另一项任务上。 为什么? 实际上,每次都从头开始训练整个模型的效率很低,其成功取决于许多因素。 另一个重要原因是,对于某些应用程序,公开可用的数据集不够大,无法训练出像 AlexNet 或 ResNet 这样的深层架构而又不会过度拟合,这意味着无法推广。 示例应用程序可以从用户给出的一些示例中进行在线学习,也可以是细粒度的分类,其中类别之间的差异很小。 +迁移学习的作用恰如其名。 这个想法是将从一项任务中学到的东西转移到另一项任务上。 为什么? 实际上,每次都从头开始训练整个模型的效率很低,其成功取决于许多因素。 另一个重要原因是,对于某些应用程序,公开可用的数据集不够大,无法训练出像 AlexNet 或 ResNet 这样的深层架构而又不会过拟合,这意味着无法推广。 示例应用程序可以从用户给出的一些示例中进行在线学习,也可以是细粒度的分类,其中类别之间的差异很小。 一个非常有趣的观察结果是,由于您冻结了所有其余部分(无论是检测还是分类),最终的层可以用于完成不同的任务,最终权重看起来非常相似。 @@ -17,7 +17,7 @@ 研究表明,在 ImageNet 上训练的卷积网络权重中的特征提取优于常规特征提取方法,例如 SURF,[H​​TG0]可变形部分描述符(**DPD** s),**定向梯度直方图**(**HOG**)和**一袋单词**(**BoW**)。 这意味着无论常规视觉表示如何工作,卷积特征都可以同样好地使用,唯一的缺点是更深的架构可能需要更长的时间来提取特征。 -当在 ImageNet 上训练深层卷积神经网络时,第一层中的卷积滤波器的可视化(请参见下图)显示,他们学习了*低层*特征,类似于边缘检测滤波器,而卷积滤波器 在最后一层学习*高级*功能,这些功能捕获特定于类的信息。 因此,如果我们在第一个池化层之后提取 ImageNet 的特征并将其嵌入 2D 空间(例如,使用 t-SNE),则可视化将显示数据中存在一些无政府状态,而如果执行 在完全连接的层上相同,我们将注意到具有相同语义信息的数据被组织成簇。 这意味着网络可以在更高层次上很好地概括,并且有可能将这种知识转移到看不见的类别中。 +当在 ImageNet 上训练深层卷积神经网络时,第一层中的卷积滤波器的可视化(请参见下图)显示,他们学习了*低层*特征,类似于边缘检测滤波器,而卷积滤波器 在最后一层学习*高级*功能,这些功能捕获特定于类的信息。 因此,如果我们在第一个池化层之后提取 ImageNet 的特征并将其嵌入 2D 空间(例如,使用 t-SNE),则可视化将显示数据中存在一些无政府状态,而如果执行 在全连接层上相同,我们将注意到具有相同语义信息的数据被组织成簇。 这意味着网络可以在更高层次上很好地概括,并且有可能将这种知识转移到看不见的类别中。 ![](img/b7b186d6-7803-4517-add9-f559586b2576.png) @@ -40,7 +40,7 @@ 深度学习的另一种不太常见的方式是自己预先训练模型。 当可用的预训练网络不适合解决特定问题时,通常会发生这种情况,我们必须自己设计网络体系结构。 显然,这需要更多的时间和精力来设计模型和准备数据集。 在某些情况下,用于进行网络预训练的数据集甚至可以是合成的,可以从计算机图形引擎(例如 3D Studio Max 或 Unity)或其他卷积神经网络(例如 GAN)生成。 可以对虚拟数据进行预训练的模型在真实数据上进行微调,并且可以与仅对真实数据进行训练的模型一起很好地工作。 -例如,如果我们想区分猫和狗,而我们没有足够的数据,则可以从“模型动物园”下载在 ImageNet 上训练的网络,并使用除最后一层以外的所有层的权重。 最后一层必须调整为具有与班级数量相同的大小,在本例中为两个,并且权重需要重新初始化和训练。 这样,通过将这些层的学习率设置为零或非常小的值(请参见下图),我们将冻结那些不需训练的层。 如果有更大的数据集,我们可以训练最后三个完全连接的层。 有时,预训练网络只能用于初始化权重,然后再进行正常训练。 +例如,如果我们想区分猫和狗,而我们没有足够的数据,则可以从“模型动物园”下载在 ImageNet 上训练的网络,并使用除最后一层以外的所有层的权重。 最后一层必须调整为具有与班级数量相同的大小,在本例中为两个,并且权重需要重新初始化和训练。 这样,通过将这些层的学习率设置为零或非常小的值(请参见下图),我们将冻结那些不需训练的层。 如果有更大的数据集,我们可以训练最后三个全连接层。 有时,预训练网络只能用于初始化权重,然后再进行正常训练。 迁移学习之所以有效,是因为在初始层计算出的特征更通用并且看起来很相似。 在顶层提取的特征对于我们要解决的问题变得更加具体。 diff --git a/docs/handson-cnn-tf/8.md b/docs/handson-cnn-tf/8.md index 0997dc65f85173f035303b7cfe81b76b7c3bb970..5e7995a20282be43fa5cf07ee2e153943eaa62a0 100644 --- a/docs/handson-cnn-tf/8.md +++ b/docs/handson-cnn-tf/8.md @@ -58,7 +58,7 @@ # 偏差和方差 -如第 2 章,“深度学习和卷积神经网络”中所讨论的,方差和偏差分别表示过拟合和欠拟合。 我们可以使用训练集,开发集和测试集错误来诊断“拟合不足”和“过度拟合”的问题。 +如第 2 章,“深度学习和卷积神经网络”中所讨论的,方差和偏差分别表示过拟合和欠拟合。 我们可以使用训练集,开发集和测试集错误来诊断“拟合不足”和“过拟合”的问题。 考虑以下场景,其中我们的数据来自两个不同的分布,分别称为分布 1 和分布 2。分布 2 表示我们关心的目标应用程序。 问题是,我们如何在这种分布上定义训练,开发和测试集。 @@ -81,12 +81,12 @@ 与人员水平的表现相比,训练误差较大,这意味着该模型甚至无法拟合数据。 训练有素,因此欠拟合/高偏见。 但是,当我们在这种情况下查看 dev 错误时,它可以很好地概括,因此不会丢失所有内容。 -* 高差异/过度拟合 +* 高差异/过拟合 | 训练错误 | 1.5% | | 火车开发错误 | 30% | -在这种情况下,该模型在看不见的数据上表现不佳,该数据与训练集属于同一分布,但不是训练的一部分。 这意味着该模型无法概括,因此会过度拟合训练数据。 +在这种情况下,该模型在看不见的数据上表现不佳,该数据与训练集属于同一分布,但不是训练的一部分。 这意味着该模型无法概括,因此会过拟合训练数据。 * 高方差和高偏见 @@ -113,7 +113,7 @@ ML 基本配方 -有用的图表说明了测试和训练误差如何随模型复杂性而变化,如下所示。 一方面,当模型过于复杂时,往往会过度拟合训练数据,因此,训练误差减小而测试误差增大。 另一方面,较简单的模型往往不适合并且无法推广。 模型复杂度的理想范围是在“测试误差”开始增加之前以及“训练误差”接近零时的某个位置。 +有用的图表说明了测试和训练误差如何随模型复杂性而变化,如下所示。 一方面,当模型过于复杂时,往往会过拟合训练数据,因此,训练误差减小而测试误差增大。 另一方面,较简单的模型往往不适合并且无法推广。 模型复杂度的理想范围是在“测试误差”开始增加之前以及“训练误差”接近零时的某个位置。 ![](img/3b7eb077-6c15-4a77-989a-40b12e4b70db.png) @@ -131,7 +131,7 @@ ML 基本配方 # 数据综合/扩充 -在无法从其他资源收集数据,数据集太小或收集的数据不能很好地表示的情况下,我们需要以某种方式自行生成数据。 这称为数据增强。 智能生成的数据可以解决许多问题,包括数据集不平衡,训练数据不足和过度拟合。 +在无法从其他资源收集数据,数据集太小或收集的数据不能很好地表示的情况下,我们需要以某种方式自行生成数据。 这称为数据增强。 智能生成的数据可以解决许多问题,包括数据集不平衡,训练数据不足和过拟合。 数据扩充通常是作为输入数据管道的一部分来完成的,该管道在训练时为模型提供数据。 随机地,而不是提供原始训练图像,您将应用一些增强来更改它。 有很多方法可以进行数据扩充,但是一些示例是: @@ -320,6 +320,6 @@ class CAE_CNN_Encoder(object): # 摘要 -在本章中,我们了解到遵循最佳实践将对作为机器学习工程师的日常活动有所帮助。 我们已经看到了如何准备数据集并将其拆分为子集,以促进对网络的正确训练和微调。 此外,我们还研究了执行有意义的测试,其中获得的结果代表了将模型部署到目标应用程序时所看到的结果。 涉及的另一个主题是对数据的过度拟合和不足,以及为了解决这些问题而应遵循的最佳实践。 此外,解决了数据集不平衡的问题,我们已经看到了一个简单的示例,该示例可能在哪里找到(疾病诊断)。 为了解决这个问题,建议收集更多的数据,扩充数据集并选择不平衡数据集不变的评估指标。 最后,展示了如何构造代码以使其更具可读性和重用性。 +在本章中,我们了解到遵循最佳实践将对作为机器学习工程师的日常活动有所帮助。 我们已经看到了如何准备数据集并将其拆分为子集,以促进对网络的正确训练和微调。 此外,我们还研究了执行有意义的测试,其中获得的结果代表了将模型部署到目标应用程序时所看到的结果。 涉及的另一个主题是对数据的过拟合和不足,以及为了解决这些问题而应遵循的最佳实践。 此外,解决了数据集不平衡的问题,我们已经看到了一个简单的示例,该示例可能在哪里找到(疾病诊断)。 为了解决这个问题,建议收集更多的数据,扩充数据集并选择不平衡数据集不变的评估指标。 最后,展示了如何构造代码以使其更具可读性和重用性。 在下一章中,我们将看到如何管理大型数据集以及如何将训练过程扩展到多个 GPU 和系统。 \ No newline at end of file