Tic商业评论

关注微信公众号【站长自定义模块】,定时推送前沿、专业、深度的商业资讯。

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

  • QQ空间
  • 回复
  • 收藏

TensorFlow2 和 Keras

lijingle 深度学习框架 2021-12-16 21:43 1890人围观

TensorFlow的早期版本存在严重的危机。如此多的API都是被分别提出。TensorFlow 2(TF2)采用Keras API改变了局面。更重要的是,API变得对程序员更友好,更容易跟踪,也不那么单调乏味。本文我们将展示如何使用此API构建深度学习模型。

带有CIFAR10的Sequential Model 
KerasAPI提供了一个高级内置类“models.Sequential”来创建公共深度学习(DL)模型。本节,我们将训练一个CIFAR10分类器并从中进行预测。下面代码的第一部分准备用于训练的CIFAR10数据集。然后,我们构建一个CNN分类器,并配置一个使用Adam优化器和交叉熵损失函数(model.compile)的训练。我们还将配置参数以便更好地训练出数据的准确性。最后,我们调用“model.fit”来训练返回包含性能指标的历史记录的模型。代码非常简单。


model.Sequential是一种stacked模型,其中每一层将前一层的输出作为输入。每一层都有一个输入和一个输出张量——张量是一个TF类,包含标量、向量或n维数组。即使有这个限制,这个模型也涵盖了大多数基本的深度学习模型。为了再次检查代码,我们可以使用model.summary可显示模型的结构摘要。例如,我们模型中的第一层是conv2d层,它输出一个形状为(None,30,30,32)的张量。None表示任何批量大小,该层的输出空间尺寸为30×30,有32个输出通道。


有时,我们可以打印出模型的概要,而不是在代码完全完成时,去调试代码(例如,在添加dense层之前调用summary)。这能使我们能够逐步排除模型问题。

为了验证训练进度,我们可以使用从model.fit返回的历史记录绘制训练和验证精度。


我们还可以使用测试集评估模型精度,并打印出其精度。


最后,下面的代码演示了如何进行预测。我们称之为model(images),其中图像包含25个测试图像。


有时,我们希望输出是概率值,而不是logit score。这里,我们创建另一个顺序模型,第一层为原始模型,第二层(输出)为softmax层。


作为演示代码的最后一步,我们用下图代码将图像和预测可视化。


Callable

如前所示,可以通过调用以图像作为输入的模型来进行预测。


i.e. model is callable:我们使用模型中的模型实例(一些输入)进行调用。


实际上,层也是可调用的。我们可以制作测试输入并调用层对操作结果进行快速跟踪。


带有Sequential模型的MNIST分类器

下面的代码是一个MNIT分类器。在组成Sequential模型时,它的语法更加精简。但它在跟踪早期开发过程中的问题时不够灵活。该模型包括一个层,用于将输入值重新缩放到0到1.0的范围,并将输入维度从(28,28)reshape为(28,28,1)-CNN层期望的格式。


我们可以在不加载真实数据的情况下快速测试模型。在下面的示例中,我们在拟合模型和进行预测时生成随机数据。在TF中,我们可以传递Ndaray或TF张量作为数据。


避免过拟合

为了避免过度拟合,我们可以在模型中添加正则化和dropout。


模型编译选项

在本节中,我们将演示配置训练选项。

优化器学习率

对于某些优化器,我们可以自定义创建学习率衰减,如下所示:


度量指标

compile中的metrics参数包含该模型的metrics列表。训练结束后, model.fit返回。


以下是一些可用的内置选项。


注意:不使用内置类,我们还可以将许多参数作为字符串传递(如:"sparse_categorical_accuracy")。


自定义cost函数

或者,我们可以定义一个自定义损失函数,如下面的MSE(均方误差)。


model.fit

接下来,我们将测试训练模型的其他选项。

验证集划分

我们可以保留一定百分比的训练样本进行验证,比如说最后x%的训练样本。要使用此选项,训练数据必须是ndarray或张量。


或者,我们可以为model.fit准备单独的验证数据集。


要从训练数据集里创建验证数据集,我们可以“take”部分训练数据进行验证,并使用“skip”将其余数据用于训练。


class weights/sample weights (optional)

在分类中,有些情况下我们希望在特定的类别中更加准确。下面的代码将一个类与用于损失函数的权重相关联。在本例中,类别5的权重较大,因此我们可以更准确地对其进行分类。


在某些情况下,我们希望权重与样本关联,而不是与类关联。因此,我们可以更加关注特定的样本集。


组合模型

通常,我们不会构建一个全新的模型。相反,我们可以用现有模型或预先训练的模型组成一个模型,然后添加新的层。例如,下面的代码在预定义模型之后附加一个FC层。


在我们的第二个示例中,它使用来自TensorFlow Hub(TF Hub)的预先训练的MobileNet模型进行特征提取。使用out-of-the-box模型进行特征提取是一种常见做法。然后我们添加新的dense层作为分类的头部。


input, layer, 和 output

在目标检测中,我们通常以不同的分辨率从多个层中提取特征进行预测。因此,一个模型通常有多个输出,特别是在目标检测中使用的特征提取器。但Sequential模型只有一个输出张量。它使用 initial_model.input作为输入,并使用initial_model中的所有三层作为输出。因此,第32行中的“特征”是一个包含3个张量的列表,每个张量保存卷积层的输出。


或者我们可以通过只输出选定的卷积层来提高选择性。


稍后我们将回到如何使用这些输出。

Sequential Models 概述

Sequential Models允许我们构建通用但不太复杂的模型。这是一个堆叠模型,其中一层接着另一层。我们使用最后一层的输出作为下一层的输入。每一层都有一个输入张量和一个输出张量。

说明

本文没有采用代码的方式进行书写,而是图片的方式,这是可以让读者自行去修改调试代码,而不是直接copy过来运行,这样学不到东西的。


函数API

接下来,我们探讨函数API,与Sequential model相比,它在建模模型时提供了更大的灵活性。例如,它允许多个输入和输出、共享参数和跳过连接。它还促进了层的可重用性。

我们使用函数API重新创建MNIST分类器。我们从定义输入形状的keras.input开始。然后在层之间创建必要的数据流。在最后一步中,我们使用keras创建了一个分类器模型。定义了输入和输出的模型。


我们再举一个提取特征的例子。


model.compile, model.fit, model.evaluate 和 model.predict 函数API的预测与 Sequential model的工作方式相同。为了完整起见,下面是训练和验证分类器模型的代码。与 Sequential model相同。


函数API允许我们轻松共享层。从下面的第17行到第25行,我们使用函数API构建编码器模型。Autoencoder是一个编码器,后跟一个解码器。在编码器流已经编程的情况下,我们可以继续从编码器输出(编码器输出)构建流。我们从第28行到第33行添加更多层,并构建自动编码器。


有时,我们希望将现有模型组合在一起以创建新模型。在下面的代码中,自动编码器由单独构建的编码器和解码器模型组成。


由于模型和层是可调用的,我们可以通过使用不同的模型组合数据流来定义新的模型(下面的第40行和第41行)。我们甚至可以添加新层,比如第39行和第42行之间的层。


作为一个思考练习,让我们看看如何将分类器头添加到输出多个张量的特征提取器中。从第17行到第34行,我们创建了一个具有两个输出的提取器—feature_3和feature_4 layer。


然后,我们提取下面第37行中““input”的特征。然后,我们使用两个独立的分支来处理这两个特征张量。最后,我们将它们连接在一起,然后是一个dense层来对输入进行分类。


模型类

我们可以使用函数API创建自定义模型类。这将所有的层代码放入面向对象的设计中。在前面的部分中,跟踪层的输出并不容易。但是在下面的自定义模型中,我们可以将换行符放在callable中以跟踪输出。(注意:@tf.function注释将禁用此功能。)这是在自定义模型类对象中包装层和模型的一个主要好处。


复杂模型

让我们用函数API构建更复杂的模型,这些模型通常用于深度学习。

多输入和/或多输出

在这个模型中,我们采用3个输入张量——一个是标题,一个是正文,一个是标签。该模型预测了两个值-部门类别和优先级。


通过两个输出,我们还配置了两个损失函数,一个用于优先级,一个用于部门。我们还可以使用下面的loss_weights参数来配置用于反向传播的相应权重。


我们还可以为不同的输出应用不同的衡量指标。在下面的示例中,名为“score_output”和“class_output”的输出使用两种不同的损失和衡量指标。


Skip 连接

Skip连接是许多state-of-the-art模型的必备功能。一个层的输入来自其最后层和前些层。在本例中,我们使用layers.add创建Skip连接。


这里是一个Skip连接,后面是两个CNN层和一个Skip连接。为了便于说明,我们调用 summary来查看其连接。例如,conv2d_4层从conv2d_3和max_poolig2d层获取输入。


共享层

模型可能具有共享相同设计和权重的层。例如,下面的两个功能特征提取具有相同的体系结构并共享相同的权重。


对于下面的代码,embedding层由两个不同的输入张量共享。


基于预训练模型和多层的特征提取

如前所述,在目标检测中,我们使用不同分辨率的多层特征来预测目标。为了演示,让我们使用vgg19模型来提取特征。下面的示例使用vgg19中的所有层作为提取的特征。


但实际上,我们只使用选定的层。


让我们用一个图像分割网络来阐述这个想法,该网络生成一个mask来分割一个对象。


下图是FPN模型(特征金字塔网络)的一部分。它包含一个具有逐渐减小的空间维度的下采样网络(黄色的)和一个用于重建空间信息的上采样网络。Skip连接以相应的空间分辨率将下采样层连接到上采样层。这允许上采样层从其上采样数据和下采样层提取的内容特征构建空间信息。


这里的对象分割使用了类似的概念。它使用预先训练好的MobileNet v2作为下采样层来提取内容特征。我们将导出5层连接到上采样层。


然后,我们创建一个unet模型,其中包含该下采样层和5个上采样层(4个实现为pix2pix.upsample,1个实现为转置卷积)。它还具有4个skip连接,连接具有各自空间分辨率的下采样层和上采样层输出。


这是模型设计。


pix2pix.upsample由转置卷积、batch normalization, dropout, 和 ReLU组成。


Callbacks

方法 model.fit、model.evaluate 和 model.predict 生成我们的应用程序可以执行的生命周期事件,例如在训练批次或时期的开始或结束时

例如,在 epoch 结束时,ModelCheckPoint 确定是否保存模型。 下面的代码使用开箱即用的回调将信息保存到 TensorBoad、保存CheckPoint并提前停止。 这是内置回调的列表。 我们还可以开发自定义回调。


TensorBoard

我们可以使用 tf.keras.metrics 收集统计指标。 下面的“update_state”累积损失指标,稍后用 tf.summary.scalar 记录。 然后可以使用 reset_states 为每个“log_freq”重置这些指标。


然后,我们可以调用 tensorboard来分析日志目录。


Tensor 和 NumPy 数组

Eager执行适用于 Numpy。 NumPy 操作接受 tf.Tensor 作为参数,许多 TF 操作可以用 NumPy ndarry 并首先将它们转换为 tf.Tensor。 我们还可以使用 tf.Tensor.numpy 将张量转换为 NumPy ndarray。 该代码示例演示了为简单测试创建Tensor的方法以及如何对其进行索引。


稀疏张量(可选)


TF操作

对于最后一部分,我们将快速演示 TensorFlow 应用程序中使用的一些常见 API。 代码非常简单,我们将通过代码注释进行解释。

tf.expand_dims


tf.reshape


tf.squeeze


tf.cast


tf.stack


tf.concat


tf.split


tf.reduce_sum


tf.tile


tf.random.uniform


tf.random.normal


本文先到此


路过

雷人

握手

鲜花

鸡蛋
我有话说......
电话咨询: 135xxxxxxx
关注微信