TensorFlow 研讨会(二)
原文:
annas-archive.org/md5/92a4018e7ab653973d73d2eb5915e580译者:飞龙
第三章:3. TensorFlow 开发
概述
TensorFlow 提供了许多资源,以创建高效的工作流程,帮助开发数据科学和机器学习应用程序。在本章中,你将学习如何使用 TensorBoard 来可视化 TensorFlow 图和操作,如何使用 TensorFlow Hub 来访问一个用户社区(这是一个非常好的预训练模型资源),以及如何使用 Google Colab,这是一个用于与他人共同开发代码的协作环境。你将使用这些工具通过最大化计算资源、转移预训练模型中的知识以及可视化模型构建过程的各个方面来加速开发。
介绍
在上一章中,你学习了如何加载和处理各种数据类型,以便在 TensorFlow 建模中使用。这包括来自 CSV 文件的表格数据、图像数据、文本数据和音频文件。到本章结束时,你应该能够处理所有这些数据类型,并从中生成数值张量,这些张量可以作为模型训练的输入。
在本章中,你将学习到有助于模型构建的 TensorFlow 资源,并帮助你创建高效的机器学习算法。你将探索实践者可以利用的实用资源,包括 TensorBoard、TensorFlow Hub 和 Google Colab。TensorBoard 是一个互动平台,提供了在 TensorFlow 开发过程中生成的计算图和数据的可视化表示。该平台解决了机器学习中常见的可视化各种数据类型的问题。该可视化工具包可以在模型构建过程中绘制模型评估指标,展示图像,播放音频数据,并执行许多其他任务,这些任务通常需要编写自定义函数。TensorBoard 提供了简单的日志写入函数,日志可以在浏览器窗口中进行可视化。
TensorFlow Hub 是一个开源库,包含了预训练的机器学习模型,代码库对所有人开放,供用户用于自己的应用程序并进行修改。用户可以通过专门的库将模型直接导入代码,并可以在tfhub.dev/上查看。TensorFlow Hub 允许用户使用由领域专家创建的最先进的模型,并能显著缩短将预训练模型作为用户模型一部分时的训练时间。
例如,该平台包含了 ResNet-50 模型,这是一个 50 层的人工神经网络(ANN),在 ILSVRC 2015 分类任务中获得了第一名,该任务是将图像分类为 1000 个不同的类别。该网络拥有超过 2300 万个可训练参数,并在超过 1400 万张图像上进行了训练。从头开始在一台普通笔记本电脑上训练该模型,并达到接近 TensorFlow Hub 上预训练模型的准确性,可能需要几天时间。正因如此,利用 TensorFlow Hub 模型可以加速开发进程。
本章中你将了解的最后一个资源是 Google Colab,它是一个在线开发环境,用于在 Google 服务器上执行 Python 代码并创建机器学习算法。该环境甚至可以访问包含图形处理单元(GPUs)和张量处理单元(TPUs)的硬件,可以免费加速模型训练。Google Colab 可通过 colab.research.google.com/ 访问。
Google Colab 解决了设置开发环境的问题,可以创建可以与他人共享的机器学习模型。例如,多名机器学习实践者可以开发相同的模型,并在同一硬件实例上训练该模型,而不需要各自使用自己的资源来运行该实例。顾名思义,该平台促进了机器学习实践者之间的协作。
现在,让我们来探索 TensorBoard,这是一个帮助实践者理解和调试机器学习工作流的工具。
TensorBoard
TensorBoard 是一个用于辅助机器学习实验的可视化工具包。该平台具有仪表板功能,可以可视化数据科学或机器学习实践者可能需要的多种常见数据类型,例如标量值、图像批次和音频文件。虽然这些可视化可以通过其他绘图库创建,例如 matplotlib 或 ggplot,但 TensorBoard 将多种可视化集成在一个易于使用的环境中。此外,创建这些可视化所需的唯一操作是在构建、拟合和评估步骤中记录跟踪信息。TensorBoard 有助于以下任务:
- 可视化模型图以查看和理解模型的架构:
图 3.1:TensorBoard 中模型图和函数的可视化表示
-
查看变量的直方图和分布,并跟踪它们随时间的变化。
-
显示图像、文本和音频数据。例如,以下图显示了来自 Fashion MNIST 数据集的图像(
www.tensorflow.org/datasets/catalog/fashion_mnist):
图 3.2:在 TensorBoard 中查看图像
- 在模型训练过程中绘制模型评估指标随 epoch 变化的图:
图 3.3:在 TensorBoard 中绘制模型评估指标
- 用于可视化嵌入向量的降维:
图 3.4:在 TensorBoard 中可视化嵌入向量
TensorBoard 从开发过程中写入的日志中创建可视化图像。为了创建日志以可视化图形,需要在开发代码中初始化文件写入对象,并将日志的位置作为参数提供。文件写入对象通常在 Jupyter notebook 或等效开发环境的开始阶段创建,在写入任何日志之前。具体如下:
logdir = 'logs/'
writer = tf.summary.create_file_writer(logdir)
在前面的代码中,设置了写入日志的目录,如果该目录尚不存在,则在运行代码后,工作目录中会自动创建一个新目录。文件写入对象在日志导出时将文件写入日志目录。要开始追踪,必须执行以下代码:
tf.summary.trace_on(graph=True, profiler=True)
前面的命令启动了追踪功能,用于记录从执行命令时开始的计算图。如果没有开启追踪,则不会记录任何内容,因此也无法在 TensorBoard 中可视化。计算图的追踪完成后,可以使用文件写入对象将日志写入日志目录,具体如下:
with writer.as_default():
tf.summary.trace_export(name="my_func_trace",\
step=0, profiler_outdir=logdir)
在写入日志时,需要使用以下参数:
-
name:该参数描述了摘要的名称。 -
step:该参数描述了摘要的单调步长值,如果对象随时间变化不大,可以将其设置为0。 -
profiler_outdir:该参数描述了写入日志的位置,如果在定义文件写入对象时没有提供该参数,则此参数是必需的。
日志写入目录设置完成后,可以通过命令行启动 TensorBoard,使用以下命令传入日志目录作为 logdir 参数:
tensorboard --logdir=./logs
某些版本的 Jupyter Notebooks 允许在笔记本中直接运行 TensorBoard。然而,库依赖关系和冲突常常会阻止 TensorBoard 在笔记本环境中运行,在这种情况下,可以通过命令行在单独的进程中启动 TensorBoard。在本书中,你将使用 TensorFlow 版本 2.6 和 TensorBoard 版本 2.1,并且始终通过命令行启动 TensorBoard。
在第一个练习中,你将学习如何使用 TensorBoard 可视化图计算过程。你将创建一个执行张量乘法的函数,并在 TensorBoard 中可视化计算图。
练习 3.01:使用 TensorBoard 可视化矩阵乘法
在本练习中,你将进行 7x7 矩阵的矩阵乘法运算,使用随机值,并追踪计算图和性能信息。之后,你将使用 TensorBoard 查看计算图。此练习将在 Jupyter Notebook 中进行。启动 TensorBoard 需要在命令行中运行命令,如最后一步所示。
请按照以下步骤操作:
-
打开一个新的 Jupyter Notebook,导入 TensorFlow 库,并设置随机种子以保证结果的可重复性。由于你正在生成随机值,设置种子可以确保每次运行代码时生成的值相同:
import tensorflow as tf tf.random.set_seed(42) -
创建一个
file_writer对象,并设置日志存储目录:logdir = 'logs/' writer = tf.summary.create_file_writer(logdir) -
创建一个 TensorFlow 函数来进行两个矩阵相乘:
@tf.function def my_matmult_func(x, y): result = tf.matmul(x, y) return result -
创建两个形状为
7x7的张量,数据为随机变量:x = tf.random.uniform((7, 7)) y = tf.random.uniform((7, 7)) -
使用 TensorFlow 的
summary类开启图形追踪:tf.summary.trace_on(graph=True, profiler=True) -
将第3 步中创建的函数应用于第4 步中创建的示例张量。接下来,将追踪数据导出到
log目录,并为图形设置name参数以便参考,同时将log目录设置为profiler_outdir参数。step参数表示摘要的单调步长值;如果被追踪的值有变化,该值应非零,并且可以通过该参数指定的步长进行可视化。对于静态对象,例如此处的图形追踪,步长应设置为零:z = my_matmult_func(x, y) with writer.as_default(): tf.summary.trace_export(name="my_func_trace",\ step=0,\ profiler_outdir=logdir) -
最后,使用命令行在当前工作目录下启动 TensorBoard,查看图形的可视化表示。启动 TensorBoard 后,可以通过访问提供的网址在网页浏览器中查看:
tensorboard --logdir=./logs对于在 Windows 上运行的用户,请在 Anaconda 提示符下运行以下命令:
tensorboard --logdir=logs通过运行上述代码,你将能够可视化以下模型图:
图 3.5:在 TensorBoard 中矩阵乘法的可视化表示
在 TensorBoard 中,你可以查看一个张量如何将两个矩阵相乘以生成另一个矩阵。通过选择不同的元素,你可以查看计算图中每个对象的相关信息,具体取决于对象的类型。在这里,你创建了两个张量,命名为 x 和 y,它们由底部的节点表示。通过选择其中一个节点,你可以查看有关张量的属性,包括它的数据类型(float)、用户指定的名称(x 或 y),以及输出节点的名称(MatMul)。这些表示输入张量的节点然后被输入到另一个节点,该节点表示张量乘法过程,标记为 MatMul,它是在 TensorFlow 函数之后的节点。选择该节点后,你可以查看该函数的属性,包括输入参数、输入节点(x 和 y)和输出节点(Identity)。最后两个节点,标记为 Identity 和 identity_RetVal,表示输出张量的创建。
在本次练习中,你使用 TensorBoard 可视化计算图。你创建了一个简单的函数,将两个张量相乘,并通过追踪图并记录结果来记录过程。在记录了计算图之后,你可以通过启动 TensorBoard 并将工具指向日志的存储位置来可视化它。
在第一个活动中,你将练习使用 TensorBoard 可视化一个更复杂的张量转换。实际上,任何张量过程和转换都可以在 TensorBoard 中可视化,前一个练习中演示的过程是创建和编写日志的好指南。
活动 3.01:使用 TensorBoard 可视化张量转换
给定两个形状为5x5x5的张量。你需要创建 TensorFlow 函数来执行张量转换,并查看转换的可视化表示。
你将采取的步骤如下:
-
导入 TensorFlow 库并将随机种子设置为
42。 -
设置日志目录并初始化文件写入对象以写入跟踪。
-
创建一个 TensorFlow 函数,将两个张量相乘,并使用
ones_like函数向结果张量的所有元素加上一个值1,以创建一个与矩阵乘法结果相同形状的张量。然后,对张量的每个值应用sigmoid函数。 -
创建两个形状为
5x5x5的张量。 -
打开图形追踪。
-
将函数应用于这两个张量,并将追踪记录导出到日志目录。
-
在命令行中启动 TensorBoard,并在网页浏览器中查看图形:
图 3.6:TensorBoard 中张量转换的可视化表示
注意
本活动的解决方案可以通过这个链接找到。
然而,TensorBoard 不仅仅用于可视化计算图。通过使用合适的 TensorFlow summary 方法,将图片、标量变量、直方图和分布写入日志目录后,均可在 TensorBoard 中查看。例如,图片可以按照以下方式写入日志:
with file_writer.as_default():
tf.summary.image("Training data", training_images, step=0)
这样做的结果将是在日志目录中添加一个名为 Training data 的文件,其中包含文件写入器写入的图片。可以通过选择标签为 IMAGES 的选项卡在 TensorBoard 中查看这些图片。
同样地,标量变量也可以以如下方式写入日志,以便在 TensorBoard 中查看:
with file_writer.as_default():
tf.summary.scalar('scalar variable', variable, step=0)
音频文件也可以按照以下方式写入日志,以便在 TensorBoard 中播放:
with file_writer.as_default():
tf.summary.audio('audio file', data, sample_rate=44100, \
step=0)
可以通过传入数据如下方式记录直方图:
with file_writer.as_default():
tf.summary.histogram('histogram', data, step=0)
在所有这些写入日志的数据示例中,step 参数被设置为零,因为这是一个必需的参数,不能为 null。将参数设置为零表示该值是静态的,不会随时间变化。每种数据类型将在 TensorBoard 中的不同标签下显示。
在下一个练习中,你将把图片写入 TensorBoard,以便可以直接在平台内查看。使用 TensorBoard,这个过程变得非常简便,而不需要编写自定义代码来查看图片。你可能希望可视化图片批次,以验证标签、检查数据增强过程,或验证图片的整体质量。
练习 3.02:使用 TensorBoard 可视化图片批次
在这个练习中,你将使用 TensorBoard 查看图片批次。你将创建一个文件写入器和一个数据生成器,并将一批图片写入日志文件。最后,你将会在 TensorBoard 中查看这些图片。
注意
你可以在 image_data 文件夹中找到图片:packt.link/1ue46。
按照以下步骤操作:
-
导入 TensorFlow 库和
ImageDataGenerator类:import tensorflow as tf from tensorflow.keras.preprocessing.image import \ ImageDataGenerator -
创建一个
file_writer对象,并设置日志存储的目录:logdir = 'logs/' writer = tf.summary.create_file_writer(logdir) -
初始化一个
ImageDataGenerator对象:train_datagen = ImageDataGenerator(rescale = 1./255) -
使用数据生成器的
flow_from_directory方法创建一个批次图片加载器:batch_size = 25 training_set = train_datagen.flow_from_directory\ ('image_data',\ target_size = (224, 224),\ batch_size = batch_size,\ class_mode = 'binary')注意
确保将路径(高亮部分)更改为系统上目录的位置。如果你是在存储数据集的同一目录下运行 Jupyter notebook,可以直接运行上述代码而无需修改。
-
从第一批图片中取出并使用文件写入器将其写入日志:
with file_writer.as_default(): tf.summary.image("Training data", \ next(training_set)[0], \ max_outputs=batch_size, \ step=0) -
在命令行中启动 TensorBoard 以查看图形的可视化表示。启动 TensorBoard 后,可以通过访问提供的 URL 在 Web 浏览器中查看 TensorBoard。默认的 URL 是
http://localhost:6006/:tensorboard --logdir=./logs对于在 Windows 上运行的用户,请在 Anaconda 提示符下运行以下命令:
tensorboard --logdir=logs目录中的图片将在 TensorBoard 中显示如下:
图 3.7:在 TensorBoard 中查看图片批次
注意
系统中的图像可能会有所不同。
TensorBoard 中的结果是来自第一批次的图像。你可以看到它们是船和飞机的图像。TensorBoard 还提供了调整图像亮度和对比度的功能;然而,这仅会影响 TensorBoard 中的图像,而不会影响底层的图像数据。
在这个练习中,你通过 TensorBoard 查看了一个图像数据生成器的图像批次。这是验证训练数据质量的一个极好方法。虽然不必验证每一张图像的质量,但可以通过 TensorBoard 轻松查看样本批次。
本节介绍了 TensorFlow 提供的一项资源,帮助数据科学和机器学习从业者理解和可视化数据和算法:TensorBoard。你已使用该资源可视化计算图和图像批次。在下一节中,你将探索 TensorFlow Hub,它是一个可以轻松访问并集成到自定义应用中的机器学习模块库。这些模型由该领域的专家创建,你将学习如何将它们应用于自己的项目。
TensorFlow Hub
TensorFlow Hub 是一个机器学习模块的在线库。该模块包含了使用任何模型所需的资产及其相关权重(例如,用于预测或迁移学习),在迁移学习中,训练一个模型所获得的知识被用于解决不同但相关的问题。这些模块可以直接用于创建它们所训练的应用,或者可以作为构建新应用的起点。可以通过以下网址访问该平台:tfhub.dev/。当你访问该网站时,会看到以下页面:
图 3.8:TensorFlow Hub 首页
在这里,你可以浏览各个领域的模型。最受欢迎的领域包括图像、文本和视频;这些领域中有许多模型:
图 3.9:TensorFlow Hub 上可用的模型领域
TensorFlow Hub 上有许多模型可供使用,这些模型以图像作为输入数据。通常,这些模型用于图像分类、分割、嵌入、生成、增强和风格迁移等任务。为文本数据创建的模型通常用于文本嵌入,而用于视频数据的模型则用于视频分类。还有用于音频数据的模型,涉及命令检测和音高提取等任务。TensorFlow Hub 不断更新最新的先进模型,这些模型可用于各种应用。
选择模型后,你将进入以下页面,该页面会告诉你关于该模型的信息,如模型大小、架构、训练使用的数据集以及参考的 URL:
图 3.10:TensorFlow Hub 模型的页面
在引用自己的应用程序所需的模型时,你需要获取模型页面的 URL 以加载它。
可以通过使用 tensorflow_hub 库在笔记本环境中访问 TensorFlow Hub 上的模型。可以按照以下方式导入该库:
import tensorflow_hub as hub
可以通过使用库的 load 函数并传入模型的参考 URL 来加载模型:
module = hub.load("https://tfhub.dev/google/imagenet"\
"/inception_resnet_v2/classification/4")
可以通过访问 signatures 属性来查看模型模块的资源,例如其架构。每个模型的 signatures 属性中可能有不同的键;然而,相关信息通常会包含在 default 键中:
model = module.signatures['default']
该模型还可以通过将整个模型视为一个单独的 Keras 层,并使用 KerasLayer 方法直接用于训练:
layer = hub.KerasLayer("https://tfhub.dev/google/imagenet"\
"/inception_resnet_v2/classification/4")
将模型作为层用于自己的应用程序的过程称为迁移学习,将在后续章节中更深入地探讨。
可以通过将模型图写入日志来查看 TensorFlow Hub 中的模型,方法是使用文件写入器,如下所示:
from tensorflow.python.client import session
from tensorflow.python.summary import summary
from tensorflow.python.framework import ops
with session.Session(graph=ops.Graph()) as sess:
file_writer = summary.FileWriter(logdir)
file_writer.add_graph(model.graph)
在接下来的练习中,你将从 TensorFlow Hub 下载一个模型。加载模型后,你将使用 TensorBoard 查看模型的架构。
练习 3.03:从 TensorFlow Hub 下载模型
在本练习中,你将从 TensorFlow Hub 下载一个模型,然后在 TensorBoard 中查看该模型的架构。将要下载的模型是 InceptionV3 模型。该模型是在 TensorFlow 1 中创建的,因此在我们使用 TensorFlow 2 时,需要一些额外的步骤来显示模型的细节。该模型包含两部分:一部分包括卷积层,用于从图像中提取特征,另一部分是具有全连接层的分类部分。
由于原作者已恰当地命名了这些层,因此它们将在 TensorBoard 中可见。
注意
你可以在这里获取 InceptionV3 模型:tfhub.dev/google/imagenet/inception_v3/classification/5。
按照以下步骤完成此练习:
-
从 TensorFlow 导入以下库:
import tensorflow as tf import tensorflow_hub as hub from tensorflow.python.client import session from tensorflow.python.summary import summary from tensorflow.python.framework import ops导入和构建模型需要 TensorFlow 和 TensorFlow Hub 库,此外,还需要使用 TensorFlow 2 视图功能来可视化使用 TensorFlow 1 创建的模型,这也是你在本书中使用的版本。
-
为存储日志创建一个变量:
logdir = 'logs/' -
通过使用
tensorflow_hub库中的load方法并传入模型的 URL,可以加载模型模块:module = hub.load('https://tfhub.dev/google/imagenet'\ '/inception_v3/classification/5') -
从模块的
signatures属性加载模型:model = module.signatures['default'] -
使用文件写入器将模型图写入 TensorBoard:
with session.Session(graph=ops.Graph()) as sess: file_writer = summary.FileWriter(logdir) file_writer.add_graph(model.graph) -
在命令行中启动 TensorBoard,以查看图形的可视化表示。启动 TensorBoard 后,您可以通过访问提供的 URL 在网页浏览器中查看 TensorBoard:
tensorboard --logdir=./logs对于运行 Windows 的用户,在 Anaconda 提示符中运行以下命令:
tensorboard --logdir=logs您应该能看到类似以下的图像:
](tos-cn-i-73owjymdk6/cf5610d6fb5d43189a63a57edb4a2993)
图 3.11:在 TensorBoard 中查看的 InceptionV3 模型架构
TensorBoard 中的结果是 InceptionV3 模型的架构。在这里,您可以查看模型每一层的所有细节,包括输入、输出和激活函数。
在本次练习中,您成功地使用 TensorFlow Hub 库将模型下载到 Jupyter 笔记本环境中。一旦模型被加载到环境中,您就使用 TensorBoard 可视化了模型的架构。这是一种帮助您在调试过程中可视化模型架构的有效方式。
在本节中,您已探讨了如何使用 TensorFlow Hub 作为一种方式,利用机器学习领域专家创建的众多优秀模型。正如您将在后续章节中发现的,这些模型可以用于解决与它们最初开发用途稍有不同的应用问题;这就是所谓的迁移学习。在下一节中,您将学习如何使用 Google Colab,这是一种类似于 Jupyter Notebooks 的环境,可以在 Google 服务器上在线协作开发 Python 应用程序。
Google Colab
Google Colab 使用户能够在 Google 服务器上执行代码,专门为数据科学从业人员设计,用于在协作环境中开发机器学习代码。该平台可以在 colab.research.google.com/ 上使用,提供在网页浏览器中直接开发 Python 编程语言的机会,无需在本地计算机上执行任何代码。该环境预加载了最新的数据科学和机器学习库,提供了一个方便的替代方案,而无需使用 Jupyter Notebooks 设置开发环境。此外,该平台还提供免费的使用层级,包括访问 GPU 和 TPU,无需配置,并且在协作者之间共享笔记本非常简便。
Google Colab 提供了与 Jupyter Notebooks 非常相似的开发体验,使用 Google Colab 相较于 Jupyter Notebooks 也有一些优点和缺点。
Google Colab 的优点
以下是使用 Google Colab 的一些主要优点:
-
协作:许多用户可以访问同一个笔记本并共同协作工作。
-
托管环境:Google Colab 运行在 Google 服务器上,如果本地计算资源有限,这将非常有帮助。无需设置开发环境,因为许多软件包已经预装。
-
易于访问:Google Colab 直接保存到 Google Drive,提供无缝集成。由于笔记本保存在云端,因此无论何时只要能访问 Google Drive,都可以访问它们。
-
加速训练时间:提供 GPU 和 TPU 服务器,这可以加速训练机器学习模型的时间,尤其是有许多隐藏层的人工神经网络(ANN)。
-
交互式小部件:可以向笔记本添加小部件,以交互方式轻松地变化输入参数和变量。
Google Colab 的缺点
以下是使用 Google Colab 的一些缺点:
-
受限的运行时:Google Colab 上仅提供两个版本的 TensorFlow,1.X 和 2.X,且它们会更新,因此某些功能可能会随时间变化,从而导致代码损坏。此外,TensorFlow 的版本可能与其他软件包不兼容。
-
依赖互联网:由于 Python 代码是在 Google 服务器上执行的,Google Colab 只能在有互联网连接的情况下访问。
-
无自动保存:笔记本必须手动保存,这与 Jupyter Notebooks 的自动保存功能不同。
-
会话超时:在虚拟机上运行的笔记本有最大 12 小时的使用时间,长时间未使用的环境将被断开连接。
-
geoplotlib可能无法显示交互元素,因为与预装的库存在不兼容问题。
在 Google Colab 上开发
由于 Google Colab 使用笔记本,开发环境与 Jupyter Notebooks 非常相似。事实上,IPython 笔记本可以加载到 Google Colab 中。可以通过直接上传、Google Drive 或 GitHub 仓库加载它们。或者,该平台提供了示例笔记本,供用户入门。当你访问该平台时,colab.research.google.com/,你将看到以下界面,其中提供了可打开的笔记本或选择新笔记本开始开发的选项:
图 3.12:Google Colab 的主页
如果选择了一个新笔记本,你将看到以下界面,这可能让你想起在 Jupyter Notebooks 中开发的场景,且有许多相同的功能。你可以以完全相同的方式创建代码或文本片段,许多从业者发现从 Jupyter 过渡到 Colab 非常顺畅:
图 3.13:Google Colab 中的空白笔记本
在接下来的练习中,您将使用 Google Colab 导入并操作数据。在 Google Colab 与 Jupyter Notebooks 工作的主要区别之一是,在 Google Colab 中工作时,您是在远程服务器上开发。这意味着任何用于分析或训练模型的数据必须加载到 Google Drive 中或直接在线可用。在以下练习中,您将直接从 GitHub 仓库导入本书的 CSV 数据。
练习 3.04:使用 Google Colab 可视化数据
在本练习中,您将从 GitHub 仓库加载一个数据集,该数据集包含针对韩国首尔次日最高和最低气温预报的偏差校正数据。
注意
您可以在此处找到 Bias_correction_ucl.csv 文件:packt.link/8kP3j。
为了执行此练习,您需要导航到 colab.research.google.com/ 并创建一个新的笔记本进行操作。您需要连接到一个启用了 GPU 的环境,以加速 TensorFlow 操作,如张量乘法。一旦数据加载到开发环境中,您将查看前五行。接下来,您将删除 Date 字段,因为矩阵乘法需要数值字段。然后,您将对数据集进行张量乘法运算,使用一个张量或均匀随机变量。
按照以下步骤完成此练习:
-
导入 TensorFlow 并检查库的版本:
import tensorflow as tf print('TF version:', tf.__version__)您应当得到 TensorFlow 库的版本:
图 3.14:Google Colab 中可用的 TensorFlow 版本的输出
-
导航到
编辑标签,进入笔记本设置,然后从硬件加速下拉菜单中选择GPU。通过显示 GPU 设备名称来验证 GPU 是否已启用:tf.test.gpu_device_name()您应当得到 GPU 设备的名称:
图 3.15:GPU 设备名称
-
导入
pandas库并直接从 GitHub 仓库加载数据集:import pandas as pd df = pd.read_csv('https://raw.githubusercontent.com'\ '/PacktWorkshops/The-TensorFlow-Workshop'\ '/master/Chapter03/Datasets'\ '/Bias_correction_ucl.csv') -
使用
head方法查看数据集的前五行:df.head()您应当得到以下输出:
图 3.16:DataFrame 前五行的输出
-
删除
Date字段,因为您将进行矩阵乘法,而矩阵乘法需要数值字段:df.drop('Date', axis=1, inplace=True) -
导入 NumPy,将 DataFrame 转换为 NumPy 数组,然后创建一个包含均匀随机变量的 TensorFlow 张量。张量的第一个轴的值将等于数据集字段的数量,第二个轴将等于
1:import numpy as np df = np.asarray(df).astype(np.float32) random_tensor = tf.random.normal((df.shape[1],1)) -
使用 TensorFlow 的
matmul函数对数据集和随机张量进行张量乘法,并打印结果:tf.matmul(df, random_tensor)您应当得到如下输出:
图 3.17:张量乘法的输出
执行乘法运算的结果是一个新的张量,形状为7752x1。
在本练习中,你学习了如何使用 Google Colab。你观察到 Google Colab 提供了一个方便的环境来构建机器学习模型,并且预先加载了许多可能需要的机器学习库。你还可以看到使用的是这些库的最新版本。不幸的是,TensorFlow 的版本不能修改,因此在生产环境中使用 Google Colab 可能不是最合适的应用。但它非常适合开发环境。
在接下来的活动中,你将进一步练习如何在开发环境中使用 Google Colab。你将以与 Jupyter Notebooks 中相同的方式使用 TensorFlow Hub。本活动将类似于练习 2.04(加载文本数据到 TensorFlow 模型),其中通过使用预训练的词嵌入模型处理文本数据。利用预训练模型将在未来章节中介绍,但本活动将展示如何轻松利用来自 TensorFlow Hub 的预训练模型。
活动 3.02:从 TensorFlow Hub 中进行预训练模型的词嵌入
在本活动中,你将练习在 Google Colab 环境中工作。你将从 TensorFlow Hub 下载一个通用句子编码器,URL 为:tfhub.dev/google/universal-sentence-encoder/4。模型加载到内存后,你将使用它对一些示例文本进行编码。
按照以下步骤操作:
-
导入 TensorFlow 和 TensorFlow Hub,并打印库的版本。
-
将模块的句柄设置为通用句子编码器的 URL。
-
使用 TensorFlow Hub 的
KerasLayer类创建一个 hub 层,并传入以下参数:module_handle、input_shape和dtype。 -
创建一个包含字符串
The TensorFlow Workshop的列表,用该编码器进行编码。 -
将
hub_layer应用于文本,将句子嵌入为一个向量。你的最终输出应该如下所示:
图 3.18:活动 3.02 的预期输出
注意
本活动的解决方案可以通过此链接找到。
本节介绍了 Google Colab,这是一种在线开发环境,用于在 Google 服务器上运行 Python 代码。这可以使任何有互联网连接的从业人员开始构建机器学习模型。此外,你可以浏览预训练模型的选择,使用本章中学习到的另一个资源——TensorFlow Hub,开始为自己的应用创建模型。Google Colab 为从业者提供了零配置、最新的环境,甚至可以访问 GPU 和 TPU 以加速模型训练。
概要
在本章中,您使用了多种 TensorFlow 资源,包括 TensorBoard、TensorFlow Hub 和 Google Colab。 TensorBoard 为用户提供了一种可视化计算模型图、指标和任何实验结果的方法。 TensorFlow Hub 允许用户利用领域专家构建的预训练模型加速他们的机器学习开发。 Google Colab 提供了一个协作环境,让您在 Google 服务器上开发机器学习模型。 开发高效的机器学习模型是一个试验和错误的迭代过程,能够可视化每个步骤可以帮助从业者调试和改进他们的模型。 此外,理解领域专家如何构建他们的模型,并能够利用网络中的预训练权重,可以显著减少训练时间。 所有这些资源都用于提供一个有效的工作流程,以开发和调试机器学习算法。
在下一章中,您将开始在 TensorFlow 中创建自己的机器学习模型,从回归模型开始。 回归模型旨在从输入数据中预测连续变量。 您将利用 Keras 层来制作您的回归模型,这对于构建人工神经网络非常有用。
第四章:4. 回归与分类模型
概述
在本章中,你将学习如何使用 TensorFlow 构建回归和分类模型。你将利用 TensorFlow 中的 Keras 层来构建模型,Keras 是一种简单的建模方法,提供了一个高级 API 来构建和训练模型。你将创建模型来解决回归和分类任务,包括分类不同分子结合特性的任务。你还将使用 TensorBoard 来可视化 TensorFlow 模型的架构并查看训练过程。
介绍
在上一章中,你学习了如何使用一些 TensorFlow 资源来帮助开发。这些资源包括 TensorBoard(用于可视化计算图)、TensorFlow Hub(一个机器学习模块的在线仓库)和 Google Colab(一个在线 Python 开发环境,用于在 Google 服务器上运行代码)。所有这些资源都帮助机器学习从业者高效地开发模型。
在本章中,你将探索如何使用 TensorFlow 创建人工神经网络(ANNs)。你将构建具有不同架构的 ANNs 来解决回归和分类任务。回归任务旨在从输入的训练数据中预测连续变量,而分类任务则旨在将输入数据分类到两个或更多类别中。例如,预测某一天是否会下雨的模型是一个分类任务,因为模型的结果会有两个类别——下雨或不下雨。然而,预测某一天降水量的模型则是一个回归任务,因为模型的输出是一个连续变量——降水量。
用于解决这些任务的模型代表了机器学习模型中的一大类,许多机器学习问题都属于这两大类。 本章将演示如何在 TensorFlow 中创建、训练和评估回归和分类模型。你将运用前几章所学的内容(包括使用 TensorBoard 来监控模型训练过程),了解如何构建高效的模型。
本章介绍了构建人工神经网络(ANNs)时使用的各种参数(称为超参数),这些参数包括激活函数、损失函数和优化器。模型拟合过程中的其他超参数包括训练轮次(epochs)和批量大小(batch size),它们分别决定了整个数据集用于更新权重的次数和每次更新时使用的数据点数量。你还将学习如何在模型拟合过程中记录变量,以便在 TensorBoard 中进行可视化。这样可以帮助你判断模型是欠拟合还是过拟合训练数据。最后,在构建模型后,你将学习如何在数据集上评估模型,看看它的表现如何。
序列模型
顺序模型用于构建回归和分类模型。在顺序模型中,信息从开始的输入层传播到结束的输出层。模型中的层是按顺序堆叠的,每一层都有输入和输出。
存在其他类型的人工神经网络(ANN)模型,例如递归神经网络(其输出反馈到输入中),这些将在后续章节中介绍。顺序神经网络与递归神经网络的区别如图 4.01所示。在这两种模型中,信息从输入层通过隐藏层流向输出层,箭头的方向表示这一流向。然而,在递归结构中,隐藏层的输出会反馈到隐藏层的输入:
](tos-cn-i-73owjymdk6/59a7e6ecd6f14acf83323f5ca786586c)
图 4.1:顺序和递归人工神经网络的架构
在接下来的章节中,您将学习如何在 TensorFlow 中创建顺序模型,这些模型构成了回归和分类模型的基础。您将使用 Keras API,该 API 现在作为 TensorFlow 库的一部分,专门用于顺序模型,因为这个高级 API 提供了一个简单的接口来创建这些模型。使用该 API,您会发现向模型中添加更多层非常容易,非常适合新手学习这个领域。
可以按如下方式初始化一个顺序模型:
model = tf.keras.Sequential()
一旦模型初始化完成,就可以向模型添加层。在本节中,您还将探讨如何向模型中添加 Keras 层。
Keras 层
Keras 层包含在 TensorFlow 包中。Keras 层是常用层的集合,可以轻松地添加到您的顺序模型中。
注意
您可以在这里查看 Keras 层的所有可能选项:www.tensorflow.org/api_docs/python/tf/keras/layers。
要向 Sequential 类的模型添加层,可以使用模型的 add 方法。可以选择在顺序模型的开头添加一个输入层,作为网络的入口点。输入层可以接受以下常见的输入参数:
-
input_shape(必需):输入张量的形状,不包括批处理轴 -
batch_size:一个可选参数,表示输入的批处理大小 -
name:输入层的可选名称
可以按如下方式向模型添加输入层。以下代码片段用于添加一个层,假设输入具有八个特征:
model.add(tf.keras.layers.InputLayer(input_shape=(8,), \
name='Input_layer'))
通过提供 name 参数,您可以给层命名,这在 TensorBoard 中可视化模型时会非常有用。另一种常用的层是提供为参数的 input_shape。以下是 Dense 类层的常见输入参数:
-
units(必需):这是一个正整数,表示该层中的单元数量。 -
input_shape: 这是输入张量的形状,除非它是模型的第一层,否则不需要。 -
activation: 这是一个可选参数,指示要应用于该层输出的激活函数。 -
use_bias: 这是一个布尔值参数,指示是否在层中使用偏置。默认值设置为True。 -
name: 这是该层的名称。如果未提供该参数,将会自动生成一个名称。 -
kernel_initializer: 这是用于初始化核权重的初始化器。默认使用Glorot 均匀初始化器,它的分布以零为中心,标准差依赖于该层单元的数量。 -
bias_initializer: 这是偏置的初始化器。此参数的默认值将偏置值设置为零。 -
kernel_regularizer: 这是用于核权重的正则化器,默认情况下没有应用任何正则化器。 -
bias_regularizer: 这是用于偏置的正则化器,默认情况下没有应用任何正则化器。
以下是将一个 12 单元的密集层(dense layer)添加到模型的示例,并在该层输出处添加 sigmoid 激活函数,同时将该层命名为 Dense_layer_1:
model.add(tf.keras.layers.Dense(units=12, name='Dense_layer_1', \
activation='sigmoid'))
现在你已经理解了如何初始化序列型模型并向其中添加层,你将在第一个练习中使用 TensorFlow 创建一个 Keras 序列模型。你将初始化一个模型,向模型添加层,向模型的输出添加激活函数,并将数据通过模型来模拟创建一个预测。
练习 4.01:使用 TensorFlow 创建人工神经网络(ANN)
在本练习中,你将创建第一个 TensorFlow 序列型人工神经网络(ANN)。你将有一个输入层、一个具有四个单元和 ReLU 激活函数的隐藏层,以及一个具有一个单元的输出层。然后,你将通过生成随机数来创建一些模拟数据,并将其通过模型,使用模型的 predict 方法模拟对每个数据示例的预测。
执行以下步骤以完成本次练习:
-
打开 Jupyter Notebook 并导入 TensorFlow 库:
import tensorflow as tf -
初始化一个 Keras 序列模型:
model = tf.keras.Sequential() -
使用模型的
add方法向模型添加一个输入层,并添加input_shape参数,大小为(8,),表示具有八个特征的输入数据:model.add(tf.keras.layers.InputLayer(input_shape=(8,), \ name='Input_layer')) -
向模型添加两个
Dense类的层,第一个表示具有四个单元和 ReLU 激活函数的隐藏层,第二个表示具有一个单元的输出层:model.add(tf.keras.layers.Dense(4, activation='relu', \ name='First_hidden_layer')) model.add(tf.keras.layers.Dense(1, name='Output_layer')) -
通过调用模型的
variables属性查看权重:model.variables你应该会看到以下输出:
图 4.2:人工神经网络的变量
该输出显示了组成模型的所有变量;它们包括每一层中所有权重和偏置的值。
-
创建一个大小为
32x8的张量,这表示一个包含 32 条记录和 8 个特征的张量:data = tf.random.normal((32,8)) -
调用模型的
predict方法并传入样本数据:model.predict(data) prediction你应该得到以下结果:
图 4.3:应用随机输入后的人工神经网络(ANN)输出
在样本数据上调用predict()方法将数据传递通过网络。在每一层中,数据会与权重进行矩阵乘法,偏置将被加到数据中,然后数据作为输入传递到下一层。这个过程会持续,直到最终的输出层。
在这个练习中,你创建了一个包含多层的顺序模型。你初始化了一个模型,添加了一个输入层以接受具有八个特征的数据,添加了一个具有四个单元的隐藏层,并添加了一个具有一个单元的输出层。在将模型拟合到训练数据之前,必须首先通过优化器编译模型,并选择一个损失函数来最小化通过更新训练过程中的权重计算的值。
在接下来的章节中,你将探索如何编译模型,然后将其拟合到训练数据中。
模型拟合
一旦模型被初始化并且层已经添加到人工神经网络(ANN)中,就必须通过编译过程使用优化器、损失函数和任何评估指标来配置模型。模型可以使用模型的compile方法进行编译,如下所示:
model.compile(optimizer='adam', loss='binary_crossentropy', \
metrics=['accuracy'])
可以通过简单地命名优化器作为参数来选择优化器。以下是 Keras 模型的默认可用优化器:
-
随机梯度下降法(SGD):此方法更新数据集中每个示例的权重。你可以在这里找到有关 SGD 的更多信息:
keras.io/api/optimizers/sgd/。 -
RMSprop:这是一种自适应优化器,在训练过程中通过使用梯度的衰减平均值来改变权重。你可以在这里找到有关 RMSprop 的更多信息:
keras.io/api/optimizers/rmsprop/。 -
Adam:这也是一个自适应优化器,实施了 Adam 算法,根据一阶和二阶梯度更新学习率。你可以在这里找到有关 Adam 的更多信息:
keras.io/api/optimizers/adam/。 -
Adagrad:这种自适应梯度优化器在每次更新权重时调整学习率。每个特征的学习率会根据先前的梯度和观测值进行调整。你可以在这里找到有关 Adagrad 的更多信息:
keras.io/api/optimizers/adagrad/。 -
Adadelta:这是 Adagrad 的一个更强大的版本,通过使用梯度更新的滑动窗口来调整学习率。你可以在这里找到有关 Adadelta 的更多信息:
keras.io/api/optimizers/adadelta/。 -
Adamax:这是一种自适应优化器,是 Adam 优化器的变种。 您可以在这里找到有关 Adamax 的更多信息:
keras.io/api/optimizers/adamax/。 -
Nadam:这是 Adam 优化器的另一种自适应变种,具有 Nesterov 动量。 您可以在这里找到有关 Nadam 的更多信息:
keras.io/api/optimizers/Nadam/。 -
Ftrl:这是实施 FTRL 算法的优化器。 您可以在这里找到有关 Ftrl 的更多信息:
keras.io/api/optimizers/ftrl/。
如果提供的优化器不相关,则还可以将自定义优化器添加到 Keras 模型中。 选择最合适的优化器通常是尝试每个优化器并确定哪个优化器通过优化过程产生最低误差的问题。 这个过程称为 超参数调优,将在后续章节中讨论。 在下一节中,您将了解在编译模型时的另一个选项:损失函数。 训练模型的目标是通过最小化损失函数计算的值来最小化损失函数。
损失函数
损失函数是预测结果与真实结果之间误差的度量。 您在训练过程中使用损失函数来确定通过优化过程中任何权重和偏差的变化是否能创建更好的模型,通过最小化优化过程中损失函数的值来实现这一目标。
可以使用许多不同类型的损失函数,具体选择将取决于问题和目标。 一般来说,回归和分类任务将使用不同的损失函数。 由于回归模型预测连续变量,回归模型的损失函数通常旨在总结预测与真实值之间的平均距离。 对于分类模型,损失函数旨在确定预测类的真阳性、真阴性、假阳性和假阴性分类数量与真实类的差异程度。
真阳性 是分类器正确预测为阳性的标签; 同样地,真阴性 是正确预测为阴性的标签。假阳性 是被预测为阳性但实际为阴性的预测,而 假阴性 是被预测为阴性但实际为阳性的预测。Keras 顺序模型中用于回归的直接可用损失函数包括以下内容:
-
(真实值 – 预测值)²,并返回整个数据集的平均值。 此损失函数主要用于回归问题,两个值之间的平方差确保损失函数结果为正数。 -
|真实值 – 预测值|,并返回整个数据集的平均值。 此方法还确保结果为正值。 -
|(真实值 - 预测值) / 真实值|,并返回数据集上的平均值,作为百分比表示。
对于分类问题,可用的损失函数包括以下内容:
-
0和1,值越接近1表示真实正例分类的数量越多。 -
0和1。
在编译模型时,其他指标也可以作为参数传递给方法。它们将在每个 epoch 后进行计算,并在训练过程中保存。可用于 Keras 模型计算的指标包括以下内容:
-
准确率:这是正确结果占总结果的比例。
-
精确度:这是预测为正例的真实正例的比例。
-
召回率:这是实际正例中真实正例的比例。
-
AUC:这个指标表示 ROC 曲线下的面积。
这些指标在理解模型在训练过程中的表现时非常有价值。所有指标的值都在 0 和 1 之间,值越高表示表现越好。一旦模型编译完成,就可以将其拟合到训练数据。这可以通过调用 fit 方法并传入以下参数来实现:
-
x:这是特征数据,可以是一个 TensorFlow 张量或 NumPy 数组。 -
y:这是目标数据,可以是一个 TensorFlow 张量或 NumPy 数组。 -
epochs:这是模型训练的 epoch 数量。一个 epoch 是对整个训练数据集的一个迭代。 -
batch_size:这是每次梯度更新时使用的训练数据样本数量。 -
validation_split:这是用于验证的数据占训练数据的比例,在每个 epoch 后进行评估。此部分数据不会用于权重更新过程。 -
shuffle:这表示是否在每个 epoch 前对训练数据进行洗牌。
要将模型拟合到训练数据,可以通过以下方式将 fit 方法应用于模型:
model.fit(x=features, y=target, epochs=10, batch_size=32, \
validation_split=0.2, shuffle=False)
一旦调用了 fit 方法,模型将开始拟合训练数据。每个 epoch 后,会返回训练的损失。如果定义了验证集,则验证集的损失也会被评估。
模型评估
一旦模型训练完成,可以通过使用模型的 evaluate 方法来评估模型。evaluate 方法根据用于训练模型的损失函数以及传递给模型的任何指标来评估模型的性能。该方法最适合用来确定模型在新数据上的表现,可以通过传入未在训练过程中使用的特征和目标数据集,或者是超出样本的数据集来实现。该方法可以按如下方式调用:
eval_metrics = model.evaluate(features, target)
该方法的结果首先是对输入数据计算的损失,然后,如果在模型编译过程中传递了任何指标,它们也将在执行 evaluate 方法时计算。模型评估是确定模型表现如何的关键步骤。由于存在大量的超参数(例如隐藏层的数量、每层的单元数量以及激活函数的选择等),模型评估是确定哪些超参数组合最优的必要步骤。有效的模型评估有助于提供一个无偏的视角,帮助确定哪种模型架构在整体上表现最佳。
在以下练习中,您将进行创建 ANN、编译模型、将模型拟合到训练数据以及最终在训练数据上评估模型的过程。您将使用 ANN 重现线性回归算法,这可以被理解为一个只有一层和一个单元的 ANN。此外,您将通过 TensorBoard 查看模型的架构和模型训练过程。
练习 4.02:使用 TensorFlow 创建一个线性回归模型作为 ANN
在本练习中,您将使用 TensorFlow 创建一个线性回归模型作为 ANN。数据集 Bias_correction_ucl.csv 描述了韩国首尔空气温度预报的偏差修正。该数据字段表示给定日期的温度测量、测量数据的气象站、与天气相关的模型预报(如湿度)以及次日温度的预测。您需要根据先前时间点的测量值和气象站的属性来预测接下来的最大和最小温度。
注意
Bias_correction_ucl.csv 文件可以在这里找到:packt.link/khfeF。
执行以下步骤以完成本次练习:
-
打开一个新的 Jupyter notebook 来实现本次练习。
-
在新的 Jupyter Notebook 单元格中,导入 TensorFlow 和 pandas 库:
import tensorflow as tf import pandas as pd -
使用 pandas 的
read_csv函数加载数据集:df = pd.read_csv('Bias_correction_ucl.csv')注意
确保您根据系统中 CSV 文件的位置更改路径(高亮显示的部分)。如果您从与 CSV 文件存储在同一目录的 Jupyter notebook 中运行代码,您可以在不做任何修改的情况下运行之前的代码。
-
删除
date列,并删除所有包含空值的行,因为您的模型只需要数值数据:df.drop('Date', inplace=True, axis=1) df.dropna(inplace=True) -
创建目标和特征数据集。目标数据集将包含名为
Next_Tmax和Next_Tmin的列,而特征数据集将包含除Next_Tmax和Next_Tmin外的所有列:target = df[['Next_Tmax', 'Next_Tmin']] features = df.drop(['Next_Tmax', 'Next_Tmin'], axis=1) -
对特征数据集进行重缩放:
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() feature_array = scaler.fit_transform(features) features = pd.DataFrame(feature_array, columns=features.columns) -
初始化一个 Keras 的
Sequential类模型:model = tf.keras.Sequential() -
使用模型的
add方法为模型添加输入层,并将input_shape设置为特征数据集中的列数:model.add(tf.keras.layers.InputLayer\ (input_shape=(features.shape[1],), \ name='Input_layer')) -
将
Dense类的输出层添加到模型中,大小为2,表示两个目标变量:model.add(tf.keras.layers.Dense(2, name='Output_layer')) -
使用 RMSprop 优化器和均方误差损失函数编译模型:
model.compile(tf.optimizers.RMSprop(0.001), loss='mse') -
为 TensorBoard 添加回调:
tensorboard_callback = tf.keras.callbacks\ .TensorBoard(log_dir="./logs") -
将模型拟合到训练数据:
model.fit(x=features.to_numpy(), y=target.to_numpy(),\ epochs=50, callbacks=[tensorboard_callback])你应该会得到以下输出:
图 4.4:拟合过程的输出,显示每个 epoch 的训练时间和损失
-
在训练数据上评估模型:
loss = model.evaluate(features.to_numpy(), target.to_numpy()) print('loss:', loss)这将产生以下输出:
loss: 3.5468221449764012 -
通过在命令行中调用以下命令,在 TensorBoard 上查看模型架构和拟合过程:
tensorboard –-logdir=logs/你可以通过访问启动 TensorBoard 后提供的 URL,在网页浏览器中查看其执行情况。默认提供的 URL 是
http://localhost:6006/:
图 4.5:TensorBoard 中模型架构的可视化表示
损失函数可以通过以下图形进行可视化:
图 4.6:TensorBoard 中表示损失与每个 epoch 的关系的可视化图
你可以在 GRAPHS 标签页中看到模型的架构。架构显示了模型的输入层和输出层,以及计算出的损失。在模型拟合过程中,损失在每个 epoch 后都会被计算,并显示在 TensorBoard 的 SCALARS 标签页中。损失是在编译过程中定义的;在这个例子中,损失是均方误差。从 TensorBoard 中,你可以看到均方误差在每个 epoch 后减少,这表明模型正在从训练数据中学习,并且正在更新权重以减少总损失。
在本次练习中,你学习了如何使用 Keras 层通过 TensorFlow 创建、训练和评估一个 ANN。你通过创建一个包含输入层和输出层的 ANN 重建了线性回归算法,每个输出都有一个单元。在这里,有两个输出,分别表示温度的最大值和最小值;因此,输出层有两个单元。
在 练习 4.01,使用 TensorFlow 创建人工神经网络(ANN) 中,你创建了一个仅包含一个层(带有权重)和输出层的 ANN。这是一个 浅层神经网络 的例子。具有多个隐藏层且包含权重的 ANN 被称为 深度神经网络,而训练它们的过程称为 深度学习。通过增加层数并使 ANN 更深,模型变得更加灵活,能够建模更复杂的函数。然而,为了获得这种灵活性,你需要更多的训练数据和更强的计算能力来训练模型。
在下一个练习中,你将创建并训练具有多个隐藏层的 ANN。
练习 4.03:使用 TensorFlow 创建多层 ANN
在这个练习中,你将使用 TensorFlow 创建一个多层人工神经网络(ANN)。这个模型将有四个隐藏层。你将向模型中添加多个层,并为每一层的输出添加激活函数。第一个隐藏层将有16个单元,第二个隐藏层将有8个单元,第三个隐藏层将有4个单元。输出层将有2个单元。你将使用与练习 4.02相同的数据集,使用 TensorFlow 创建线性回归模型作为 ANN,该数据集描述了韩国首尔的气温预报偏差修正。该练习旨在根据先前时间点的测量值和气象站的属性,预测下一个最大和最小气温。
执行以下步骤以完成此练习:
-
打开一个新的 Jupyter 笔记本以实现此练习。
-
在新的 Jupyter Notebook 单元格中,导入 TensorFlow 和 pandas 库:
import tensorflow as tf import pandas as pd -
使用 pandas 的
read_csv函数加载数据集:df = pd.read_csv('Bias_correction_ucl.csv')注意
确保你根据文件在系统上的位置更改路径(高亮显示的部分)。如果你是从与 CSV 文件相同的目录运行 Jupyter 笔记本,你可以不做任何修改直接运行前面的代码。
-
删除
Date列并删除任何包含空值的行:df.drop('Date', inplace=True, axis=1) df.dropna(inplace=True) -
创建目标和特征数据集:
target = df[['Next_Tmax', 'Next_Tmin']] features = df.drop(['Next_Tmax', 'Next_Tmin'], axis=1) -
重新缩放特征数据集:
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() feature_array = scaler.fit_transform(features) features = pd.DataFrame(feature_array, columns=features.columns) -
初始化一个
Sequential类的 Keras 模型:model = tf.keras.Sequential() -
使用模型的
add方法为模型添加一个输入层,并将input_shape设置为特征数据集中的列数:model.add(tf.keras.layers.InputLayer\ (input_shape=(features.shape[1],), \ name='Input_layer')) -
向模型中添加三个隐藏层和一个
Dense类的输出层。第一个隐藏层将有16个单元,第二个隐藏层将有8个单元,第三个隐藏层将有4个单元。为各个层适当命名。输出层将有两个单元,以匹配具有两列的目标变量:model.add(tf.keras.layers.Dense(16, name='Dense_layer_1')) model.add(tf.keras.layers.Dense(8, name='Dense_layer_2')) model.add(tf.keras.layers.Dense(4, name='Dense_layer_3')) model.add(tf.keras.layers.Dense(2, name='Output_layer')) -
使用 RMSprop 优化器和均方误差损失编译模型:
model.compile(tf.optimizers.RMSprop(0.001), loss='mse') -
为 TensorBoard 添加一个回调:
tensorboard_callback = tf.keras.callbacks\ .TensorBoard(log_dir="./logs") -
将模型拟合到训练数据,训练
50个周期,并添加一个验证拆分,比例为 20%:model.fit(x=features.to_numpy(), y=target.to_numpy(),\ epochs=50, callbacks=[tensorboard_callback] , \ validation_split=0.2)你应该得到以下输出:
图 4.7:拟合过程的输出,显示每个周期、每个样本的训练时间以及每个周期后的损失
-
在训练数据上评估模型:
loss = model.evaluate(features.to_numpy(), target.to_numpy()) print('loss:', loss)这将显示以下结果:
loss: 1.664448248190068 -
在 TensorBoard 中查看模型架构和模型拟合过程:
tensorboard --logdir=logs/你应该得到如下所示的结果:
图 4.8:TensorBoard 中模型架构的可视化表示
你可以可视化损失函数,如下截图所示:
图 4.9:在训练和验证集划分上,损失随 epoch 变化的可视化表示
网络架构显示了模型的输入层和四个隐藏层,以及最终计算的损失。在模型拟合过程中,每个 epoch 后都会计算损失,并显示在 TensorBoard 的SCALARS选项卡中。在这里,损失是均方误差。从 TensorBoard 中,你可以看到每个 epoch 后,训练集(橙色线)和验证集(蓝色线)的均方误差在逐渐减少,表明模型正在有效地从训练数据中学习。
在本次练习中,你已经创建了一个具有多个隐藏层的 ANN。你获得的损失比使用线性回归时的损失要低,这展示了 ANN 的强大能力。通过调整超参数(例如,改变层数、每层的单元数、添加激活函数以及改变损失和优化器),损失可能会更低。在下一次活动中,你将把你的模型构建技能应用到一个新的数据集上。
活动 4.01:使用 TensorFlow 创建多层感知器(ANN)
特征数据集superconductivity.csv包含超导体的属性,包括材料的原子质量和密度。重要的是,数据集还包含材料的临界温度,即材料表现出超导特性的温度。在本次活动中,你的任务是找出材料的临界温度,或者说材料获得超导特性的温度。
注意
superconductivity.csv文件可以在这里找到:packt.link/sOCPh。
执行以下步骤完成本次活动:
-
打开一个新的 Jupyter 笔记本来实现本次活动。
-
导入 TensorFlow 和 pandas 库。
-
加载
superconductivity.csv数据集。 -
删除包含空值的行。
-
将目标设置为
critical_temp列,将特征数据集设置为其余列。 -
使用标准缩放器对特征数据集进行缩放。
-
初始化一个 Keras
Sequential类的模型。 -
向模型添加一个输入层,四个隐藏层,大小分别为
64、32、16和8,以及一个大小为1的输出层。为第一个隐藏层添加 ReLU 激活函数。 -
使用 RMSprop 优化器编译模型,学习率为
0.001,并使用均方误差作为损失函数。 -
添加回调函数,将日志写入 TensorBoard。
-
将模型拟合到训练数据,训练
100个 epochs,批量大小为32,验证集划分比例为 20%。 -
在训练数据上评估模型。
-
在 TensorBoard 中查看模型架构。
你应该得到类似以下的输出:
图 4.10:在 TensorBoard 中,模型架构的可视化表示
-
在 TensorBoard 中可视化模型拟合过程。你应该会得到如下输出:
图 4.11:在 TensorBoard 中,损失随训练和验证拆分的轮次变化的可视化表示
注意
本活动的解决方案可以通过此链接找到。
在下一部分,你将探索分类模型,这些模型尝试将数据分类为不同的类别。你将从二分类模型开始,它将数据分类为仅两个类别。这是最简单的分类模型形式。一旦掌握了二分类器,就可以挑战更复杂的模型,如多标签分类和多类分类。
分类模型
分类模型的目标是将数据分类到不同的类别中。例如,垃圾邮件过滤器就是一个分类模型,它旨在将电子邮件分类为“垃圾邮件”(指未经请求的、不需要的邮件)或“正常邮件”(合法邮件)。垃圾邮件过滤器是一个二分类模型的例子,因为它有两个类别。输入到过滤器的内容可能包括电子邮件的内容、发件人的电子邮件地址和主题行等特征,输出将是预测的类别,垃圾邮件或正常邮件。分类模型可以将数据分类为两个以上的类别(称为多类分类),或者对数据进行多个正标签的分类(称为多标签分类)。
有几种不同的算法可以用于分类任务。一些流行的算法包括逻辑回归、决策树和人工神经网络(ANN)。ANN 是分类模型的一个不错选择,因为它们能够学习特征与目标之间的复杂关系,并且通过在 ANN 输出层应用适当的激活函数可以获得结果。
常用的分类模型激活函数是 sigmoid 函数,它与逻辑回归中使用的函数相同。事实上,可以通过构建一个具有单层、一个单元和 sigmoid 激活函数的 ANN 来创建一个逻辑回归模型。Sigmoid 函数是一种转换,其中输入是任意实数值,输出是一个严格介于 0 和 1 之间的数值。以下图示为例:
Sigmoid 转换的输出可以被解释为一个值属于正类的概率;接近 1 的值表示属于正类的概率较高:
图 4.12:Sigmoid 函数的可视化表示
在应用了 sigmoid 函数后,会应用一个阈值,高于该阈值的数据将被归类为正类,低于该阈值的数据将被归类为负类。sigmoid 函数的默认阈值为 0.5,意味着任何值大于或等于 0.5 的数据将被归类为正类。
在下一个练习中,你将使用 TensorFlow 创建一个逻辑回归模型。你将通过创建一个单层人工神经网络(ANN)来实现这一点,这一过程类似于 练习 4.02 中的线性回归模型,使用 TensorFlow 创建线性回归模型作为 ANN。不同之处在于,你将在 ANN 的输出端添加一个 sigmoid 激活函数。另一个将这两个练习区分开的差异是你将使用不同的损失函数来计算损失。
练习 4.04:使用 TensorFlow 创建逻辑回归模型作为 ANN
在本练习中,你将使用 TensorFlow 将逻辑回归模型创建为 ANN。数据集 qsar_androgen_receptor.csv 用于开发分类模型,以区分具有不同分子属性的结合/非结合分子。在这里,分子属性代表数据集的特征,其结合属性代表目标变量,其中正值代表结合分子,负值代表非结合分子。你将创建一个逻辑回归模型,根据数据集中提供的分子属性预测分子的结合特性。
注意
qsar_androgen_receptor.csv 文件可以在这里找到:packt.link/hWvjc。
执行以下步骤来完成本练习:
-
打开一个新的 Jupyter notebook 来实现本练习。
-
导入 TensorFlow 和 pandas 库:
import tensorflow as tf import pandas as pd -
使用 pandas 的
read_csv函数加载数据集:df = pd.read_csv('qsar_androgen_receptor.csv', \ sep=';')注意
确保根据 CSV 文件在系统上的位置更改路径(已突出显示)。如果你从存储 CSV 文件的同一目录运行 Jupyter notebook,则无需修改代码即可运行上述代码。
-
丢弃任何包含空值的行:
df.dropna(inplace=True) -
创建目标和特征数据集:
target = df['positive'].apply(lambda x: 1 if x=='positive' else 0) features = df.drop('positive', axis=1) -
初始化一个 Keras
Sequential类的模型:model = tf.keras.Sequential() -
使用模型的
add方法为模型添加输入层,并将input_shape设置为特征数据集中的列数:model.add(tf.keras.layers.InputLayer\ (input_shape=(features.shape[1],), \ name='Input_layer')) -
将
Dense类的输出层添加到模型中,大小为1,表示目标变量:model.add(tf.keras.layers.Dense(1, name='Output_layer', \ activation='sigmoid')) -
使用 RMSprop 优化器和二元交叉熵损失函数编译模型,并计算准确率:
model.compile(tf.optimizers.RMSprop(0.0001), \ loss='binary_crossentropy', metrics=['accuracy']) -
创建一个 TensorBoard 回调:
tensorboard_callback = tf.keras.callbacks.TensorBoard\ (log_dir="./logs") -
通过训练数据训练模型
50个 epoch,并添加 TensorBoard 回调,验证集比例为 20%:model.fit(x=features.to_numpy(), y=target.to_numpy(), \ epochs=50, callbacks=[tensorboard_callback] , \ validation_split=0.2)你的输出应该类似于下图:
图 4.13:拟合过程的输出,显示每个 epoch、每个样本的训练时间,以及每个 epoch 后的损失
-
在训练数据上评估模型:
loss, accuracy = model.evaluate(features.to_numpy(), \ target.to_numpy()) print(f'loss: {loss}, accuracy: {accuracy}')你应该得到类似如下的输出:
loss: 0.2781583094794838, accuracy: 0.9110320210456848 -
通过在命令行中调用以下命令,在 TensorBoard 中可视化模型拟合过程:
tensorboard --logdir=logs/你应该在浏览器中看到类似如下的界面:
图 4.14:在 TensorBoard 中的模型架构的可视化表示
损失函数可以表示为如下形式:
图 4.15:在 TensorBoard 中评估的训练和验证分割上,以一个 epoch 为函数的损失和准确度的可视化表示
从 TensorBoard 中可以看到,通过在模型编译过程中添加 metrics 参数,模型架构中有一个额外的节点用于计算准确度指标。此外,在 SCALARS 标签页中,还显示了训练和验证分割的准确度指标,作为一个 epoch 的函数。
从图表中可以看出,对于训练集,准确度随着时间的推移增加,损失减少,这表明模型正在学习。然而,在验证集上,准确度开始下降,损失开始增加,这表明模型可能正在过拟合训练数据。
在这个练习中,你学会了如何构建一个分类模型,用于区分不同分子在其其他分子属性基础上的结合特性。该分类模型等同于逻辑回归模型,因为它只有一层,并且之前有一个 sigmoid 激活函数。由于只有一层,每个输入特征都有一个权重,并且偏置只有一个值。sigmoid 激活函数将该层的输出转换为介于 0 和 1 之间的值,然后通过四舍五入表示你的两类。0.5 及以上代表一类,具有结合特性的分子,而低于 0.5 代表另一类,即没有结合特性的分子。
接下来的活动将通过结合你在练习 4.03(使用 TensorFlow 创建多层感知机)、活动 4.01(使用 TensorFlow 创建多层感知机)中学到的创建多层人工神经网络(ANN)的知识,以及你在练习 4.04(使用 TensorFlow 创建逻辑回归模型作为 ANN)中学到的创建分类模型的知识,来总结你在本章的学习。你将使用与前一个活动相同的数据集,但会改变目标变量,使其更适合分类任务。
活动 4.02:使用 TensorFlow 创建多层分类 ANN
特征数据集superconductivity.csv包含超导体的属性,包括材料的原子质量和密度。重要的是,数据集还包含材料的临界温度,即材料展现超导性特性的温度。你需要确定哪些超导体在氮气的沸点(77.36 K)以上展现超导性,从而使得可以使用易得的液氮进行超导性实验。目标变量将在临界温度高于 77.36 K 时为true,低于该温度时为false,表示材料是否在氮气的沸点以上展现超导性。
注意事项
superconductivity.csv 文件可以在此找到:packt.link/sOCPh。
执行以下步骤来完成此活动:
-
打开一个 Jupyter Notebook 来完成活动。
-
导入 TensorFlow 和 pandas 库。
-
加载
superconductivity.csv数据集。 -
删除所有包含空值的行。
-
当
critical_temp列的值高于77.36时,将目标值设置为true,低于时设置为false。特征数据集是数据集中的其余列。 -
使用标准化缩放器对特征数据集进行重新缩放。
-
初始化一个 Keras
Sequential类的模型。 -
向模型中添加一个输入层,三个隐藏层,大小分别为
32、16、8,以及一个输出层,使用sigmoid激活函数,大小为1。 -
使用 RMSprop 优化器编译模型,学习率为
0.0001,损失函数为二元交叉熵,并计算准确率指标。 -
添加一个回调函数,将日志写入 TensorBoard。
-
将模型拟合到训练数据中,训练
50个周期,验证集分割为 0%。 -
在训练数据上评估模型。
-
在 TensorBoard 中查看模型架构和模型拟合过程。
注意事项
本活动的解决方案可以通过此链接找到。
在本节中,你已经开始了使用 TensorFlow 构建、训练和评估分类模型的探索。你已经看到它们与回归任务的 ANN 构建方式非常相似,主要的区别在于输出层的激活函数。
总结
在本章中,你开始了在 TensorFlow 中创建人工神经网络(ANNs)的旅程。你了解了利用 Keras 层创建回归和分类模型是多么简单。Keras 层是一个独立的类库,在后台使用 TensorFlow。由于其流行和易用性,它们现在已经包含在 TensorFlow 中,并可以像调用任何其他 TensorFlow 类一样进行调用。
你创建了具有全连接层的人工神经网络(ANN),并且通过不同的层级进行变动,首先是一个类似于线性回归算法的 ANN,这相当于一个单层 ANN。然后,你向 ANN 中添加了更多层,并在各层的输出上添加了激活函数。激活函数可以用来判断某个单元是否激活,或者用来绑定某个单元输出的值。回归模型的目标是根据提供的数据预测一个连续变量。在本章的练习和活动中,你尝试预测了首尔的温度,给定来自气象站的数据,并预测了超导材料的临界温度,基于不同的材料特性。
最后,你探讨了分类模型,这些模型旨在将数据分类到不同的类别中。这些模型与回归模型在设置方式上相似;然而,在最终输出上使用激活函数,将输出值限制在两个数字之间,这两个数字表示数据点是否被分类到某个类别中。你从二分类模型开始,这些模型旨在将数据分为两个类别,并通过一个练习演示了二分类的概念,在该练习中,你根据分子其他属性的特征将分子分类到代表其结合特性的类别中。
在下一章,你将更深入地探讨分类模型。你将学习一些分类模型的细节和功能,包括如何对具有多个类别的数据进行分类(即多类分类),以及数据点是否可以有多个正标签(即多标签分类)。你将探讨如何构建架构来创建这些模型,训练时使用的适当损失函数,以及如何计算相关的度量指标来评估模型的表现。
第五章:5. 分类模型
概述
在本章中,您将探索不同类型的分类模型。您将获得使用 TensorFlow 构建二元分类、多类别分类和多标签分类器的实际经验。最后,您将学习模型评估的概念,并了解如何使用不同的指标来评估模型的表现。
到本章结束时,您将对分类模型及使用 TensorFlow 编程有一个良好的理解。
介绍
在上一章中,您学习了回归问题,其中目标变量是连续的。连续变量可以取最小值和最大值之间的任何值。您已经学会了如何使用 TensorFlow 训练这样的模型。
在本章中,您将研究另一种监督学习问题,称为分类问题,其中目标变量是离散的——意味着它只能取有限数量的值。在行业中,您最有可能遇到这样的项目,其中变量被聚合为不同的组,如产品层次、用户类别、客户类别或薪资范围。分类器的目标是从数据中学习模式,并预测观察值的正确类别。
例如,在贷款提供商的情况下,分类模型将尝试根据客户的资料和财务状况预测他们在来年违约的可能性。该结果只能取两个可能的值(是或否),这就是二元分类。另一个分类器模型可能会根据用户之前的评分和这部新电影的信息,预测用户对该电影的评分,评分范围为 1 到 5。当结果可以取两个以上的值时,您正在处理多类别分类。最后,还有第三种类型的分类器,称为多标签分类,其中模型将预测多个类别。例如,模型将分析一张输入图像,并预测图像中是否有猫、狗或老鼠。在这种情况下,模型将预测三个不同的二元输出(或标签)。
本章将介绍每种分类器,详细阐述其特点,并探讨如何衡量这些模型的表现。
二元分类
如前所述,二元分类指的是一种监督学习类型,其中目标变量只能取两个可能的值(或类别),例如真/假或是/否。例如,在医疗行业中,您可能想根据患者的个人信息(如年龄、身高、体重和/或医疗测量值)来预测他们是否更有可能患病。同样,在营销领域,广告商可能利用类似的信息来优化电子邮件活动。
诸如随机森林分类器、支持向量分类器或逻辑回归等机器学习算法在分类任务上表现良好。神经网络也可以为二元分类实现良好的结果。将回归模型转换为二元分类器非常简单,只需要两个关键的变化:最后一层的激活函数和损失函数。
逻辑回归
0和1。值0通常对应于false(或no),而值1则指true(或yes)。
换句话说,逻辑回归的输出将是其为真的概率。例如,如果输出为0.3,则可以说结果为真(或 yes)的概率为 30%。但由于只有两个可能的值,这也意味着有 70%的概率(100% - 30%)结果为假(或 no):
图 5.1: 逻辑回归的输出
现在您已经了解了逻辑回归的输出是什么,您只需找到一个可以将连续输入值转换为0和1之间值的函数。幸运的是,这样的数学函数确实存在,称为sigmoid 函数。该函数的公式如下:
图 5.2: Sigmoid 函数的公式
对应于应用于
x的指数函数。指数函数的取值范围从0到正无穷。因此,如果x的值接近正无穷,sigmoid 的值将趋向于1。另一方面,如果x非常接近负无穷,则 sigmoid 的值将趋向于0:
图 5.3: Sigmoid 函数的曲线
因此,将线性回归模型的输出应用于 sigmoid 函数将其转换为逻辑回归。对于神经网络也是同样的逻辑:如果您将 sigmoid 函数应用于感知器模型(线性回归),则将获得二元分类器。要实现这一点,只需在感知器模型的最后一个全连接层中指定 sigmoid 作为激活函数。在 TensorFlow 中,您可以将activation参数指定为:
from tensorflow.keras.layers import Dense
Dense(1, activation='sigmoid')
前面的代码片段展示了如何定义一个具有单个单元的全连接层,该单元可以输出任何值,并对其应用 sigmoid 激活函数。结果将在0和1之间。现在,您已经了解如何修改神经网络的回归模型以将其转变为二元分类器,需要指定相关的损失函数。
二元交叉熵
在上一节中,你学习了如何将一个线性回归模型转换为二分类器。使用神经网络,只需在最后的全连接层上添加 sigmoid 激活函数即可。但还有一个影响该模型训练的因素:损失函数的选择。
对于线性回归,最常用的损失函数是均方误差和平均绝对误差,如在第四章《回归与分类模型》中所示。这些函数会计算预测值与实际值之间的差异,神经网络模型会在反向传播过程中相应地更新所有权重。对于二分类问题,典型的损失函数是二元交叉熵(也叫做对数损失)。该函数的公式如下:
图 5.4:二元交叉熵公式
代表观测
i 的实际值。
代表观测
i 的预测概率。
N 代表观测的总数。
这个公式看起来相当复杂,但其逻辑非常简单。考虑以下单个观测的例子:实际值为 1,预测概率为 0.8。如果应用上述公式,结果将如下:
请注意,方程式右侧的值大约为零:
因此,当预测值与实际值非常接近时,损失值会非常小。
现在考虑另一个例子,其中实际值为 0,预测概率为 0.99。结果如下:
在这种情况下,损失会很高,因为预测值与实际值差异很大。
BinaryCrossentropy 用于计算这个损失:
from tensorflow.keras.losses import BinaryCrossentropy
bce = BinaryCrossentropy()
二分类架构
二分类器的架构与线性回归非常相似,如在第四章《回归与分类模型》中所示。它由一个输入层组成,该层读取输入数据集的每个观测值,一个输出层负责预测响应变量,以及一些隐藏层,学习导致正确预测的模式。以下图示展示了这种架构的一个例子:
图 5.5:二分类器的架构
与线性回归的唯一区别是输出,它是一个介于0和1之间的概率值。这个概率值表示其中一个可能值发生的概率。如前所述,这通过使用 sigmoid 激活函数和二元交叉熵进行反向传播来实现。
现在你已经看到了构建二分类器的所有元素,你可以通过一个练习将它付诸实践。
练习 5.01:构建逻辑回归模型
在这个练习中,你将使用 TensorFlow 构建并训练一个逻辑回归模型,预测 Dota 2 比赛中哪个队伍获胜,使用的输入信息包括游戏的模式和类型等。
你将使用 Dota 2 数据集进行工作。Dota 2 是一款流行的电脑游戏。该数据集包含与游戏相关的信息,目标变量指示哪个队伍获胜。
注意
训练数据集可以在这里访问:packt.link/Tdvdj。
测试数据集可以在这里访问:packt.link/4PsPN。
原始数据集可以在这里找到:archive.ics.uci.edu/ml/datasets/Dota2+Games+Results。
-
打开一个新的 Jupyter 笔记本。
-
导入 pandas 库并使用
pd作为别名:import pandas as pd -
创建一个名为
train_url的变量,包含训练集的 URL:train_url = 'https://raw.githubusercontent.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/master/Chapter05'\ '/dataset/dota2Train.csv' -
使用
read_csv()方法将训练数据集加载到一个名为X_train的DataFrame()函数中,提供 CSV 文件的 URL,并将header=None设置为数据集没有列名。使用head()方法打印 DataFrame 的前五行数据:X_train = pd.read_csv(train_url, header=None) X_train.head()期望的输出如下所示:
图 5.6:Dota 2 训练集的前五行数据
你可以看到数据集包含 117 列,且它们都是数值型的。还需要注意的是,目标变量(第
0列)包含两个不同的值:-1和1。由于你将训练一个逻辑回归模型,可能的值应该是0和1。你需要将-1的值替换为0。 -
使用
pop()方法提取目标变量(第 0 列),并将其保存在名为y_train的变量中:y_train = X_train.pop(0) -
使用
replace()方法将目标变量中的所有-1值替换为0,并使用head()方法打印前五行数据:y_train = y_train.replace(-1,0) y_train.head()期望的输出如下所示:
图 5.7:Dota 2 训练集中目标变量的前五行数据
现在,训练集的目标变量中的所有值都是
0或1。 -
创建一个名为
test_url的变量,包含测试集的 URL:test_url = 'https://raw.githubusercontent.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/master/Chapter05/dataset'\ '/dota2Test.csv' -
使用
read_csv()方法加载测试数据集到名为X_test的DataFrame()函数中,提供 CSV 文件的 URL,并设置header=None,因为数据集没有提供列名。使用head()方法打印前五行:X_test = pd.read_csv(test_url, header=None) X_test.head()预期的输出如下:
图 5.8:Dota 2 测试集的前五行
测试集与训练集非常相似,你需要对其进行相同的转换。
-
使用
pop()方法提取目标变量(第 0 列),并将其保存为名为y_test的变量:y_test = X_test.pop(0) -
使用
replace()方法将目标变量中的所有-1值替换为0,并使用head()方法打印前五行:y_test = y_test.replace(-1,0) y_test.head()预期的输出如下:
图 5.9:Dota 2 测试集中的目标变量前五行
-
导入 TensorFlow 库并使用
tf作为别名:import tensorflow as tf -
使用
tf.random.set_seed()设置 TensorFlow 的种子为8,以获得可重复的结果:tf.random.set_seed(8) -
使用
tf.keras.Sequential()实例化一个顺序模型,并将其保存为名为model的变量:model = tf.keras.Sequential() -
从
tensorflow.keras.layers导入Dense()类:from tensorflow.keras.layers import Dense -
使用
Dense()创建一个包含512个单元的全连接层,指定 ReLu 作为激活函数,并将输入形状设置为(116,),这对应于数据集中的特征数量。将其保存为名为fc1的变量:fc1 = Dense(512, input_shape=(116,), activation='relu') -
使用
Dense()创建一个包含512个单元的全连接层,并指定 ReLu 作为激活函数。将其保存为名为fc2的变量:fc2 = Dense(512, activation='relu') -
使用
Dense()创建一个包含128个单元的全连接层,并指定 ReLu 作为激活函数。将其保存为名为fc3的变量:fc3 = Dense(128, activation='relu') -
使用
Dense()创建一个包含128个单元的全连接层,并指定 ReLu 作为激活函数。将其保存为名为fc4的变量:fc4 = Dense(128, activation='relu') -
使用
Dense()创建一个包含128个单元的全连接层,并指定 sigmoid 作为激活函数。将其保存为名为fc5的变量:fc5 = Dense(1, activation='sigmoid') -
使用
add()方法顺序添加所有五个全连接层到模型中:model.add(fc1) model.add(fc2) model.add(fc3) model.add(fc4) model.add(fc5) -
使用
summary()方法打印模型的摘要:model.summary()预期的输出如下:
图 5.10:模型架构摘要
上述输出显示了模型中有五个层(如预期)并展示了每层的参数数量。例如,第一层包含 59,904 个参数,该模型的总参数数量为 404,855。所有这些参数将在训练模型时进行训练。
-
从
tf.keras.losses实例化一个BinaryCrossentropy()函数,并将其保存为名为loss的变量:loss = tf.keras.losses.BinaryCrossentropy() -
从
tf.keras.optimizers实例化Adam(),学习率设置为0.001,并将其保存为名为optimizer的变量:optimizer = tf.keras.optimizers.Adam(0.001) -
使用
compile()函数编译模型,并指定在前面步骤中创建的优化器和损失函数:model.compile(optimizer=optimizer, loss=loss) -
使用
fit()方法在训练集上进行五个 epoch 的模型训练:model.fit(X_train, y_train, epochs=5)预期输出如下:
图 5.11:训练过程的日志
上述输出显示了每个 epoch 训练过程中记录的日志。请注意,处理单个 epoch 大约需要 15 秒,且损失值从
0.6923(第一 epoch)降到0.6650(第五 epoch),这表明模型通过减少二元交叉熵损失正在缓慢改善其性能。 -
使用
predict()方法预测测试集的结果。将结果保存到名为preds的变量中,并显示其前五个值:preds = model.predict(X_test) preds[:5]预期输出如下:
图 5.12:测试集前五行的预测结果
上述输出显示了每个预测的概率。小于
0.5的值会被分类为0(该输出中的第一和最后一个观察结果),而大于或等于0.5的值会被分类为1(第二到第四个观察结果)。 -
显示测试集前五个真实标签:
y_test[:5]预期输出如下:
图 5.13:测试集前五行的真实标签
将该输出与模型在测试集前五行上的预测结果进行比较,发现存在一些错误值:第三个预测(索引为2)应为0,最后一个预测应为0。因此,在这五个观察值中,二分类器犯了两个错误。
在接下来的部分中,你将看到如何使用不同的指标正确评估模型的性能。
分类器的评估指标
在前一部分中,你学习了如何训练一个二分类器来预测正确的输出:0或1。在练习 5.01中,构建逻辑回归模型,你查看了几个样本以评估所构建模型的性能。通常,你会使用像准确率或 F1 分数这样的性能指标对模型进行评估,而不仅仅是对一个小子集进行评估,而是对整个数据集进行评估。
准确率和空白准确率
其中一个最广泛使用的分类问题评估指标是准确率。它的公式非常简单:
图 5.14:准确率指标的公式
准确率的最大值为1,表示模型正确预测了 100%的案例。其最小值为0,表示模型无法正确预测任何案例。
对于二分类器,正确预测的数量是指那些值为0或1的观察结果,且这些值为正确预测的值:
图 5.15:二分类器的准确度指标公式
假设你正在评估两个不同的二分类器在测试集上对 10,000 个观察结果的预测表现。第一个模型正确预测了 5,000 个值为 0 的实例和 3,000 个值为 1 的实例。其准确度得分将如下:
图 5.16:模型 1 准确度公式
第二个模型正确预测了 500 个值为 0 的案例和 1,500 个值为 1 的案例。其准确度得分将如下:
图 5.17:模型 2 准确度公式
第一个模型在 80% 的情况下预测正确,而第二个模型仅在 20% 的情况下预测正确。在这种情况下,你可以说模型 1 比模型 2 更好。
尽管0.8通常是一个相对较好的分数,但这并不一定意味着你的模型表现良好。例如,假设你的数据集中包含 9,000 个值为 0 的案例和 1,000 个值为 1 的案例。一个非常简单的模型,如果总是预测值为 0,将会获得 0.9 的准确度。在这种情况下,第一个模型的表现甚至比这个极其简单的模型差。这种总是预测数据集中最频繁值的模型特性被称为 0.9,因为简单模型预测 0,它在 90% 的情况下是正确的。
注意
准确度和空准确度指标不仅适用于二分类,还可以应用于其他类型的分类。
TensorFlow 提供了一个类 tf.keras.metrics.Accuracy,可以从张量中计算准确度得分。该类有一个名为 update_state() 的方法,它接受两个张量作为输入参数,并计算它们之间的准确度得分。你可以通过调用 result() 方法来访问此得分。输出结果将是一个张量。你可以使用 numpy() 方法将其转换为 NumPy 数组。以下是如何计算准确度得分的示例:
from tensorflow.keras.metrics import Accuracy
preds = [1, 1, 1, 1, 0, 0]
target = [1, 0, 1, 0, 1, 0]
acc = Accuracy()
acc.update_state(preds, target)
acc.result().numpy()
这将导致以下准确度得分:
0.5
注意
TensorFlow 并没有为空准确度指标提供一个类,但你可以通过使用 Accuracy(),并提供一个仅包含 1(或 0)的预测张量,轻松计算它。
精确度、召回率和 F1 分数
在上一节中,你学习了如何使用准确度指标来评估模型的表现,并将其与称为“空准确度”的基准进行比较。准确度得分被广泛使用,因为它对于非技术性听众来说是熟知的,但它也有一些局限性。考虑以下示例。
图 5.18:模型预测与实际值的示例
该模型的准确度得分为 0.981!,这个值相当高。但如果这个模型用于预测一个人是否患有某种疾病,它只会在一个案例中预测正确。在其他九个案例中,它错误地预测这些人没有得病,而实际上他们有该疾病。同时,它错误地预测了 10 个实际上健康的人为患病。由此可见,这个模型的表现显然不令人满意。不幸的是,准确率得分只是一个整体得分,它并不能告诉你模型表现不好的地方。
幸运的是,其他指标可以更好地评估模型,比如精确度、召回率或 F1 分数。这三项指标的取值范围与准确率得分相同:1 表示完美得分,所有观察值都预测正确,0 是最差得分,意味着没有任何正确的预测。
但在查看它们之前,你需要了解以下定义:
-
真阳性(TP):所有实际值和相应预测都为真(即正类)的观察值
-
真负(TN):所有实际值和相应预测都为假(即负类)的观察值
-
假阳性(FP):所有预测为真,但实际值为假的观察值
-
假阴性(FN):所有预测为假,但实际值为真的观察值
以 图 5.18 为例,你将得到以下结果:
-
TP = 1
-
TN = 980
-
FP = 10
-
FN = 9
这在下表中可以看到:
图 5.19:TP、TN、FP 和 FN 示例
精确度得分是一个评估模型是否预测了大量假阳性的指标。其公式如下:
图 5.20:精确度公式
在前面的例子中,精确度得分为 。你可以看到该模型犯了很多错误,并且预测了大量的假阳性(FP),而实际的真阳性(TP)则相对较少。
召回率用于评估假阴性(FN)与真阳性(TP)之比。其公式如下:
图 5.21:召回率公式
在前面的例子中,召回率得分为 。通过这个指标,你可以看到模型表现不好,预测了大量的假阴性(FN)。
最后,F1 分数是一个结合了精确度和召回率的指标(它是精确度和召回率的调和平均数)。其公式如下:
图 5.22:F1 分数的公式
以与前述相同的例子,F1 分数将为
模型实现了0.095的 F1 分数,这与其0.981的准确度分数非常不同。因此,当你希望强调不正确的预测时,F1 分数是一个很好的性能指标——该分数考虑了 FN 和 FP 的数量,以及 TP 和 TN。
注意
与准确度、精确度和召回率性能指标一样,F1 分数也可应用于其他类型的分类。
你可以通过使用Precision()和Recall()的相应类来轻松计算 TensorFlow 中的精确度和召回率:
from tensorflow.keras.metrics import Precision, Recall
preds = [1, 1, 1, 1, 0, 0]
target = [1, 0, 1, 0, 1, 0]
prec = Precision()
prec.update_state(preds, target)
print(f"Precision: {prec.result().numpy()}")
rec = Recall()
rec.update_state(preds, target)
print(f"Recall: {rec.result().numpy()}")
这导致以下输出:
图 5.23:提供示例的精确度和召回率分数
注意
TensorFlow 并未提供用于计算 F1 分数的类,但可以通过创建自定义指标来轻松实现这一功能。这将在练习 5.02,分类评估指标中介绍。
混淆矩阵
混淆矩阵本身并不是一个性能指标,而更多是用于可视化模型预测与实际值之间关系的图形工具。在前一节中,你已经看到了图 5.18 的一个示例。
混淆矩阵将显示预测值(例如,水平轴)和实际值(例如,垂直轴)的所有可能值。在每个预测和实际值组合的交点处,你将记录属于此情况的观察数。
对于二元分类,混淆矩阵如下所示:
图 5.24:二元分类的混淆矩阵
理想情况是所有值都位于该矩阵的对角线上。这意味着你的模型正确预测了所有可能的值。在对角线之外的所有值是模型犯错的地方。
注意
混淆矩阵也可用于多类分类,不仅限于二元分类。
运行下面的代码查看混淆矩阵:
from tensorflow.math import confusion_matrix
preds = [1, 1, 1, 1, 0, 0]
target = [1, 0, 1, 0, 1, 0]
print(confusion_matrix(target, preds))
这将显示以下输出:
图 5.25:TensorFlow 混淆矩阵
前述输出显示了混淆矩阵。从中可以看出,模型预测了以下结果:两个 TP、一个 TN、两个 FP 和一个 FN。
在下一练习中,你将应用这些性能指标到与练习 5.01,构建逻辑回归模型相同的逻辑回归模型。
练习 5.02:分类评估指标
在本练习中,你将重复使用与练习 5.01,构建逻辑回归模型相同的逻辑回归模型,并通过查看不同的性能指标来评估其性能:准确度、精确度、召回率和 F1 分数。
原始数据集由悉尼大学的 Stephen Tridgell 分享。
注意
训练数据集可以通过以下链接访问:packt.link/QJGpA。
测试数据集可以通过以下链接访问:packt.link/ix5rW。
练习 5.01中的模型,构建逻辑回归模型,可以通过以下链接找到:packt.link/sSRQL。
现在,运行以下指令:
-
打开一个新的 Jupyter 笔记本。
-
导入 pandas 库,并使用
pd作为别名:import pandas as pd -
创建一个名为
train_url的变量,包含训练集的 URL:train_url = 'https://raw.githubusercontent.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/master/Chapter05/dataset'\ '/dota2PreparedTrain.csv' -
使用
read_csv()方法将训练数据集加载到名为X_train的DataFrame()函数中,提供 CSV 文件的 URL,并设置header=None,因为数据集没有提供列名:X_train = pd.read_csv(train_url, header=None) -
使用
pop()方法提取目标变量(第0列),并将其保存在名为y_train的变量中:y_train = X_train.pop(0) -
创建一个名为
test_url的变量,包含测试集的 URL:test_url = 'https://raw.githubusercontent.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/master/Chapter05/dataset'\ '/dota2PreparedTest.csv' -
使用
read_csv()方法将测试数据集加载到名为X_test的DataFrame()函数中,提供 CSV 文件的 URL,并设置header=None,因为数据集没有提供列名:X_test = pd.read_csv(test_url, header=None) -
使用
pop()方法提取目标变量(第0列),并将其保存在名为y_test的变量中:y_test = X_test.pop(0) -
使用
tf作为别名导入tensorflow库,并从tensorflow.keras.utils导入get_file()方法:import tensorflow as tf from tensorflow.keras.utils import get_file -
创建一个名为
model_url的变量,包含模型的 URL:model_url = 'https://github.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/blob/master/Chapter05'\ 'model/exercise5_01_model.h5?raw=true' -
使用
get_file()方法,通过提供文件名(exercise5_01_model.h5)及其 URL 将模型下载到本地。将输出保存到一个名为model_path的变量中:model_path = get_file('exercise5_01_model.h5', model_url) -
使用
tf.keras.models.load_model()加载模型,并指定模型的本地路径:model = tf.keras.models.load_model(model_path) -
使用
summary()方法打印模型摘要:model.summary()预期的输出如下:
图 5.26:模型总结
上述输出展示了与练习 5.01中相同的架构,即构建逻辑回归模型。
-
使用
predict()方法预测测试集的结果。将其保存在一个名为preds_proba的变量中,并显示其前五个值:preds_proba = model.predict(X_test) preds_proba[:5]预期的输出如下:
图 5.27:测试集的预测概率
输出为每个观察值为
1(或为真)的预测概率。你需要将这些概率转换为0和1。为此,你需要将所有概率大于或等于0.5的情况视为1(或为真),而对于概率小于0.5的记录则视为0(或为假)。 -
当预测概率大于或等于
0.5时,将其转换为1,当小于0.5时转换为0。将结果保存在名为preds的变量中,并打印其前五行:preds = preds_proba >= 0.5 preds[:5]预期的输出如下:
图 5.28:测试集的预测结果
现在,预测结果已转换为二值:真(等于
1)和假(等于0)。 -
从
tensorflow.keras.metrics导入Accuracy、Precision和Recall:from tensorflow.keras.metrics import Accuracy, Precision, Recall -
实例化
Accuracy、Precision和Recall对象,并将其保存在名为acc、pres和rec的变量中:acc = Accuracy() prec = Precision() rec = Recall() -
使用
update_state()、result()和numpy()方法计算测试集上的准确度分数。将结果保存在名为acc_results的变量中并打印其内容:acc.update_state(preds, y_test) acc_results = acc.result().numpy() acc_results预期的输出如下:
0.59650314该模型的准确率为
0.597。 -
使用
update_state()、result()和numpy()方法计算测试集上的精确度分数。将结果保存在名为prec_results的变量中并打印其内容:prec.update_state(preds, y_test) prec_results = prec.result().numpy() prec_results预期的输出如下:
0.59578335该模型的精确度为
0.596。 -
使用
update_state()、result()和numpy()方法计算测试集上的召回率分数。将结果保存在名为rec_results的变量中并打印其内容:rec.update_state(preds, y_test) rec_results = rec.result().numpy() rec_results预期的输出如下:
0.6294163该模型的召回率为
0.629。 -
使用上一节中显示的公式计算 F1 分数。将结果保存在名为
f1的变量中并打印其内容:f1 = 2*(prec_results * rec_results) / (prec_results + rec_results) f1预期的输出如下:
0.6121381493171637总体而言,模型在准确率、精确度、召回率和 F1 分数这四个不同指标上都取得了接近
0.6的较低分数。因此,该模型的正确预测和错误预测几乎一样多。你可以尝试自己构建另一个模型,看看是否能提高其表现。
在接下来的部分,你将学习如何通过多类分类将分类扩展到超过两个可能值。
多类分类
使用二分类时,你只能处理目标变量,它只能取两个可能的值:0和1(假或真)。多类分类可以看作是二分类的扩展,它允许目标变量拥有超过两个值(或者可以说,二分类是多类分类的一个子集)。例如,预测患者疾病严重程度的模型,或者根据用户过去的购物行为将其分类到不同组的模型,都属于多类分类器。
在下一节中,你将深入了解 Softmax 函数,它用于多类分类。
Softmax 函数
二分类器需要为神经网络的最后一个全连接层使用特定的激活函数,即 sigmoid。多类分类器的激活函数不同,它是 softmax。其公式如下:
图 5.29:Softmax 函数公式
对应于类别
i的预测值。
对应于类别
j的预测值。
此公式将应用于目标变量的每个可能值。如果有 10 个可能的值,那么该激活函数将计算 10 个不同的 softmax 值。
注意,softmax 会对分子和分母上的预测值进行指数运算。其背后的原因是,指数函数放大了预测值之间的微小变化,并使得概率更接近0或1,以便更好地解释最终的输出。例如,exp(2) = 7.39,而exp(2.2) = 9.03。因此,如果两个类别的预测值非常接近,它们的指数化值之间的差异将变得更大,从而更容易选择较大的一个。
softmax 函数的结果介于0和1之间,因为该方法将一个类别的值除以所有类别值的总和。因此,softmax 函数的实际输出是相关类别为最终预测结果的概率:
图 5.30:Softmax 转换示例
在前面的示例中,目标变量有五个不同的值,softmax 函数将它们转换为概率。第一个类别(0)是具有最高概率的类别,这将是最终的预测结果。
类别交叉熵
多类分类还需要一个特定的损失函数,这与二分类器使用的二元交叉熵不同。对于多类分类,损失函数是类别交叉熵。其公式如下:
图 5.31:类别交叉熵的公式
表示观察值
i属于类别j的实际值的概率。
表示观察值
i属于类别j的预测概率。
TensorFlow 提供了两个不同的类别来计算这个损失函数:CategoricalCrossentropy() 和 SparseCategoricalCrossentropy():
from tensorflow.keras.losses import CategoricalCrossentropy,
SparseCategoricalCrossentropy
cce = CategoricalCrossentropy()
scce = SparseCategoricalCrossentropy()
它们之间的区别在于目标变量的格式。如果实际值以独热编码存储,表示实际类别,则需要使用 CategoricalCrossentropy()。另一方面,如果响应变量以整数形式存储,表示实际类别,则需要使用 SparseCategoricalCrossentropy():
图 5.32:根据目标变量的格式使用的损失函数
多类模型的输出将是一个包含每个类别概率的向量,如下所示:
import numpy as np
preds_proba = np.array([0.54, 0.16, 0.09, 0.15, 0.06])
第一个值(0.54)对应于索引 0 类别的概率,0.016 是索引 1 类别的概率,而 0.09 对应于索引 2 类别的概率,依此类推。
为了得到最终的预测(即具有最高概率的类别),你需要使用 argmax() 函数,它会查看向量中的所有值,找到最大值并返回与其相关的索引:
preds_proba.argmax()
这将显示以下输出:
0
在前面的例子中,最终的预测是 类别 0,这对应于具有最高概率(0.54)的向量索引。
多类分类架构
多类分类器的架构与逻辑回归非常相似,区别在于最后一层将包含更多的单元。每个单元对应于目标变量的一个类。例如,如果你正在构建一个输入向量大小为 6 并使用单一隐藏层预测具有三种不同值的响应的模型,则其架构如下所示:
图 5.33:多类分类器的架构
最后一层的 softmax 激活函数为每个可能类别提供了发生的概率:A、B 和 C。这些概率是相互依赖的,因为最终应该只预测一个类别。如果类别 A 更有可能成为预测(如前面的例子所示),那么其余类别(B 和 C)的概率应该较低。请注意,所有类别的概率总和为 1,因此它们确实是相互依赖的。
现在你已经了解了所有的构建模块,可以在接下来的练习中构建一个多类分类器。
练习 5.03:构建一个多类模型
在本练习中,你将使用 TensorFlow 构建并训练一个多类分类器,该分类器将使用数据集中提供的九个不同的数值特征,从八个不同的值预测航天飞机的散热器位置。
目标变量(最后一列)包含七个不同的级别:Rad.Flow、Fpv.Close、Fpv.Open、High、Bypass、Bpv.Close 和 Bpv.Open。你的目标是使用数据集中提供的九个特征准确预测这七个级别中的一个。
注意
训练数据集可以通过以下链接访问:packt.link/46iMY。
测试数据集可以通过以下链接访问:packt.link/dcNPt。
原始数据集可以通过以下链接找到:archive.ics.uci.edu/ml/datasets/Statlog+%28Shuttle%29。
执行以下步骤以完成练习:
-
打开一个新的 Jupyter 笔记本。
-
导入 pandas 库并使用
pd作为别名:import pandas as pd -
创建一个名为
train_url的变量,包含训练集的 URL:train_url = 'https://raw.githubusercontent.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/master/Chapter05'\ '/dataset/shuttle.trn' -
使用
read_table()方法将训练数据集加载到名为X_train的 DataFrame 中,提供 CSV 文件的 URL,使用header=None因为数据集没有列名,使用sep=' '因为数据集中的每一列是由空格分隔的。使用head()方法打印前五行:X_train = pd.read_table(train_url, header=None, sep=' ') X_train.head()预期的输出将如下所示:
图 5.34:训练集的前五行
可以看到数据集包含 10 列,且都是数字类型。另外,注意目标变量(第
9列)包含不同的类别值。 -
使用
pop()方法提取目标变量(第9列),并将其保存在名为y_train的变量中:y_train = X_train.pop(9) -
创建一个名为
test_url的变量,包含测试集的 URL:test_url = 'https://raw.githubusercontent.com/PacktWorkshops'\ '/The-TensorFlow-Workshop/master/Chapter05/dataset'\ '/shuttle.tst' -
使用
read_table()方法将测试数据集加载到名为X_test的 DataFrame 中,提供 CSV 文件的 URL,设置header=None因为数据集没有列名,使用sep=' '因为数据集中的每一列是由空格分隔的。使用head()方法打印前五行。X_test = pd.read_table(test_url, header=None, sep=' ') X_test.head()预期的输出将如下所示:
图 5.35:测试集的前五行
可以看到测试集与训练集非常相似。
-
使用
pop()方法提取目标变量(第9列),并将其保存在名为y_test的变量中:y_test = X_test.pop(9) -
导入 TensorFlow 库并使用
tf作为别名:import tensorflow as tf -
使用
tf.random.set_seed()将 TensorFlow 的种子设置为8,以获得可重现的结果:tf.random.set_seed(8) -
使用
tf.keras.Sequential()实例化一个顺序模型,并将其保存在一个名为model的变量中:model = tf.keras.Sequential() -
从
tensorflow.keras.layers导入Dense()类:from tensorflow.keras.layers import Dense -
使用
Dense()创建一个包含512单元的全连接层,并指定 ReLu 作为激活函数,同时将输入形状设置为(9,),这对应于数据集中的特征数量。将其保存在一个名为fc1的变量中:fc1 = Dense(512, input_shape=(9,), activation='relu') -
使用
Dense()创建一个包含512单元的全连接层,并指定 ReLu 作为激活函数。将其保存在一个名为fc2的变量中:fc2 = Dense(512, activation='relu') -
使用
Dense()创建一个包含128单元的全连接层,并指定 ReLu 作为激活函数。将其保存在一个名为fc3的变量中:fc3 = Dense(128, activation='relu') -
再次使用
Dense()创建一个包含128单元的全连接层,并指定 ReLu 作为激活函数。将其保存在一个名为fc4的变量中:fc4 = Dense(128, activation='relu') -
使用
Dense()创建一个包含 128 单元的全连接层,并指定 softmax 作为激活函数。将其保存在一个名为fc5的变量中:fc5 = Dense(8, activation='softmax') -
顺序地将所有五个全连接层添加到模型中,使用
add()方法。model.add(fc1) model.add(fc2) model.add(fc3) model.add(fc4) model.add(fc5) -
使用
summary()方法打印模型的摘要:model.summary()预期的输出将如下所示:
图 5.36:模型架构的总结
上述输出显示了模型中的五个层(如预期),并告知每个层的参数数量。例如,第一层包含
5,120个参数,该模型的总参数数量为350,984。所有这些参数将在拟合模型时进行训练。 -
从
tf.keras.losses中实例化SparseCategoricalCrossentropy(),并将其保存在名为loss的变量中:loss = tf.keras.losses.SparseCategoricalCrossentropy() -
从
tf.keras.optimizers中实例化Adam(),将学习率设置为0.001,并将其保存在名为optimizer的变量中:optimizer = tf.keras.optimizers.Adam(0.001) -
使用
compile()方法编译模型,指定优化器和损失参数,并将准确度作为需要报告的度量:model.compile(optimizer=optimizer, loss=loss, \ metrics=['accuracy']) -
使用
fit()方法在训练集上开始模型训练过程,训练五个 epochs:model.fit(X_train, y_train, epochs=5)预期输出如下所示:
图 5.37:训练过程的日志
上述输出显示了训练过程中每个 epoch 的日志。请注意,处理一个 epoch 大约需要 7 秒,损失值从
0.5859(第一 epoch)降至0.0351(第五 epoch)。 -
使用
evaluate()方法评估模型在测试集上的表现:model.evaluate(X_test, y_test)预期输出如下所示:
图 5.38:模型在测试集上的表现
在这个练习中,你学习了如何构建和训练一个多类分类器,来预测由八个不同类别组成的结果。你的模型在训练集和测试集上的准确率接近0.997,这非常了不起。这意味着你的模型在大多数情况下能正确预测类别。
现在,让我们在下面的活动中巩固你的学习。
活动 5.01:使用 TensorFlow 构建字符识别模型
在这个活动中,你的任务是构建和训练一个多类分类器,该分类器能够识别图像中的 26 个字母。在这个数据集中,图像已经转换为 16 个不同的统计特征,这些特征将作为我们的输入。该模型的目标是确定每个观测值属于 26 个字母中的哪一个。
原始数据集由 Odesta 公司 David J. Slate 分享,数据集可以在此找到:archive.ics.uci.edu/ml/datasets/Letter+Recognition。
数据集可以从这里访问:packt.link/j8m3L。
以下步骤将帮助你完成该活动:
-
使用 pandas 的
read_csv()加载数据。 -
使用 pandas 的
pop()方法提取目标变量。 -
将数据分为训练集(前 15,000 行)和测试集(后 5,000 行)。
-
使用五个完全连接的层,分别为
512、512、128、128和26个单元,来构建多类分类器。 -
在训练集上训练这个模型。
-
使用
evaluate()方法从 TensorFlow 评估模型在测试集上的表现。 -
使用
confusion_matrix()方法从 TensorFlow 打印混淆矩阵。预期的输出如下:
图 5.39:测试集的混淆矩阵
注意
该活动的解决方案可以通过这个链接找到。
多标签分类
多标签分类是另一种分类类型,在这种类型中,你不仅预测一个目标变量(如二元分类或多类分类),而是同时预测多个响应变量。例如,你可以预测图像中不同物体的多个输出(例如,模型将预测给定图片中是否有猫、男人和汽车),或者你可以预测文章的多个主题(例如,文章是否涉及经济、国际新闻和制造业)。
使用神经网络实现多标签分类非常简单,你已经学会了构建它所需的一切。在 TensorFlow 中,多标签分类器的架构与多类分类器相同,最终的输出层有多个单元,对应于你要预测的目标变量的数量。但不同的是,你将使用 sigmoid 作为激活函数,binary cross-entropy 作为损失函数,而不是使用 softmax 和 categorical cross-entropy。
Sigmoid 函数将预测每个目标变量的发生概率:
图 5.40:多标签分类器的架构
在前面的示例中,你有三个目标变量,每个目标变量的发生概率是相互独立的(它们的和不会等于 1)。该模型预测目标2和3很可能是这个观测的输出。
从概念上讲,多标签分类结合了多个逻辑回归模型。它们将共享相同的参数(权重和偏差),但每个模型有独立的二进制输出。TensorFlow 中多类分类器的最后一层将像这样:
from tensorflow.keras.layers import Dense
Dense(3, activation='sigmoid')
将要使用的损失函数是二元交叉熵:
from tensorflow.keras.losses import BinaryCrossentropy
bce = BinaryCrossentropy()
现在,将你所学到的知识付诸实践,在以下活动中动手操作。
活动 5.02:使用 TensorFlow 构建电影类型标签模型
在这个活动中,你的任务是构建并训练一个多标签分类器,该分类器将预测电影的类型,涵盖 28 种可能的类别。每部电影可以同时被分配到多个类型。特征是从电影简介中提取的主要关键词。该活动使用的数据集是原始数据集的一个子集,包含了 20,000 行数据。
原始数据集由 IMDb 提供,可以从这里找到:www.uco.es/kdis/mllresources/#ImdbDesc。
数据集的特征可以从这里访问:packt.link/yW5ru。
数据集的目标可以从这里访问:packt.link/8f1mb。
以下步骤将帮助你完成该活动:
-
使用 pandas 的
read_csv()加载特征和目标。 -
将数据分为训练集(前 15,000 行)和测试集(后 5,000 行)。
-
构建一个多类别分类器,包含五个全连接层,分别是
512、512、128、128和28个单元。 -
在训练集上训练此模型。
-
使用 TensorFlow 的
evaluate()方法在测试集上评估其性能。预期的输出如下:
图 5.41:活动 5.02 的预期输出
注意
这个活动的解决方案可以通过此链接找到。
总结
本章开始时,你介绍了分类模型,并与回归模型进行了对比。你了解到,分类器的目标变量只能包含有限数量的可能值。
接着你探索了二元分类,其中响应变量只能取两个可能的值:0 或 1。你深入了解了如何使用 TensorFlow 构建逻辑回归模型,采用 sigmoid 激活函数和二元交叉熵作为损失函数,并为预测视频游戏《Dota 2》中的获胜队伍构建了自己的二元分类器。
之后,你了解了可以用来评估分类器模型性能的不同指标。你练习了使用 TensorFlow 计算准确率、精确度、召回率和 F1 分数,并绘制了混淆矩阵,这是一个用来查看模型正确与错误预测的可视化工具。
接着你深入探讨了多类别分类的主题。这类模型与二元分类器的区别在于,它们的响应变量可以有两个以上的可能值。你研究了 softmax 激活函数和类别交叉熵损失函数,它们在 TensorFlow 中用于训练这类模型。
最后一部分,你了解了多标签分类,其中输出可以同时是多个类别。在 TensorFlow 中,这样的模型可以通过构建类似于多类别分类的架构来轻松实现,但分别使用 sigmoid 激活函数和二元交叉熵作为损失函数。
在下一章,你将学习如何通过应用一些正则化技术来防止模型过拟合,从而帮助模型更好地对未见数据进行泛化。