提交 01d7172b 编写于 作者: W wizardforcel

2020-09-15 14:06:33

上级 7e52817c
......@@ -137,7 +137,7 @@ def my_conv_2d(input, weight_shape, num_filters, strides):
因此,不仅要为模型中所需的每种新层将这些内容写出来都非常费力,而且还引入了更多的区域,在这些区域中,错误可能会潜入您的代码中,这从来都不是一件好事。
对我们来说幸运的是,TensorFlow 具有第二层抽象,可以帮助您简化构建 TensorFlow 图时的工作。 这种抽象级别的一个示例是层 API。 层 API 使您可以轻松处理许多机器学习任务中常见的许多构建基块。
对我们来说幸运的是,TensorFlow 具有第二层抽象,可以帮助您简化构建 TensorFlow 图时的工作。 这种抽象级别的一个示例是层 API。 层 API 使您可以轻松处理许多机器学习任务中常见的许多构建基块。
层 API 的工作方式是包装我们在上一个示例中编写的所有内容并将其抽象出来,因此我们不必再为它担心。 例如,我们可以压缩前面的代码以将卷积层构造为一个函数调用。 与以前建立相同的卷积层现在看起来像这样:
......@@ -153,7 +153,7 @@ API 堆栈的最后一层是 TensorFlow 提供的最高抽象层,这称为估
本书不会介绍估计器 API 的用法,但是如果读者希望了解有关估计器的更多信息,可以在 TensorFlow 网站上找到一些有用的教程。
本书将重点介绍如何使用低级 API 以及层,数据集和指标 API 来构建,训练和评估自己的 ML 模型。 我们相信,通过使用这些较低级别的 API,读者将对 TensorFlow 的幕后工作方式有更深入的了解,并有能力更好地应对可能需要使用这些较低级别 API 的各种未来问题。
本书将重点介绍如何使用低级 API 以及层,数据集和指标 API 来构建,训练和评估自己的 ML 模型。 我们相信,通过使用这些较低级别的 API,读者将对 TensorFlow 的幕后工作方式有更深入的了解,并有能力更好地应对可能需要使用这些较低级别 API 的各种未来问题。
# 急切执行
......
......@@ -66,7 +66,7 @@ ML 系统的组成部分是评估。 在评估模型时,我们会看到模型
ML 工程师可能会遵循的典型流程来开发预测模型,如下所示:
1. 收集资料
1. 收集数据
2. 从数据中提取相关特征
3. 选择 ML 体系结构(CNN,ANN,SVM,决策树等)
4. 训练模型
......@@ -436,7 +436,7 @@ TensorFlow 卷积操作为您提供了两种用于填充需求的选项:相同
* 有效-TensorFlow 不填充图像。 卷积内核将仅进入输入中的“有效”位置。
* 相同-如果我们假设步幅为 1,则在这种情况下,TensorFlow 将足够填充输入,以便输出空间大小与输入空间大小相同。
如果您确实希望对填充有更多控制,则可以在层的输入上使用`tf.pad()`,以用所需的零个位数来填充输入。
如果您确实希望对填充有更多控制,则可以在层的输入上使用`tf.pad()`,以用所需的零个位数来填充输入。
通常,我们可以使用以下公式计算卷积运算的输出大小:
......@@ -589,7 +589,7 @@ tf.layers.max_pooling2d(inputs=some_input_layer, pool_size=[2, 2], strides=2)
这些计算与是否使用卷积或池化层无关,例如,步幅为 2 的卷积层将与步幅为 2 的池化层具有相同的感受域。
例如,给定以下层之后的`14x14x3`图像,这将适用:
例如,给定以下层之后的`14x14x3`图像,这将适用:
* 卷积:S:1,P:0,K:3
* 卷积:S:1,P:0,K:3
......
......@@ -41,7 +41,7 @@
# CNN 模型架构
图像分类模型的关键部分是其 CNN 层。 这些层将负责从图像数据中提取特征。 这些 CNN 层的输出将是一个特征向量,就像以前一样,我们可以将其用作所选分类器的输入。 对于许多 CNN 模型,分类器将只是连接到我们 CNN 输出的完全连接层。 如第 1 章,“TensorFlow 简介和设置”中所示,我们的线性分类器只是一个全连接层; 除了层的大小和输入会有所不同之外,这里就是这种情况。
图像分类模型的关键部分是其 CNN 层。 这些层将负责从图像数据中提取特征。 这些 CNN 层的输出将是一个特征向量,就像以前一样,我们可以将其用作所选分类器的输入。 对于许多 CNN 模型,分类器将只是连接到我们 CNN 输出的完全连接层。 如第 1 章,“TensorFlow 简介和设置”中所示,我们的线性分类器只是一个全连接层; 除了层的大小和输入会有所不同之外,这里就是这种情况。
重要的是要注意,分类或回归问题(例如定位)(或其他使用图像的其他问题)所使用的 CNN 架构在本质上是相同的。 唯一真正的不同是,在 CNN 层完成特征提取之后会发生什么。 例如,一个差异可能是用于不同任务的损失函数,如下图所示:
......@@ -407,13 +407,13 @@ decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)
# `tf.data` API 简介
在继续之前,我们将看一下 TensorFlow 处理数据输入到我们可能训练的任何模型的方式。 TensorFlow `tf.data` API 为我们提供了轻松构建复杂的输入管道可能需要的所有工具。 您可能通常会构建的一个管道将涉及加载原始训练数据,对其进行一些预处理,改组,然后将其分批准备进行训练。 `tf.data` API 使我们能够使用简单且可重复使用的代码段轻松地完成所有这些步骤。
在继续之前,我们将看一下 TensorFlow 处理数据输入到我们可能训练的任何模型的方式。 TensorFlow `tf.data` API 为我们提供了轻松构建复杂的输入流水线可能需要的所有工具。 您可能通常会构建的一个流水线将涉及加载原始训练数据,对其进行一些预处理,改组,然后将其分批准备进行训练。 `tf.data` API 使我们能够使用简单且可重复使用的代码段轻松地完成所有这些步骤。
您需要了解`tf.data` API 的两个主要组件。 首先是`tf.data.Dataset`; 这就是您的原始数据。 更具体地说,它包含一系列元素,其中每个元素包含一个或多个张量对象。 对于图像分类任务,一个元素将是一个训练示例,并且它将由两个张量组成-一个张量用于图像,一个张量用于其相应的标签。
第二个成分是`tf.data.Iterator`。 这些允许您从数据集中提取元素,并充当数据集和模型代码之间的连接。 TensorFlow 中有几种不同类型的迭代器,它们都有不同的用途,涉及不同的使用难度。
创建数据集可以通过两种方式完成。 第一种方法是通过创建数据源。 一个简单的例子是使用`tf.data.Dataset.from_tensor_slices()`,它将根据一个或多个张量对象的切片创建一个数据集。 产生数据集的另一种方法是在现有数据集上使用数据集转换。 这样做将返回合并了所应用转换的新数据集。 重要的是要了解所有输入管道必须以数据源开头。 一旦有了`Dataset`对象,通常对它应用所有链接在一起的多个转换。
创建数据集可以通过两种方式完成。 第一种方法是通过创建数据源。 一个简单的例子是使用`tf.data.Dataset.from_tensor_slices()`,它将根据一个或多个张量对象的切片创建一个数据集。 产生数据集的另一种方法是在现有数据集上使用数据集转换。 这样做将返回合并了所应用转换的新数据集。 重要的是要了解所有输入流水线必须以数据源开头。 一旦有了`Dataset`对象,通常对它应用所有链接在一起的多个转换。
目前,一些简单的转换示例包括`Dataset.batch()``Dataset.repeat()`,它们从`Dataset`对象返回一批具有指定大小的批次,当`Dataset`内容到达末尾时,它将继续重复该内容。 一种可以多次遍历数据集的简单方法(`count`参数)。
......@@ -522,7 +522,7 @@ decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)
# 模型初始化
随着我们向模型中添加越来越多的层,使用反向传播训练它们的难度越来越大。 通过模型传递回去以更新权重的误差值随着我们的深入而变得越来越小。 这被称为消失梯度问题。
随着我们向模型中添加越来越多的层,使用反向传播训练它们的难度越来越大。 通过模型传递回去以更新权重的误差值随着我们的深入而变得越来越小。 这被称为消失梯度问题。
因此,在开始训练模型之前,需要注意的重要一件事是将权重初始化为什么值。 错误的初始化会使模型收敛非常慢,或者甚至根本不会收敛。
......@@ -546,7 +546,7 @@ decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)
# Xavier-Bengio 和初始化器
在了解*训练深度前馈神经网络*的难度时,Xavier Glorot 和 Yoshua Bengio 表明,如果从均匀分布`U ~ [-1/√n, 1/√n]`初始化每一层的权重,其中`n`是上一层中的大小,对于乙状结肠激活函数,顶层(更靠近输出)的神经元迅速饱和为 0。我们知道,由于乙状结肠函数的形式,激活值 0 表示权重非常大,并且反向传播的梯度接近零。 较小的梯度值会减慢学习过程,因为早期层中的权重停止更新或停止学习。
在了解*训练深度前馈神经网络*的难度时,Xavier Glorot 和 Yoshua Bengio 表明,如果从均匀分布`U ~ [-1/√n, 1/√n]`初始化每一层的权重,其中`n`是上一层中的大小,对于乙状结肠激活函数,顶层(更靠近输出)的神经元迅速饱和为 0。我们知道,由于乙状结肠函数的形式,激活值 0 表示权重非常大,并且反向传播的梯度接近零。 较小的梯度值会减慢学习过程,因为早期层中的权重停止更新或停止学习。
因此,我们想要的是使权重在最初确定的时间间隔内均匀分布,也就是说,权重的方差应该在我们从底层移动到顶层时保持不变。 这将使错误平稳地流到顶层,从而使网络在训练期间收敛更快。
......@@ -580,7 +580,7 @@ bias_initializer=tf.zeros_initializer())
到目前为止,在本章中,我们已经看到了如何使用 TensorFlow 训练卷积神经网络来完成图像分类任务。 训练完模型后,我们将其遍历测试集,并从一开始就将其存储起来,以查看其在从未见过的数据上的性能如何。 在测试集上评估模型的过程向我们表明了在部署模型时模型将泛化的程度。 能够很好地泛化的模型显然是理想的属性,因为它可以在许多情况下使用。
我们使用的 CNN 架构是可以提高模型泛化能力的方法之一。 要记住的一种简单技术是从设计模型开始就尽可能简单地使用很少的层或滤镜。 由于非常小的模型很可能无法适应您的数据,因此您可以慢慢增加复杂性,直到不再发生适应不足的情况为止。 如果您以这种方式设计模型,则将限制过拟合的可能性,因为您不允许自己拥有的模型对于数据集而言过大。
我们使用的 CNN 架构是可以提高模型泛化能力的方法之一。 要记住的一种简单技术是从设计模型开始就尽可能简单地使用很少的层或滤镜。 由于非常小的模型很可能无法适应您的数据,因此您可以慢慢增加复杂性,直到不再发生适应不足的情况为止。 如果您以这种方式设计模型,则将限制过拟合的可能性,因为您不允许自己拥有的模型对于数据集而言过大。
但是,在本节中,我们将探索我们可以做的其他一些事情,以建立更好的机器学习模型,以及如何将它们纳入我们的训练过程中。 以下方法旨在防止过拟合,并通过这样做,有助于创建更强大的模型,并能更好地进行泛化。 防止模型过拟合的过程称为**正则化**
......@@ -618,7 +618,7 @@ bias_initializer=tf.zeros_initializer())
l2_reg = tf.contrib.layers.l2_regularizer(scale=0.001)
```
`scale`参数是我们通常需要通过交叉验证找到并设置自己的`λ`。 如果将其设置为 0,则不会进行任何正则化。 现在,当我们创建任何层时,我们会将正则化函数作为参数传递。 TensorFlow 将进行计算以获取我们需要添加到损失函数中的所有正则化项:
`scale`参数是我们通常需要通过交叉验证找到并设置自己的`λ`。 如果将其设置为 0,则不会进行任何正则化。 现在,当我们创建任何层时,我们会将正则化函数作为参数传递。 TensorFlow 将进行计算以获取我们需要添加到损失函数中的所有正则化项:
```py
# Example of adding passing regularizer to a conv layer.
......@@ -675,7 +675,7 @@ fc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training)
之前,我们已经完成了权重的初始化工作,以使梯度下降优化器的工作更加轻松。 但是,好处仅在训练的早期阶段才能看到,并不能保证在后期阶段有所改善。 那就是我们转向另一个称为批量规范层的伟大发明的地方。 在 CNN 模型中使用批量规范层产生的效果与第 2 章,“深度学习和卷积神经网络”中看到的输入标准化大致相同。 现在唯一的区别是,这将在模型中所有卷积层和完全连接层的输出处发生。
批量规范层通常将附加到每个完全连接或卷积层的末端,但是在激活函数之前,它将对层输出进行规范化,如下图所示。 它通过获取图层输出(一批激活)并减去批次平均值并除以批次标准差来执行此操作,因此图层输出具有零均值和单位标准差。 请注意,在激活函数之前或之后放置批量规范化是一个引起激烈争论的话题,但是两者都应该起作用。
批量规范层通常将附加到每个完全连接或卷积层的末端,但是在激活函数之前,它将对层输出进行规范化,如下图所示。 它通过获取层输出(一批激活)并减去批次平均值并除以批次标准差来执行此操作,因此层输出具有零均值和单位标准差。 请注意,在激活函数之前或之后放置批量规范化是一个引起激烈争论的话题,但是两者都应该起作用。
![](img/3e1365ac-328e-48f0-8077-920bb837324e.png)
......
......@@ -160,7 +160,7 @@ R-CNN 在计算上仍然很昂贵,因为您必须对大约 2,000 个单独的
# Fast R-CNN
2015 年,提出了快速 R-CNN 来解决 R-CNN 的速度问题。 在此方法中,主要的变化是我们在管道中获取投标区域的位置。 首先,我们通过 CNN 运行整个输入图像,而不是从输入图像中直接获取它们,并提取靠近网络末端的生成的特征图。 接下来,再次使用区域提议方法,以与 R-CNN 类似的方式从该特征图中提取候选区域。
2015 年,提出了快速 R-CNN 来解决 R-CNN 的速度问题。 在此方法中,主要的变化是我们在流水线中获取投标区域的位置。 首先,我们通过 CNN 运行整个输入图像,而不是从输入图像中直接获取它们,并提取靠近网络末端的生成的特征图。 接下来,再次使用区域提议方法,以与 R-CNN 类似的方式从该特征图中提取候选区域。
以这种方式获取建议有助于重用和共享昂贵的卷积计算。 网络中位于网络下方的全连接层将分类并另外定位,仅接受固定大小的输入。 因此,使用称为 **RoI 池**的新层将特征图中建议的区域扭曲为固定大小(在下一节中进一步讨论)。 RoI 池会将区域大小调整为最后一个 FC 层所需的大小。 下图显示了整个过程:
......@@ -566,7 +566,7 @@ def loss_layer(self, predicts, labels, scope='loss_layer'):
这个运算相当不好地称为反卷积,这意味着它是卷积的逆运算,但实际上并非如此。 更恰当的名称是转置卷积或分数步卷积。
层类型为您提供了一种对输入体积进行升采样的学习方法,并且可以在每次需要将输入要素地图智能地投影到更高的空间时使用。 一些用例包括以下内容:
此层类型为您提供了一种对输入体积进行升采样的学习方法,并且可以在每次需要将输入要素地图智能地投影到更高的空间时使用。 一些用例包括以下内容:
* 上采样(条纹转置卷积)== UNPOOL + CONV
* 可视化显着图
......
......@@ -70,7 +70,7 @@
一些网络体系结构,例如残差网络(我们将在后面看到),使用瓶颈技术再次减少了参数数量并增加了非线性。
# 虚拟网
# VGGNet
VGGNet 由牛津大学的**视觉几何组****VGG**)创建,是真正引入堆叠更多层的想法的首批架构之一。 虽然 AlexNet 最初以其七层出现时被认为很深,但与 VGG 和其他现代体系结构相比,这现在已经很小了。
......@@ -80,7 +80,7 @@ VGGNet 由牛津大学的**视觉几何组**(**VGG**)创建,是真正引
堆叠过滤器的这种洞察力带来了能够拥有更深的结构(我们通常会看到更好的结构)的优点,该结构保留了相同的感受域大小,同时还减少了参数数量。 本章后面将进一步探讨这个想法。
# 建筑
# 架构
接下来,我们将看到 VGGNet 的体系结构,特别是包含 16 层的 VGG-16 风格。 所有卷积层都有空间大小为`3x3`的滤镜,并且随着我们深入网络,卷积层中滤镜的数量从 64 个增加到 512 个。
......@@ -110,7 +110,7 @@ VGG 最酷的功能之一是,由于其在 conv 层中的内核较小,因此
如前所述,您需要在训练数据集中使用大量样本来消耗模型参数,因此最好避免过度使用全连接层来避免参数爆炸。 幸运的是,人们发现,如果最后只有一层而不是三层,那么 VGGNet 的工作原理几乎相同。 因此,删除这些全连接层会从模型中删除大量参数,而不会大大降低性能。 因此,如果您决定实现 VGGNet,我们建议您也这样做。
# 码
#
接下来,我们介绍负责在 Tensorflow 中构建 VGG-16 模型图的函数。 像本章中的所有模型一样,VGGNet 旨在对 Imagenet 挑战的 1,000 个类别进行分类,这就是为什么该模型输出大小为 1000 的向量的原因。 显然,可以为您自己的数据集轻松更改此设置,如下所示:
......@@ -200,7 +200,7 @@ VGG 最酷的功能之一是,由于其在 conv 层中的内核较小,因此
self.predictions = tf.nn.softmax(self.fc8, name='predictions')
```
# 关于 VGG 的更多信息
# VGG 的更多信息
2014 年,VGG 在 Imagenet 分类挑战中获得第二名,在 Imagenet 定位挑战中获得第一名。 正如我们所看到的,VGGNet 的设计选择是堆叠许多小的卷积层,从而可以实现更深的结构,同时具有更少的参数(如果我们删除了不必要的全连接层),则性能更好。 这种设计选择在创建强大而高效的网络方面非常有效,以至于几乎所有现代体系结构都复制了这种想法,并且很少(如果有的话)使用大型过滤器。
......@@ -219,7 +219,7 @@ GoogLeNet 具有 22 层,参数几乎比 AlexNet 少 12 倍。 因此,除了
![](img/a792bf21-afb7-4617-90ee-9eaf988cddd9.png)
# 起始模块
# Inception 模块
起始模块(或层的块)旨在覆盖较大的区域,但也保持较高的分辨率,以便也可以在图像中查看重要的本地信息。 除了创建更深的网络外,起始块还引入了并行卷积的思想。 我们的意思是在前一层的输出上执行不同大小的并行卷积。
......@@ -295,7 +295,7 @@ def inception_block_a(x, name='inception_a'):
return concat
```
# 有关 GoogLeNet 的更多信息
# GoogLeNet 的更多信息
GoogLeNet 的主要优点是,它比 VGG 更为准确,同时使用的参数更少,计算能力也更低。 主要的缺点仍然是,如果我们开始堆叠很多初始层,梯度将消失,而且整个网络具有多个分支和多个损失的设计相当复杂。
......@@ -378,7 +378,7 @@ for group_i, group in enumerate(groups):
net = conv + net
```
# 移动网
# MobileNet
我们将以一个新的 CNN 系列结束本章,该系列不仅具有较高的准确性,而且更轻巧,并且在移动设备上的运行速度更快。
......@@ -406,7 +406,7 @@ MobileNets 使用两个超参数来帮助控制精度和速度之间的折衷,
* **宽度倍增器**:通过统一减少整个网络中使用的滤波器数量,控制深度卷积精度
* **分辨率倍增器**:只需将输入图像缩小到不同大小
# 有关 MobileNets 的更多信息
# MobileNets 的更多信息
对于任何神经网络设计,MobileNets 都具有一些最佳的精度,速度和参数比率。
......
此差异已折叠。
......@@ -11,7 +11,7 @@
本章涵盖的主要主题如下:
* 使用来自另一个训练过的模型的权重预先初始化一个模型
* 在需要时使用 TensorFlow 加载模型并冻结/解冻
* 在需要时使用 TensorFlow 加载模型并冻结/解冻层
# 什么时候?
......@@ -108,9 +108,9 @@ class CAE_CNN_Encoder(object):
return self.__x_image
```
# 选择
# 选择层
一旦定义了模型`model = CAE_CNN_Encoder` `()`,选择将要使用预训练权重初始化的层就很重要。 请注意,两个网络的结构(要初始化的网络和提供训练后的权重的网络)必须相同。 因此,例如,以下代码片段将选择名称为`convs``fc`的所有层:
一旦定义了模型`model = CAE_CNN_Encoder` `()`,选择将要使用预训练权重初始化的层就很重要。 请注意,两个网络的结构(要初始化的网络和提供训练后的权重的网络)必须相同。 因此,例如,以下代码片段将选择名称为`convs``fc`的所有层:
```py
from models import CAE_CNN_Encoder
......@@ -133,7 +133,7 @@ list_fc_linear = [v for v in tf.global_variables() if "fc" in v.name or "output"
<tf.Variable 'logits/bias:0' shape=(10,) dtype=float32_ref>]
```
将定义图的层分为卷积和完全连接两个列表后,您将使用`tf.Train.Saver`加载所需的权重。 首先,我们需要创建一个保存器对象,将要从检查点加载的变量列表作为输入,如下所示:
将定义图的层分为卷积和完全连接两个列表后,您将使用`tf.Train.Saver`加载所需的权重。 首先,我们需要创建一个保存器对象,将要从检查点加载的变量列表作为输入,如下所示:
```py
# Define the saver object to load only the conv variables
......@@ -157,15 +157,15 @@ saver = tf.train.Saver()
请注意,调用`restore`会覆盖`global_variables_initializer`,所有选定的权重都将替换为检查点的权重。
# 仅训练一些层
# 仅训练一些层
迁移学习的另一个重要部分是冻结不需要训练的图层的权重,同时允许对某些图层(通常是最后一层)进行训练。 在 TensorFlow 中,我们可以仅将要优化的层传递给求解器(在此示例中,仅将 FC 层传递给):
迁移学习的另一个重要部分是冻结不需要训练的层的权重,同时允许对某些层(通常是最后一层)进行训练。 在 TensorFlow 中,我们可以仅将要优化的层传递给求解器(在此示例中,仅将 FC 层传递给):
```py
train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss, var_list=list_fc_linear)
```
# 完整资料
# 完整代码
在此示例中,我们将从 MNIST 卷积自编码器示例中加载权重。 我们将仅恢复编码器部分的权重,冻结卷积层,并训练 FC 层以执行数字分类:
......
......@@ -24,7 +24,7 @@
8. 将您的数据集分为训练,开发和测试集
9. 评估模型
# 资料准备
# 数据准备
所有机器学习算法的骨干都是数据。 机器学习算法学习的一切都来自数据。 因此,至关重要的是向算法提供代表问题陈述的正确数据。 就像已经看到的那样,深度学习特别需要大量数据用于训练模型。 有时我们可以说一定数量的数据足以解决问题,但是却永远不够! 多多益善。 能够正确训练的模型的复杂度与训练模型上的数据量成正比。 有限的数据将为该问题的模型体系结构选择设定上限。 在考虑可用数据量时,还值得注意的是,其中一部分也需要用于验证和测试目的。
......@@ -125,7 +125,7 @@ ML 基本配方
![](img/3b7eb077-6c15-4a77-989a-40b12e4b70db.png)
# 资料不平衡
# 数据不平衡
我们已经看到了数据表示和分布在解决偏差和方差问题中的重要性。 我们遇到的另一个相关问题是分类任务中各个类之间的数据分配不均。 这称为数据不平衡。 例如,如果我们有一个二进制分类问题,并且其中一个类别有 50000 张图像,而另一个类别只有 1000 张图像,这可能会导致训练算法的性能出现巨大问题。 我们必须通过以下方法解决数据不平衡的问题:
......@@ -135,13 +135,13 @@ ML 基本配方
# 查看您的效果指标
分类准确性不是一个很好的衡量标准,尤其是当我们的数据不平衡时。 这种准确性将更倾向于具有更多数据的类。 有许多良好的性能评估指标可以真实地描述算法的执行方式,例如混淆矩阵,**受试者工作特性曲线**(ROC),**精确回**(PR)曲线和 F1 分数。 这些将在本章稍后详细说明。
分类准确性不是一个很好的衡量标准,尤其是当我们的数据不平衡时。 这种准确性将更倾向于具有更多数据的类。 有许多良好的性能评估指标可以真实地描述算法的执行方式,例如混淆矩阵,**受试者工作特性曲线**(ROC),**精确回**(PR)曲线和 F1 分数。 这些将在本章稍后详细说明。
# 数据综合/扩充
# 数据综合/增强
在无法从其他资源收集数据,数据集太小或收集的数据不能很好地表示的情况下,我们需要以某种方式自行生成数据。 这称为数据增强。 智能生成的数据可以解决许多问题,包括数据集不平衡,训练数据不足和过拟合。
数据扩充通常是作为输入数据管道的一部分来完成的,该管道在训练时为模型提供数据。 随机地,而不是提供原始训练图像,您将应用一些增强来更改它。 有很多方法可以进行数据扩充,但是一些示例是:
数据扩充通常是作为输入数据流水线的一部分来完成的,该流水线在训练时为模型提供数据。 随机地,而不是提供原始训练图像,您将应用一些增强来更改它。 有很多方法可以进行数据扩充,但是一些示例是:
* 增加噪音
* 应用几何变换
......@@ -166,7 +166,7 @@ Tensorflow 已经具有其损失函数,并内置了加权选项:
例如,如果您尝试对 A,B,C 三个类别进行分类,其中 A 为 10%,B 为 45%,C 为 45%,则可以将`tf.losses.sparse_softmax_cross_entropy`用于以下权重:`[1.0, 0.3, 0.3]`
# 评指标
# 评指标
在为模型选择评估指标时,我们还需要小心。 假设对于狗/非狗分类问题,我们有两种算法的准确度分别为 98% 和 96%。 乍一看,这些算法看起来都具有相似的性能。 让我们记住,分类准确度定义为做出的正确预测数除以做出的预测总数。 换句话说,真阳性(TP)和真阴性(TN)预测数除以预测总数。 但是,可能出现的情况是,随着狗图像的出现,我们还会得到大量被错误分类为狗的背景或类似外观的物体,通常称为假阳性(FP)。 另一个不良行为可能是许多狗图像被错误分类为负面或假阴性(FN)。 显然,根据定义,分类准确性不能捕获误报或误报的概念。 因此,需要更好的评估指标。
......@@ -341,7 +341,7 @@ class CAE_CNN_Encoder(object):
return self.__x_image
```
# CNN 创建食谱
# CNN 创建秘籍
以下几点基于我们在训练神经网络方面的经验以及该领域研究人员认为的当前最佳实践。 希望如果您需要从头开始设计自己的 CNN 架构,他们将为您提供帮助。 但是,在尝试设计自己的 CNN 之前,您应该查看其他现成的体系结构以从中学习,并检查它们是否已经为您完成了工作。
......
......@@ -34,7 +34,7 @@
我们可以根据需要使用几种不同的格式来存储数据,例如 HDF5 或 LMDB。 但是,当我们使用 TensorFlow 时,我们将继续使用其自己的内置格式 TFRecords。 TFRecords 是 TensorFlow 自己的标准文件格式,用于存储数据。 它是一种二进制文件格式,提供对其内容的顺序访问。 它足够灵活,可以存储复杂的数据集和标签以及我们可能想要的任何元数据。
# 制作 TFRecord
# 创建 TFRecord
在开始之前,让我们分解一下 TFRecord 的工作方式。 打开 TFRecord 文件进行写入后,创建一个称为`Example`的内容。 这只是一个协议缓冲区,我们将使用它填充要保存在其中的所有数据。 在示例中,我们将数据存储在`Feature`中。 功能是描述示例中数据的一种方式。 功能可以是以下三种类型之一:字节列表,浮点列表或`int64`列表。 将所有数据放入功能部件并将它们写入示例缓冲区后,我们会将整个协议缓冲区序列化为字符串,然后将其写入 TFRecord 文件。
......@@ -82,13 +82,13 @@ for index in range(len(labels)):
为了允许我们随机播放数据,我们可以做的一件事是通过创建多个 TFRecord 文件并将数据散布到这些多个文件中来*分片*我们的数据。 这样,我们可以在每个纪元处重新整理加载 TFRecord 文件的顺序,因此我们在训练时将为我们有效地整理数据。 每 100 万张图像需要 1000 个碎片,这是可以遵循的良好基准。
在下一节中,我们将看到如何使用 TFRecords 建立有效的数据馈送管道
在下一节中,我们将看到如何使用 TFRecords 建立有效的数据馈送流水线
# 建立高效的管道
# 建立高效的流水线
当我们处理较小的数据集时,仅将整个数据集加载到计算机内存中就足够了。 如果您的数据集足够小,这很简单并且可以正常工作; 但是,在很多时候,情况并非如此。 现在我们将研究如何克服这个问题。
为了避免一次加载所有数据,我们将需要创建一个数据管道以将我们的训练数据馈入模型。 除其他事项外,该管道将负责从存储中加载一批元素,对数据进行预处理,最后将数据提供给我们的模型。 幸运的是,这一切都可以使用 TensorFlow 数据 API 轻松完成。
为了避免一次加载所有数据,我们将需要创建一个数据流水线以将我们的训练数据馈入模型。 除其他事项外,该流水线将负责从存储中加载一批元素,对数据进行预处理,最后将数据提供给我们的模型。 幸运的是,这一切都可以使用 TensorFlow 数据 API 轻松完成。
对于这些示例,我们将假定已将数据保存到多个(在本例中为两个)TFRecord 文件中,如先前所述。 如果您有两个以上,则没有区别; 您只需在设置内容时包括所有名称即可。
......@@ -126,7 +126,7 @@ return image, label
train_dataset = train_dataset.map(decode_tfrec, num_parallel_calls=4)
```
# 并行调用地图转换
# 映射转换的并行调用
默认情况下,您在数据集上调用的任何地图转换都仅作用于数据集的单个元素,并且将按顺序处理元素。 要加快速度并使用所有 CPU 功能,最简单的方法是将`num_parallel_calls`参数设置为可用的 CPU 内核数。 这样,我们就不会浪费任何可用的 CPU 能力。 但是,警告您不要将其设置为高于可用内核的数量,因为由于调度效率低下,这实际上可能会降低性能。
......@@ -140,17 +140,17 @@ train_dataset = train_dataset.map(decode_tfrec, num_parallel_calls=4) # Decode
# 批量
您希望在管道末尾做的最后一件事是生成一批准备发送到 GPU 进行训练的数据。 这可以通过批量方法简单地完成,并传入所需的批量大小:
您希望在流水线末尾做的最后一件事是生成一批准备发送到 GPU 进行训练的数据。 这可以通过批量方法简单地完成,并传入所需的批量大小:
```py
train_dataset = train_dataset.batch(128) # Take a batch of 128 from the dataset.
```
当试图使我们的管道尽可能高效时,批次的大小是一个重要的参数。 尽可能大可能并不总是最好的。 例如,如果您的图像上有很多预处理步骤,那么当 CPU 对大量图像进行预处理时,GPU 可能会处于空闲状态。
当试图使我们的流水线尽可能高效时,批次的大小是一个重要的参数。 尽可能大可能并不总是最好的。 例如,如果您的图像上有很多预处理步骤,那么当 CPU 对大量图像进行预处理时,GPU 可能会处于空闲状态。
# 预取
我们能够建立有效数据管道的另一种方法是始终准备好一批数据准备发送到 GPU。 理想情况下,在训练模型时,我们希望 GPU 的使用率始终保持在 100%。 这样,我们可以最大程度地利用昂贵的硬件,该硬件可以在训练时有效地计算前进和后退的传球次数。
我们能够建立有效数据流水线的另一种方法是始终准备好一批数据准备发送到 GPU。 理想情况下,在训练模型时,我们希望 GPU 的使用率始终保持在 100%。 这样,我们可以最大程度地利用昂贵的硬件,该硬件可以在训练时有效地计算前进和后退的传球次数。
为此,我们需要 CPU 加载并准备一批图像,以准备在向前和向后传递模型的过程中传递给 GPU。 幸运的是,在收集批量之后,我们可以使用简单的预取转换轻松完成此操作,如下所示:
......@@ -158,13 +158,13 @@ train_dataset = train_dataset.batch(128) # Take a batch of 128 from the dataset
train_dataset= train_dataset.batch(128).prefetch(1)
```
使用预取将确保我们的数据管道在进行训练时为我们准备一整批数据,准备将其加载到 GPU 中以进行下一次迭代。 这样做可以确保我们的管道在等待一批批次收集之前不会减慢速度,并且如果获取批次所需的时间少于模型的前后传递时间,那么我们的管道将尽可能高效。
使用预取将确保我们的数据流水线在进行训练时为我们准备一整批数据,准备将其加载到 GPU 中以进行下一次迭代。 这样做可以确保我们的流水线在等待一批批次收集之前不会减慢速度,并且如果获取批次所需的时间少于模型的前后传递时间,那么我们的流水线将尽可能高效。
要清楚的是,此处使用`prefetch(1)`表示我们`prefetch`整批数据。 这就是为什么我们将批量作为流水线的最后一步,并在此处使用预取功能,因为这样做最有效。
# 追踪图
# 追踪图
TensorFlow 提供了一种很好的方式来分析并查看整个图形通过其时间轴跟踪工具执行所需的时间。 这是查看图表的哪些部分正在减慢训练速度并发现数据管道中任何低效率的好工具。
TensorFlow 提供了一种很好的方式来分析并查看整个图形通过其时间轴跟踪工具执行所需的时间。 这是查看图表的哪些部分正在减慢训练速度并发现数据流水线中任何低效率的好工具。
我们将从为您提供如何跟踪图形的示例开始。 这非常简单:您只需在常规代码中添加几行,就会生成一个 JSON 文件,我们可以将该文件加载到 Google Chrome 浏览器中,以查看图形执行的所有时间:
......@@ -192,7 +192,7 @@ with tf.Session() as sess:
现在将显示跟踪图形的结果。 查看此内容将告诉您图形的每个部分执行所需的时间。 您应该特别注意存在大块空白的地方。 这些空白表示设备(例如您的 GPU)正坐在那里等待数据,以便它们可以执行计算。 您应该尝试通过优化数据馈送方式来消除这些问题。
但是请注意,您的管道可能已完全优化,但是您没有 CPU 周期来足够快地处理管道。 检查您的 CPU 使用情况,看看是否是这种情况。
但是请注意,您的流水线可能已完全优化,但是您没有 CPU 周期来足够快地处理流水线。 检查您的 CPU 使用情况,看看是否是这种情况。
# TensorFlow 中的分布式计算
......@@ -305,7 +305,7 @@ CREATE INDEX idxAngle ON tb_drive (wheel_angle);​
CREATE INDEX idxAcc ON tb_drive (acc);
```
# 用 Python 进行查询
# 将 Python 用于查询
首先,在开始玩之前,我们需要安装 Python 驱动程序`pip install cassandra-driver​`; 以下代码片段仅列出了 Cassandra 集群中表的内容:
......@@ -372,7 +372,7 @@ nodetool -h localhost snapshot mydb​
* **弹性计算云****EC2**
* S3
* 贤者
* SageMaker
# EC2
......@@ -394,7 +394,7 @@ nodetool -h localhost snapshot mydb​
可用端口
# 哪一个
# AMI
这是 AWS 中最酷的功能之一,它使您可以从所有数据和已安装的工具(从一个服务器实例到另一个服务器实例)创建映像。 因此,您可以仅使用所有工具,驱动程序等配置一台服务器,以后再使用具有相同映像的另一台服务器:
......@@ -412,7 +412,7 @@ Amazon S3 是存储系统,您可以在其中从常规 HTTP 请求上传/下载
S3 系统可以进行公共配置,因此人们可以从任何地方下载/上传内容。
# 贤者
# SageMaker
SageMaker 提供了一种在云中训练/部署机器学习模型的简便方法。 SageMaker 将提供 Jupyter 笔记本,您可以在其中可视化/训练模型并直接连接到 S3 中的数据(提供了访问 S3 的 API):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册