GSP631
概览
TensorFlow 是一款由 Google 开发的可移植机器学习开源库,它功能强大,可处理超大型数据集。在本实验中,您将使用 TensorFlow Vertex AI Workbench 来创建并训练一个用于识别不同服饰类别的计算机视觉模型。
TensorFlow 简介
TensorFlow 提供了用于构建机器学习模型的计算框架,还提供了各种不同的工具包,让您能够以自己喜欢的抽象级别构建模型。在本实验中,您将使用 tf.keras(一种高级 API)在 TensorFlow 中构建和训练用于对图像进行分类的神经网络。
神经网络
神经网络是一种受大脑启发而创造的模型。它由多个层组成,其中至少有一层是隐藏层,该层由连接起来的简单单元(即神经元)以及相应的非线性关系组成。
神经网络中的节点通常会接受多个输入值,并生成一个输出值。神经元会对输入值的加权和应用激活函数(非线性转换),来计算输出值。
有关神经网络的更多信息,请参阅神经网络:结构。
目标
在本实验中,您将学习如何完成以下操作:
- 设计、编译、训练和评估 Tensorflow 模型
- 保存并加载模型
- 编写自己的回调,以在训练期间自定义模型行为
- 完成一系列练习,以对神经网络的不同层进行实验
设置和要求
点击“开始实验”按钮前的注意事项
请阅读以下说明。实验是计时的,并且您无法暂停实验。计时器在您点击开始实验后即开始计时,显示 Google Cloud 资源可供您使用多长时间。
此实操实验可让您在真实的云环境中开展实验活动,免受模拟或演示环境的局限。我们会为您提供新的临时凭据,让您可以在实验规定的时间内用来登录和访问 Google Cloud。
为完成此实验,您需要:
- 能够使用标准的互联网浏览器(建议使用 Chrome 浏览器)。
注意:请使用无痕模式或无痕浏览器窗口运行此实验。这可以避免您的个人账号与学生账号之间发生冲突,这种冲突可能导致您的个人账号产生额外费用。
注意:如果您已有自己的个人 Google Cloud 账号或项目,请不要在此实验中使用,以避免您的账号产生额外的费用。
任务 1. 在 Vertex AI Workbench 中打开笔记本
-
在 Google Cloud 控制台的导航菜单中依次点击 Vertex AI > Workbench。
-
找到 实例,然后点击 Open JupyterLab(打开 JupyterLab)按钮。
Workbench 实例的 JupyterLab 界面会在新浏览器标签页中打开。
安装 TensorFlow 和其他软件包
-
在“启动器”菜单的其他下,选择终端。
-
检查是否已配置 Python 环境。复制以下命令并将其粘贴到终端中。
python --version
输出示例:
Python 3.10.14
- 运行以下命令以安装 TensorFlow 软件包。
pip3 install tensorflow
- 如需升级
pip3
,请在终端中运行以下命令。
pip3 install --upgrade pip
Pylint 是一款用于检查 Python 代码错误的工具,它可以突出显示 Python 源代码中的语法和格式问题。
- 运行以下命令以安装
pylint
软件包。
pip install -U pylint --user
- 安装
requirements.txt
文件中实验所需的软件包:
pip install -r requirements.txt
现在,您的环境已设置完毕!
任务 2. 创建新笔记本并导入库
-
点击 Workbench 左侧的 + 图标以打开新的启动器。
-
在“启动器”菜单的笔记本下,选择 Python3。
系统会显示一个新的 Jupyter 笔记本。如需详细了解如何使用 Jupyter 笔记本,请参阅 Jupyter 笔记本文档。
- 为 Cloud Logging 导入并配置
logging
和 google-cloud-logging
。在第一个单元中,添加以下代码:
# Import and configure logging
import logging
import google.cloud.logging as cloud_logging
from google.cloud.logging.handlers import CloudLoggingHandler
from google.cloud.logging_v2.handlers import setup_logging
cloud_logger = logging.getLogger('cloudLogger')
cloud_logger.setLevel(logging.INFO)
cloud_logger.addHandler(CloudLoggingHandler(cloud_logging.Client()))
cloud_logger.addHandler(logging.StreamHandler())
- 导入
tensorflow
以训练和评估模型。为了便于使用,将其命名为 tf
。在第一个单元中添加以下代码。
# Import TensorFlow
import tensorflow as tf
- 导入
numpy
来解析数据,以进行调试。为便于使用,将其命名为 np
。在第一个单元中添加以下代码。
# Import numpy
import numpy as np
- 在第一个单元中添加以下代码,以导入
tensorflow_datasets
来集成数据集。TensorFlow Datasets 是一系列可用于 TensorFlow 的数据集的集合。
如需详细了解如何使用该数据集集合,请参阅相应指南和数据集列表。
# Import tensorflow_datasets
import tensorflow_datasets as tfds
-
如需运行该单元,请点击运行按钮或按 Shift + Enter。
-
保存笔记本。依次点击文件 -> 保存。将该文件命名为 model.ipynb
,然后点击确定。
任务 3. 加载并预处理数据集
关于数据集
您将训练一个神经网络,并用其对名为 Fashion MNIST 的数据集中的服饰图像进行分类。
该数据集包含来自 10 个不同服饰类别的共 70,000 件服饰。这些图像以较低的分辨率(28x28 像素)显示了各件服饰,如下方所示:
本实验将使用 60,000 张图像来训练神经网络,然后使用 10,000 张图像来评估在完成学习后,该网络在图像分类方面能够达到的准确率。
您可以在 tensorflow datasets (tfds) 中获得 Fashion MNIST 数据。
加载数据集
要加载 Fashion MNIST 数据,需使用 tfds.load()
函数。
- 在笔记本的第二个单元中添加以下代码:
# Define, load and configure data
(ds_train, ds_test), info = tfds.load('fashion_mnist', split=['train', 'test'], with_info=True, as_supervised=True)
在上面的代码中,您通过设置 split
参数来指定要加载的数据集分块。您还将 as_supervised
设置为 True
,以确保所加载的 tf.data.Dataset
具有 2 元组结构 (input, label)
。
ds_train 和 ds_test 均属于 tf.data.Dataset
类型。ds_train 具有 60,000 张图像,这些图像将用于训练模型。ds_test 具有 10,000 张图像,这些图像将用于评估模型。
如需详细了解 tfds.load()
及其参数,请查看相应指南。
这些值具体是什么样的?
- 接下来添加 print 语句,以查看批次为 0 的训练图像的最小值和最大值。在第二个单元中添加以下代码:
# Values before normalization
image_batch, labels_batch = next(iter(ds_train))
print("Before normalization ->", np.min(image_batch[0]), np.max(image_batch[0]))
数据预处理
-
批次大小是机器学习中使用的一个术语,指一次迭代中使用的训练示例数量。将此值设置为
32
。
在 model.ipynb
中添加以下代码,以指定批次大小:
# Define batch size
BATCH_SIZE = 32
- 在训练神经网络时,出于各种原因,将像素值缩放至 0 到 1 之间会更便于训练。此过程称为“归一化”。由于 FashionMNIST 数据集的像素值在 [0, 255] 范围内,因此需要将像素值除以 255.0,以便对图像进行归一化处理。
下方提供的代码使用 tf.data.Dataset
的 map()
函数对 ds_train
和 ds_test
中的图像进行了归一化处理。由于像素值属于 tf.uint8
类型,因此使用了 tf.cast
函数将其转换为 tf.float32
类型,然后再除以 255.0
。此外,还以 BATCH_SIZE
为参数调用了 batch()
方法,以便将数据集转换为批次。
如需详细了解可用于 tf.data.Dataset
的所有方法,请点击此处。
将以下代码添加到文件末尾:
# Normalize and batch process the dataset
ds_train = ds_train.map(lambda x, y: (tf.cast(x, tf.float32)/255.0, y)).batch(BATCH_SIZE)
ds_test = ds_test.map(lambda x, y: (tf.cast(x, tf.float32)/255.0, y)).batch(BATCH_SIZE)
- 再次添加 print 语句,以查看训练数据集中图像的最小值和最大值:
将以下代码添加到文件末尾:
# Examine the min and max values of the batch after normalization
image_batch, labels_batch = next(iter(ds_train))
print("After normalization ->", np.min(image_batch[0]), np.max(image_batch[0]))
任务 4. 设计、编译和训练模型
在本部分,您将使用 TensorFlow 来设计模型。
- 在文件中添加以下代码:
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
我们来看一下在模型架构中使用的不同类型的层和参数:
每一层神经元都需要有一个激活函数,该函数用于决定是否应激活神经元。此类函数有很多,本实验中使用的是以下函数。
-
Relu
的实际含义为:如果 X>0,则返回 X,否则返回 0。该函数会将 0 或更大值传递到网络中的下一层。
-
Softmax
会接受一组值并挑选出最大值,因此您无需排序即可找到最大值。例如,如果最后一层的输出为 [0.1, 0.1, 0.05, 0.1, 9.5, 0.1, 0.05, 0.05, 0.05],则它会返回 [0,0,0,0,1,0,0,0,0]。
编译和训练模型
在本部分,您需要先使用优化器和损失函数来编译模型,然后再基于训练数据和标签来训练模型。
目标是让模型找出训练数据与其标签之间的关系。训练完成后,您需要让模型查看与训练数据相似的新服饰图像,并预测它们所属的服饰类别。
优化器是编译 tf.keras 模型所需的两个参数之一。优化器 (optimizer
) 是一种可修改神经网络属性(如权重和学习速率)的算法,它有助于降低损失并提高准确率。
如需详细了解 tf.keras
中可用的不同类型的优化器,请点击此处。
损失 (loss
) 以数字形式表示模型的表现。如果模型表现较好,损失会表示为一个较小的数字。反之,损失则会表示为一个较大的数字。
如需详细了解 tf.keras
中可用的不同类型的损失函数,请点击此处。
请注意 metrics=
参数。通过该参数,TensorFlow 可将预测结果与已知答案(标签)进行比较,以报告每个训练周期完成后预测的准确率。简单来说,就是报告训练的实际进展情况。
如需详细了解“tf.keras”中可用的不同类型的指标,请点击此处。
Model.fit 将对模型训练固定数量的周期。
- 在文件中添加以下代码:
# Compile the model
model.compile(optimizer = tf.keras.optimizers.Adam(),
loss = tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
model.fit(ds_train, epochs=5)
点击“检查我的进度”以验证是否完成了以下目标: 创建机器学习模型
运行代码
- 点击运行按钮或按 Shift + Enter,以运行第二个单元。
执行该笔记本单元后,系统会报告每个周期(或每一遍)训练完成后实现的损失和准确率。请注意,每个周期(或每一遍)训练完成后,准确率都会有所提高:
输出示例(您获得的值可能会略有不同,请忽略任何警告消息):
Before normalization -> 0 227
After normalization -> 0.0 1.0
Epoch 1/5
1875/1875 [==============================] - 12s 6ms/step - loss: 0.5264 - sparse_categorical_accuracy: 0.8175
Epoch 2/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.3977 - sparse_categorical_accuracy: 0.8580
Epoch 3/5
1875/1875 [==============================] - 5s 3ms/step - loss: 0.3585 - sparse_categorical_accuracy: 0.8701
Epoch 4/5
1875/1875 [==============================] - 5s 2ms/step - loss: 0.3329 - sparse_categorical_accuracy: 0.8784
Epoch 5/5
1875/1875 [==============================] - 5s 2ms/step - loss: 0.3151 - sparse_categorical_accuracy: 0.8846
对于 # Values before normalization
部分的输出,您会发现最小值和最大值在 [0, 255]
范围内。进行归一化处理后,您可以看到所有值都在 [0, 1]
范围内。
随着训练继续进行,损失将会降低,准确率则会提高。
模型完成训练后,您会在最后一个周期结束时看到准确率值。该值可能接近上面的 0.8846(您获得的准确率值可能会有所不同)。
这表明,神经网络对训练数据进行分类的准确率约为 89%。换言之,它可以找出图像与标签之间的模式匹配,成功率达到 89%。这个表现不是很好,但考虑到它只是基于一个小型神经网络进行了 5 个周期的训练,所以表现也不算太坏。
任务 5. 评估模型针对未曾见过的数据的表现
对于未曾见过的数据,模型会有何种表现呢?
测试集可以帮助我们回答这个问题。您可以调用 model.evaluate
,传入两个测试集,模型便会报告每个测试集的损失。
评估测试集:
- 在笔记本的第三个单元中添加以下代码:
cloud_logger.info(model.evaluate(ds_test))
- 点击运行按钮或按 Shift + Enter,以运行该单元。
滚动到输出底部后,您可以在最后一行看到评估结果。
Before normalization -> 0 227
After normalization -> 0.0 1.0
Epoch 1/5
1875/1875 [==============================] - 12s 6ms/step - loss: 0.5264 - sparse_categorical_accuracy: 0.8175
Epoch 2/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.3977 - sparse_categorical_accuracy: 0.8580
Epoch 3/5
1875/1875 [==============================] - 5s 3ms/step - loss: 0.3585 - sparse_categorical_accuracy: 0.8701
Epoch 4/5
1875/1875 [==============================] - 5s 2ms/step - loss: 0.3329 - sparse_categorical_accuracy: 0.8784
Epoch 5/5
1875/1875 [==============================] - 5s 2ms/step - loss: 0.3151 - sparse_categorical_accuracy: 0.8846
313/313 [==============================] - 1s 4ms/step - loss: 0.3653 - sparse_categorical_accuracy: 0.8708
INFO:cloudLogger:[0.36530008912086487, 0.8708000183105469]
模型针对测试集 (ds_test
) 报告的准确率为 0.8708,即准确率约为 87%(您获得的值可能会略有不同)。
正如预期的那样,模型处理未知数据的准确率不像处理训练数据时那么高!
更深入地探索 TensorFlow 以后,您将了解如何改进这个方面。
点击“检查我的进度”以验证是否完成了以下目标: 使用模型
任务 6. 保存并加载模型
无论是训练期间还是训练之后,您都可以保存模型进度。这意味着,您可以从上次暂停的地方继续训练模型,从而避免长时间训练。可保存模型进度还意味着,您可以分享模型,以便他人基于您的工作成果进行“再创作”。在第一个练习中,您将添加必要的代码来保存并加载模型。
整个模型可以保存为两种不同的文件格式(SavedModel
和 Keras
)。TensorFlow SavedModel
格式是 TF2.x 中的默认文件格式,但模型也可以保存为 Keras
格式。您将详细了解如何以这两种文件格式保存模型。
- 在笔记本的第四个单元中添加以下代码:
# Save the entire model as a SavedModel.
model.save('saved_model')
# Reload a fresh Keras model from the saved model
new_model = tf.keras.models.load_model('saved_model')
# Summary of loaded SavedModel
new_model.summary()
# Save the entire model to a keras file.
model.save('my_model.keras')
# Recreate the exact same model, including its weights and the optimizer
new_model_keras = tf.keras.models.load_model('my_model.keras')
# Summary of loaded keras model
new_model_keras.summary()
上面的代码展示了如何以两种不同的格式保存模型,以及如何重新加载保存的模型。您可以根据自己的应用场景选择其中任何一种格式。如需详细了解此功能,请参阅有关如何“保存和加载模型”的 TensorFlow 文档。
- 点击运行按钮或按 Shift + Enter,以运行该单元。
在输出结果末尾,您会看到两组模型摘要。第一组显示的是模型以 SavedModel
格式保存后的摘要。第二组显示的是模型以 h5
格式保存后的摘要。
可以看到,两组模型摘要是相同的,因为我们实际上是以两种不同格式保存了同一模型。
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense (Dense) (None, 64) 50240
dense_1 (Dense) (None, 10) 650
=================================================================
Total params: 50,890
Trainable params: 50,890
Non-trainable params: 0
_________________________________________________________________
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
flatten (Flatten) (None, 784) 0
dense (Dense) (None, 64) 50240
dense_1 (Dense) (None, 10) 650
=================================================================
Total params: 50,890
Trainable params: 50,890
Non-trainable params: 0
_________________________________________________________________
点击“检查我的进度”以验证是否完成了以下目标: 保存并加载模型
任务 7. 探索回调
在之前训练模型时,您应该已经注意到,随着训练的进行,模型的损失会降低,准确率则会提高。达到所需的训练准确率和损失后,您可能仍需等待一段时间才能完成训练。
您可能会想,“为何不能在模型达到期望的准确率值后就停止训练呢?”
例如,如果 95% 的准确率已足够好,且模型在经过 3 个训练周期后就成功实现这一目标,那为何还要坐等模型完成更多训练周期呢?
答案是:为了进行回调!
回调是一种强大的工具,可用于在训练、评估或推理期间自定义 Keras 模型的行为。您可以定义一个回调,让模型针对训练集达到所需准确率后便立即停止训练。
请尝试运行以下代码,看看如果设置一个在准确率达到 84% 后就停止训练的回调会发生什么情况:
-
打开启动器,选择 Python3 来新建一个 Jupyter 笔记本。
-
将该文件保存为 callback_model.ipynb
。
-
将以下代码粘贴到 callback_model.ipynb
的第一个单元中:
# Import and configure logging
import logging
import google.cloud.logging as cloud_logging
from google.cloud.logging.handlers import CloudLoggingHandler
from google.cloud.logging_v2.handlers import setup_logging
exp_logger = logging.getLogger('expLogger')
exp_logger.setLevel(logging.INFO)
exp_logger.addHandler(CloudLoggingHandler(cloud_logging.Client(), name="callback"))
# Import tensorflow_datasets
import tensorflow_datasets as tfds
# Import numpy
import numpy as np
# Import TensorFlow
import tensorflow as tf
# Define Callback
class myCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
if(logs.get('sparse_categorical_accuracy')>0.84):
exp_logger.info("\nReached 84% accuracy so cancelling training!")
self.model.stop_training = True
callbacks = myCallback()
# Define, load and configure data
(ds_train, ds_test), info = tfds.load('fashion_mnist', split=['train', 'test'], with_info=True, as_supervised=True)
# Define batch size
BATCH_SIZE = 32
# Normalizing and batch processing of data
ds_train = ds_train.map(lambda x, y: (tf.cast(x, tf.float32)/255.0, y)).batch(BATCH_SIZE)
ds_test = ds_test.map(lambda x, y: (tf.cast(x, tf.float32)/255.0, y)).batch(BATCH_SIZE)
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
# Compile data
model.compile(optimizer = tf.keras.optimizers.Adam(),
loss = tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
model.fit(ds_train, epochs=5, callbacks=[callbacks])
-
按 Ctrl + S 或前往文件 > 保存笔记本,以保存所做更改。
-
点击运行按钮或按 Shift + Enter,以运行代码。
请注意,训练在几个周期后便已取消。
点击“检查我的进度”以验证是否完成了以下目标: 探索回调
任务 8. 对模型进行实验
在本部分,您将对神经网络的不同层进行实验。
练习 1
在本练习中,您将探索模型中的各个层。如果改变神经元的数量,会发生什么情况?
-
打开启动器,选择 Python3 来新建一个 Jupyter 笔记本。
-
将该文件保存为 updated_model.ipynb
。
-
将以下代码粘贴到 updated_model.ipynb
的第一个单元中:
# Import and configure logging
import logging
import google.cloud.logging as cloud_logging
from google.cloud.logging.handlers import CloudLoggingHandler
from google.cloud.logging_v2.handlers import setup_logging
up_logger = logging.getLogger('upLogger')
up_logger.setLevel(logging.INFO)
up_logger.addHandler(CloudLoggingHandler(cloud_logging.Client(), name="updated"))
# Import tensorflow_datasets
import tensorflow_datasets as tfds
# Import numpy
import numpy as np
# Import TensorFlow
import tensorflow as tf
# Define, load and configure data
(ds_train, ds_test), info = tfds.load('fashion_mnist', split=['train', 'test'], with_info=True, as_supervised=True)
# Define batch size
BATCH_SIZE = 32
# Normalizing and batch processing of data
ds_train = ds_train.map(lambda x, y: (tf.cast(x, tf.float32)/255.0, y)).batch(BATCH_SIZE)
ds_test = ds_test.map(lambda x, y: (tf.cast(x, tf.float32)/255.0, y)).batch(BATCH_SIZE)
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
# Compile data
model.compile(optimizer = tf.keras.optimizers.Adam(),
loss = tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
model.fit(ds_train, epochs=5)
# Logs model summary
model.summary(print_fn=up_logger.info)
- 对密集层设置不同的值来进行实验。
前往 # Define the model
部分,将神经元数量从 64 个更改为 128 个:
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
-
按 Ctrl + S 或前往文件 > 保存笔记本,以保存所做更改。
-
点击运行按钮或按 Shift + Enter,以运行代码。
对于损失、训练时间等数据,您得到了哪些不同结果?您认为原因是什么?
增加到 128 个神经元后,您需要进行更多计算,而这会减慢训练过程。在本例中,增加神经元产生了积极影响,因为模型准确率得到提高。但并非所有情况下都是“越多越好”。您很快就会经历回报递减规律。
点击“检查我的进度”以验证是否完成了以下目标: 练习 1
练习 2
请考虑一下在网络中额外添加一些层所产生的影响。如果在两个密集层之间额外添加一层,会发生什么情况?
- 在
updated_model.ipynb
的 # Define the model
部分添加一层。
将模型定义替换为以下内容:
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
-
按 Ctrl + S 或前往文件 > 保存笔记本,以保存所做更改。
-
点击运行按钮或按 Shift + Enter,以运行代码。
得到的答案是:没有显著影响,因为这是相对简单的数据。对于更复杂的数据,通常需要添加额外层。
点击“检查我的进度”以验证是否完成了以下目标: 练习 2
练习 3
在训练模型之前,您对像素值进行了归一化,使其保持在 [0, 1]
范围内。如果去除归一化,让这些值处于 [0, 255] 范围内(就像它们最初在数据集中那样),会有什么影响?
- 来试试吧!在
# Define, load and configure data
中,移除同时应用于训练数据集和测试数据集的映射函数。
# Define, load and configure data
(ds_train, ds_test), info = tfds.load('fashion_mnist', split=['train', 'test'], with_info=True, as_supervised=True)
# Define batch size
BATCH_SIZE = 32
# Normalizing and batch processing of data
ds_train = ds_train.batch(BATCH_SIZE)
ds_test = ds_test.batch(BATCH_SIZE)
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
- 在单元末尾添加以下代码,以列显批次 0 中第一个图像的最大值。在未进行归一化的情况下,最大值将在
[0, 255]
范围内。
# Print out max value to see the changes
image_batch, labels_batch = next(iter(ds_train))
t_image_batch, t_labels_batch = next(iter(ds_test))
up_logger.info("training images max " + str(np.max(image_batch[0])))
up_logger.info("test images max " + str(np.max(t_image_batch[0])))
- 最终的
updated_model.ipynb
将如下所示:
# Import and configure logging
import logging
import google.cloud.logging as cloud_logging
from google.cloud.logging.handlers import CloudLoggingHandler
from google.cloud.logging_v2.handlers import setup_logging
up_logger = logging.getLogger('upLogger')
up_logger.setLevel(logging.INFO)
up_logger.addHandler(CloudLoggingHandler(cloud_logging.Client(), name="updated"))
# Import tensorflow_datasets
import tensorflow_datasets as tfds
# Import numpy
import numpy as np
# Import TensorFlow
import tensorflow as tf
# Define, load and configure data
(ds_train, ds_test), info = tfds.load('fashion_mnist', split=['train', 'test'], with_info=True, as_supervised=True)
# Define batch size
BATCH_SIZE = 32
# Normalizing and batch processing of data
ds_train = ds_train.batch(BATCH_SIZE)
ds_test = ds_test.batch(BATCH_SIZE)
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
# Compile data
model.compile(optimizer = tf.keras.optimizers.Adam(),
loss = tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
model.fit(ds_train, epochs=5)
# Logs model summary
model.summary(print_fn=up_logger.info)
# Print out max value to see the changes
image_batch, labels_batch = next(iter(ds_train))
t_image_batch, t_labels_batch = next(iter(ds_test))
up_logger.info("training images max " + str(np.max(image_batch[0])))
up_logger.info("test images max " + str(np.max(t_image_batch[0])))
-
按 Ctrl + S 或前往文件 > 保存笔记本,以保存所做更改。
-
点击运行按钮或按 Shift + Enter,以运行代码。
# Print out max value to see the changes
的预期输出
INFO:upLogger:training images max 255
INFO:upLogger:test images max 255
完成训练周期后,您可以看到未进行归一化时准确率发生的变化。
您认为准确率为何会发生这种变化?
点击此处可查看 Stack Overflow 上的最佳答案。
点击“检查我的进度”以验证是否完成了以下目标: 练习 3
练习 4
如果移除 Flatten()
层会发生什么情况?为什么会这样?
快来试试吧:
- 在
# Define the model
部分移除 tf.keras.layers.Flatten()
:
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
- 保存并运行
updated_model.ipynb
中的该单元。
您会收到有关数据形状的错误。这是正常现象。
虽然该错误的详细信息目前看起来并不明确,但这进一步证实了一个经验法则,即网络中的第一层应与数据的形状保持一致。目前,输入图像的形状为 28x28,但使用包含 28 层、每层 28 个神经元的神经网络是不切实际的。因此,将 28,28 展平为 784x1 会更合理。
您无需自己编写所有代码来处理此问题,只需在开头添加 Flatten()
层即可。稍后,当您将数组加载到模型中以后,系统会自动展平这些数组。
练习 5
请注意最后一层(即输出层)。为什么最后一层有 10 个神经元?如果神经元数量不是 10 个,会发生什么情况?
将神经元数量改为 5 个,然后再训练神经网络,看看会有哪些变化。
- 将
# Define the model
部分替换为以下内容,以撤消您在上一部分所做的更改:
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
- 将最后一层的神经元数量从 10 个改为 5 个:
# Define the model
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation=tf.nn.relu),
tf.keras.layers.Dense(5, activation=tf.nn.softmax)])
- 保存并运行
updated_model.ipynb
中的该单元。
具体变化:一旦发现意外值,就会出现错误。
另一个经验法则是,最后一层的神经元数量应与您要分类的类别数量保持一致。在本例中,类别为数字 0-9,所以共有 10 个类别,因此最后一层应有 10 个神经元。
恭喜!
恭喜!在本实验中,您学习了如何设计、编译、训练和评估 Tensorflow 模型。您还学习了如何保存并加载模型,以及如何通过编写自己的回调,在训练期间自定义模型行为。最后,您完成了一系列练习,以便对神经网络的不同层进行实验。
后续步骤/了解详情
Google Cloud 培训和认证
…可帮助您充分利用 Google Cloud 技术。我们的课程会讲解各项技能与最佳实践,可帮助您迅速上手使用并继续学习更深入的知识。我们提供从基础到高级的全方位培训,并有点播、直播和虚拟三种方式选择,让您可以按照自己的日程安排学习时间。各项认证可以帮助您核实并证明您在 Google Cloud 技术方面的技能与专业知识。
上次更新手册的时间:2024 年 9 月 12 日
上次测试实验的时间:2024 年 9 月 12 日
版权所有 2024 Google LLC 保留所有权利。Google 和 Google 徽标是 Google LLC 的商标。其他所有公司名和产品名可能是其各自相关公司的商标。