1. 概览
在本实验中,您将学习如何构建 Keras 分类器。我们不会尝试找出识别花朵的完美神经网络层组合,而是先使用一种称为迁移学习的技术,将强大的预训练模型调整为适合我们的数据集。
本实验包含有关神经网络的必要理论说明,是开发者学习深度学习的良好起点。
本实验是“Keras on TPU”系列实验的第 2 部分。您可以按以下顺序执行这些步骤,也可以单独执行。
- TPU 速度数据流水线:tf.data.Dataset 和 TFRecords
- [本实验] 您的第一个 Keras 模型,使用迁移学习
- 使用 Keras 和 TPU 的卷积神经网络
- 现代卷积神经网络、squeezenet、Xception 以及 Keras 和 TPU

学习内容
- 使用 softmax 层和交叉熵损失构建自己的 Keras 图片分类器
- 作弊方法 😈:使用迁移学习,而不是构建自己的模型。
反馈
如果您在此 Codelab 中发现任何问题,请告诉我们。您可以通过 GitHub 问题 [反馈链接] 提供反馈。
2. Google Colaboratory 快速入门
本实验使用 Google Colaboratory,无需您进行任何设置。Colaboratory 是一个在线笔记本平台,可用于教育目的。它提供免费的 CPU、GPU 和 TPU 训练。

您可以打开此示例笔记本并运行几个单元格,以便熟悉 Colaboratory。
选择 TPU 后端

在 Colab 菜单中,依次选择运行时 > 更改运行时类型,然后选择 TPU。在此代码实验中,您将使用强大的 TPU(张量处理单元)来支持硬件加速训练。首次执行时,系统会自动连接到运行时,您也可以使用右上角的“连接”按钮。
笔记本执行

点击某个单元格,然后使用 Shift-Enter 逐个执行单元格。您还可以通过依次选择运行时 > 全部运行来运行整个笔记本
目录

所有笔记本都有目录。您可以使用左侧的黑色箭头打开该菜单。
隐藏单元格

部分单元格将仅显示其标题。这是 Colab 特有的笔记本功能。您可以双击它们来查看其中的代码,但通常不会很有趣。通常是支持或可视化函数。您仍需运行这些单元格,以便定义其中的函数。
Authentication

只要您使用已获授权的账号进行身份验证,Colab 就可以访问您的私有 Google Cloud Storage 存储分区。上述代码段将触发身份验证流程。
3. [信息] 神经网络分类器 101
简而言之
如果您已经了解下一段中所有粗体字词,则可以继续进行下一个练习。如果您刚刚开始学习深度学习,欢迎您,请继续阅读。
对于构建为层序列的模型,Keras 提供了 Sequential API。例如,使用三个密集层的图片分类器可以在 Keras 中编写为:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
tf.keras.layers.Dense(500, activation="relu"),
tf.keras.layers.Dense(50, activation="relu"),
tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])
# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy']) # % of correct answers
# train the model
model.fit(dataset, ... )

密集神经网络
这是用于对图像进行分类的最简单的神经网络。它由分层排列的“神经元”组成。第一层处理输入数据,并将其输出提供给其他层。之所以称为“密集”,是因为每个神经元都与前一层中的所有神经元相连。

您可以将图片输入到此类网络中,方法是将所有像素的 RGB 值展平为一个长向量,并将其用作输入。虽然这不是最佳的图像识别技术,但我们稍后会对其进行改进。
神经元、激活、RELU
“神经元”会计算所有输入的加权和,添加一个称为“偏差”的值,并通过所谓的“激活函数”馈送结果。权重和偏差最初是未知的。它们将随机初始化,并通过基于大量已知数据训练神经网络来“学习”。

最常用的激活函数是 RELU(修正线性单元)。如上图所示,这是一个非常简单的函数。
Softmax 激活函数
上述网络的末尾是一个 5 个神经元的层,因为我们要将花卉分为 5 个类别(玫瑰、郁金香、蒲公英、雏菊、向日葵)。中间层中的神经元使用经典的 RELU 激活函数进行激活。不过,在最后一层中,我们希望计算介于 0 到 1 之间的数字,表示相应花朵是玫瑰、郁金香等的概率。为此,我们将使用一种名为“softmax”的激活函数。
对向量应用 softmax 函数的方法是,先计算每个元素的指数,然后对向量进行归一化处理(通常使用 L1 范数,即绝对值之和),使值总和为 1,从而可以解释为概率。

交叉熵损失
现在,我们的神经网络可以根据输入图片生成预测结果,我们需要衡量这些结果的准确性,即网络给出的结果与正确答案(通常称为“标签”)之间的距离。请注意,我们已为数据集中的所有图片添加了正确的标签。
任何距离都可以,但对于分类问题,所谓的“交叉熵距离”是最有效的。我们将此函数称为误差或“损失”函数:

梯度下降法
“训练”神经网络实际上是指使用训练图片和标签来调整权重和偏差,以最大限度地减少交叉熵损失函数。具体运作方式如下。
交叉熵是权重、偏差、训练图像的像素及其已知类别的函数。
如果我们计算相对于所有权重和所有偏差的交叉熵偏导数,就会得到一个“梯度”,该梯度是针对给定的图片、标签以及当前权重和偏差值计算得出的。请注意,我们可能有数百万个权重和偏差,因此计算梯度听起来像是一项非常繁重的工作。幸运的是,Tensorflow 可以帮我们完成这项工作。梯度的数学属性是它指向“上方”。由于我们希望前往交叉熵较低的位置,因此我们朝相反的方向前进。我们通过梯度的一小部分来更新权重和偏差。然后,我们在训练循环中,使用下一批训练图片和标签反复执行相同的操作。希望这会收敛到交叉熵最小的位置,尽管无法保证此最小值是唯一的。

小批次和动量
您可以仅根据一张示例图片计算梯度并立即更新权重和偏差,但如果根据一批(例如 128 张)图片计算梯度,则得到的梯度能更好地表示不同示例图片施加的限制,因此更有可能更快地收敛到解决方案。小批次的大小是一个可调整的参数。
这种有时称为“随机梯度下降法”的技术还有另一个更实用的好处:处理批次也意味着处理更大的矩阵,而这些矩阵通常更易于在 GPU 和 TPU 上进行优化。
不过,收敛可能仍然有点混乱,如果梯度向量全为零,甚至可能会停止。这是否意味着我们找到了最小值?不一定。梯度分量在最小值或最大值处可以为零。如果梯度向量有数百万个元素,并且这些元素全部为零,那么每个零都对应一个最小值,而没有一个零对应最大值的概率非常小。在多维空间中,鞍点非常常见,我们不希望停留在鞍点。

图示:鞍点。梯度为 0,但它在所有方向上都不是最小值。(图片提供方信息 维基媒体:Nicoguaro - 自制作品,CC BY 3.0)
解决方案是为优化算法增加一些动量,使其能够顺利通过鞍点而不停止。
术语库
批次或小批次:始终基于批次的训练数据和标签进行训练。这样做有助于算法收敛。“批次”维度通常是数据张量的第一个维度。例如,形状为 [100, 192, 192, 3] 的张量包含 100 张 192x192 像素的图片,每张图片包含三个值(RGB)。
交叉熵损失:一种常用于分类器的特殊损失函数。
密集层:一种神经元层,其中每个神经元都与上一层中的所有神经元相连。
特征:神经网络的输入有时称为“特征”。确定将数据集的哪些部分(或部分组合)馈送到神经网络以获得良好预测结果的技巧称为“特征工程”。
标签:监督式分类问题中“类别”或正确答案的另一种名称
学习速率:在训练循环的每次迭代中,权重和偏差更新所依据的梯度分数。
logits:在应用激活函数之前,神经元层的输出称为“logits”。该术语源自“logistic 函数”(也称为“S 型函数”),后者曾经是最热门的激活函数。“Neuron outputs before logistic function”(逻辑函数之前的神经元输出)缩短为“logits”。
损失:将神经网络输出与正确答案进行比较的误差函数
神经元:计算输入的加权和,添加偏差,并通过激活函数馈送结果。
独热编码:5 个类别中的第 3 个类别编码为包含 5 个元素的向量,其中第 3 个元素为 1,其余元素均为 0。
relu:修正线性单元。一种常用的神经元激活函数。
sigmoid:另一种曾经很受欢迎的激活函数,在特殊情况下仍然有用。
softmax:一种特殊的激活函数,可作用于向量,增大最大分量与所有其他分量之间的差值,还会将向量归一化为总和为 1,以便将其解读为概率向量。用作分类器的最后一步。
张量:“张量”类似于矩阵,但具有任意数量的维度。一维张量是向量。二维张量是矩阵。然后,您可以拥有 3 维、4 维、5 维或更多维度的张量。
4. 迁移学习
对于图像分类问题,密集层可能不够。我们必须了解卷积层以及排列卷积层的多种方式。
但我们也可以走捷径!您可以下载经过完整训练的卷积神经网络。您可以截断它们的最后一层(即 softmax 分类头),并替换为您自己的层。所有训练后的权重和偏差保持不变,您只需重新训练添加的 softmax 层。这种技术称为迁移学习。令人惊讶的是,只要预训练神经网络所用的数据集与您的数据集“足够接近”,这种技术就能发挥作用。
动手
请打开以下笔记本,执行单元格(按 Shift-Enter 键),然后按照标有“需要完成的工作”的说明操作。
Keras Flowers transfer learning (playground).ipynb
其他信息
借助迁移学习,您可以同时受益于顶尖研究人员开发的高级卷积神经网络架构,以及在庞大的图片数据集上进行的预训练。在本例中,我们将从在 ImageNet(一个包含许多植物和户外场景的图片数据库)上训练的网络进行迁移学习,这与花卉足够接近。

图示:使用已训练的复杂卷积神经网络作为黑盒,仅重新训练分类头。这就是迁移学习。我们稍后将了解这些复杂的卷积层排列方式是如何运作的。目前,这是其他人的问题。
Keras 中的迁移学习
在 Keras 中,您可以从 tf.keras.applications.* 集合实例化预训练模型。例如,MobileNet V2 是一种非常出色的卷积架构,其大小合理。选择 include_top=False 可获取不含最终 softmax 层的预训练模型,以便您添加自己的 softmax 层:
pretrained_model = tf.keras.applications.MobileNetV2(input_shape=[*IMAGE_SIZE, 3], include_top=False)
pretrained_model.trainable = False
model = tf.keras.Sequential([
pretrained_model,
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(5, activation='softmax')
])
另请注意 pretrained_model.trainable = False 设置。它会冻结预训练模型的权重和偏差,以便您仅训练 softmax 层。这通常涉及相对较少的权重,可以快速完成,并且不需要非常大的数据集。不过,如果您有大量数据,迁移学习与 pretrained_model.trainable = True 搭配使用效果会更好。预训练的权重随后会提供出色的初始值,并且仍可通过训练进行调整,以更好地适应您的问题。
最后,请注意插入到密集 softmax 层之前的 Flatten() 层。密集层可处理扁平数据向量,但我们不知道预训练模型是否会返回这种向量。因此,我们需要展平。在下一章中,我们将深入探讨卷积架构,并说明卷积层返回的数据格式。
采用这种方法,准确率应该接近 75%。
解决方案
以下是解决方案笔记本。如果您遇到困难,可以使用它。
Keras Flowers transfer learning (solution).ipynb
所学内容
- 🤔 如何在 Keras 中编写分类器
- 🤓 配置了 softmax 最后一层和交叉熵损失
- 😈 迁移学习
- 🤔 训练您的首个模型
- 🧐 跟踪模型在训练期间的损失和准确率
请花点时间在脑海中过一遍此核对清单。
5. 恭喜!
现在,您可以构建 Keras 模型了。请继续学习下一个实验,了解如何组装卷积层。
- TPU 速度数据流水线:tf.data.Dataset 和 TFRecords
- [本实验] 您的第一个 Keras 模型,使用迁移学习
- 使用 Keras 和 TPU 的卷积神经网络
- 现代卷积神经网络、squeezenet、Xception 以及 Keras 和 TPU
TPU 实践
Cloud AI Platform 提供 TPU 和 GPU:
- 在 Deep Learning VM 上
- 在 AI Platform Notebooks 中
- 在 AI Platform Training 作业中
最后,我们非常欢迎您提供反馈。如果您发现此实验有任何问题,或者认为此实验应进行改进,请告诉我们。您可以通过 GitHub 问题 [反馈链接] 提供反馈。

|

