TensorFlow 2.0 教程 01:基本图形分类

TensorFlow 2 现在已经上线了!

TensorFlow 2现在是实时的!本教程将指导您使用深度学习构建一个简单的CIFAR-10图像分类器。在本教程中,我们将:

定义一个模型

设置一个数据管道

训练模型

使用多GPU加速训练速度

为监控过程/更新学习计划添加回调。

本教程中的代码可以在这里找到。(地址:https://github.com/lambdal/TensorFlow2-tutorial/tree/master/01-basic-image-classification )

定义模型

TensorFlow 2使用Keras作为其高级API。Keras提供了两种定义模型的方法:顺序式API和函数式API。

使用Keras的顺序式API定义一个模型

使用Keras的函数式API定义相同的模型

顺序式API与函数式API

这些API之间的主要区别是:顺序式API要求其第一层使用input_shape提供,而函数式API要求其第一层是tf.keras.layers.Input,并且需要在最后调用tf.keras.models.Model构造器。

顺序式API更简洁,而函数式API更灵活,因为它允许一个模型是非顺序式的。例如,要在ResNet中具有跳过连接。本教程采用TensorFlow官方的ResNet的Keras实现,它使用了函数式API。

设置一个数据管道

我们现在已经定义了一个模型。为了训练这个模型,我们需要一个数据管道来向它提供标签化的训练数据。该数据管道执行以下任务:

加载: 将数据集(例如图像和标签)从存储器复制到程序的内存中。

预处理:转换数据集。例如,在图像分类中,我们可能会调整大小、白化、洗牌或批处理图像。

供给数据: 从一个数据集中获取例子并传入到一个训练循环中。

从存储器加载数据

首先,我们将CIFAR-10从存储器加载到numpy ndarrays:

注意:

当您第一次调用keras.datasets.cifar10.load_data时,CIFAR-10将会被从网络下载到 ~/.keras/datasets/cifar-10-batches-py.tar.gz。后续的调用就不涉及到网络了。

x 表示尺寸为32 x 32 x 3的50000个图像 (宽度、高度和三个RGB通道)。

y表示这50000个图像的标签。

理论上来说,我们可以简单地将这些原始numpy.ndarray对象提供到一个训练循环中,并将这称为一个数据管道。然而,为了获得更高的模型精度,我们需要对数据进行预处理(即在使用之前对其执行某些转换)。为此,我们利用了Tensorflow的Dataset类。

tf.data.Dataset 类

TensorFlow的Dataset类有两个主要用途:

它充当一个保存训练数据的容器。

它可以被用来在训练数据的元素上执行某些变换。

我们按照以下方式来实例化一个表示CIFAR-10数据集的tensorflow.data.Dataset对象:

在训练过程中,存储在train_dataset中的CIFAR-10训练示例将通过take()迭代器进行访问:

实际上,我们没有执行任何数据预处理过程。调用take()只简单地发送出原始CIFAR-10图像;前20张图像如下:

数据扩充

扩充经常用于“膨胀”训练数据集,这可以提高泛化性能。

让我们通过对每个图像执行以下步骤来扩充CIFAR-10数据集:

使用一个四像素的黑色边框填充图像。

从填充图像中随机裁剪一个32×32的区域。

抛硬币来决定图像是否应该被水平翻转。

我们首先定义一个函数,给定一个图像,执行上面的步骤1-3:

接下来,我们调用方法map;这个调用会返回一个新的Dataset对象,该对象包含将CIFAR-10中的每个图像传递到 augmentation中的结果。这个新对象将以原始顺序来发送转换后的图像:

以下是扩充后的前20张图像:

注: 扩充只应用于训练集;在推理过程中应用扩充将导致不确定的预测和验证分数。

随机打乱

我们随机打乱数据集。TensorFlow Dataset有一个shuffle方法,可以按照以下方式来将它链接到我们的扩充过程中:

要获得完美的随机打乱效果,buffer_size应该大于或等于数据集的大小(在本例中为50,000);对于大型数据集,这是不可能的。

以下是随机打乱后的Dataset中的20张图像:

规范化

将数据规范化是一种常见的做法。在这里,我们定义一个函数,线性缩放每个图像使具有零均值和单位方差:

接下来,我们将它与我们的扩充和随机打乱操作链接起来:

数据batching

最后,我们对数据集进行batch操作。我们将drop_remainder设置为True以删除足够多的训练示例,以便训练集的大小可以被batch_size整除。

我们现在有了一个完整的数据管道。现在我们就可以开始训练过程了。

训练模型

Keras模型需要在训练之前进行编译。编译过程本质上定义了三个东西:损失函数、优化器和评估指标:

注意,这里我们使用了sparse_categorical_crossentropy和 sparse_categorical_accuracy,因为每个标签都由一个整数(类的索引)表示。如果一个独热编码向量表示每个标签,那么我们应该使用categorical_crossentropy 和 categorical_accuracy。

Keras使用fit API来训练模型。我们可以选择在每个validation_freq训练epoch(迭代)中在一个验证数据集上来测试模型。

注意,我们使用测试数据集只是为了进行验证,因为CIFAR-10本身并不提供验证集。模型合理性验证应该在从训练数据集中分割出来的一组数据上进行。

注意,在本例中,fit函数接受了TensorFlow数据集对象(train_dataset和 test_dataset)。如前所述,它还可以接受numpy的ndarrays作为输入。使用数组的缺点是缺乏在数据集应用转换的灵活性。

要对模型进行评估,我们可以使用测试数据集调用evaluate方法:

多GPU

到目前为止,我们已经展示了如何使用TensorFlow的Dataset API来创建一个数据管道,以及如何使用Keras API来定义模型并进行训练和评估。下一步是让代码使用多个GPU来运行。

实际上,Tensorflow 2已经使您可以很容易地将您的单GPU实现转换成使用多个GPU运行。您所需要做的就是定义一个分布策略,并在策略范围内创建模型:

我们这里使用的是MirroredStrategy,它支持在一台机器上的多个GPU上执行同步的分布式训练。默认情况下,它使用NVIDIA NCCL作为多gpu归约实现。

注意,您将会想要基于您正在使用的GPU数量来使用数据管道的batch方法来扩展批尺寸。

添加回调

通常我们需要在训练期间执行一些自定义操作。例如,您可能希望在训练期间记录统计信息以用于调试或优化;执行一个学习速率时间表来提高训练效率;或者保存筛选器组聚集时的可视快照。在TensorFlow 2中,您可以使用回调特性来在训练期间实现自定义事件。

Tensorboard

TensorBoard主要用于在训练过程中记录和可视化信息。它非常适合于检查模型的性能。Tensorboard支持是通过tensorflow.keras.callbacks.TensorBoard回调函数提供的:

在上面的例子中,我们首先创建了一个TensorBoard回调,用于记录每个训练步骤的数据(通过update_freq=batch),然后将这个回调附加到fit函数。TensorFlow将会生成tfevents文件,可以使用TensorBoard将其可视化。例如,这是训练过程中分类精度的可视化(蓝色表示训练精度,红色表示验证精度):

学习速率时间表

通常,我们希望随着训练的进行能对学习速率有良好的控制。一个自定义学习速率时间表可以作为回调函数来实现。在这里,我们创建了一个自定义的schedule函数,它使用一个step函数(在第30个epoch和第45个epoch)来降低学习速率。这个schedule被转换成一个keras.callbacks.LearningRateScheduler并附加到fit函数。

这些是一个60个epoch的自定义学习速率的统计信息:

总结

本教程以图像分类为例,介绍了TensorFlow 2.0的基础知识。我们覆盖了:

带有TensorFlow 2的数据集API的数据管道

使用Keras (TensorFlow 2的官方高级API)训练、评估、保存和恢复模型

带有分布式策略的多GPU

带有回调的自定义训练

下面是本教程的完整代码。您还可以使用此TensorFlow 2.0教程代码仓库来复制我们有关TensorFlow 2.0的教程。


https://www.jianshu.com/p/b6c17c7ed8ff

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论