Python 深度学习第二版(GPT 重译)(三)(1)

简介: Python 深度学习第二版(GPT 重译)(三)

七、使用 Keras:深入探讨

本章涵盖

  • 使用 Sequential 类、功能 API 和模型子类创建 Keras 模型
  • 使用内置的 Keras 训练和评估循环
  • 使用 Keras 回调函数自定义训练
  • 使用 TensorBoard 监控训练和评估指标
  • 从头开始编写训练和评估循环

您现在对 Keras 有了一些经验——您熟悉 Sequential 模型、Dense 层以及用于训练、评估和推断的内置 API——compile()fit()evaluate()predict()。您甚至在第三章中学习了如何从 Layer 类继承以创建自定义层,以及如何使用 TensorFlow 的 GradientTape 实现逐步训练循环。

在接下来的章节中,我们将深入研究计算机视觉、时间序列预测、自然语言处理和生成式深度学习。这些复杂的应用将需要比 Sequential 架构和默认的 fit() 循环更多的内容。所以让我们首先把你变成一个 Keras 专家!在本章中,您将全面了解如何使用 Keras API:这是您将需要处理下一个遇到的高级深度学习用例的关键方法。

7.1 一系列工作流程

Keras API 的设计遵循“逐步揭示复杂性”的原则:使入门变得容易,同时使处理高复杂性用例成为可能,只需要在每一步进行增量学习。简单用例应该易于接近,任意高级工作流程应该是可能的:无论您想做多么小众和复杂的事情,都应该有一条明确的路径。这条路径建立在您从更简单工作流程中学到的各种东西之上。这意味着您可以从初学者成长为专家,仍然可以以不同的方式使用相同的工具。

因此,并没有一种“真正”的使用 Keras 的方式。相反,Keras 提供了一系列工作流程,从非常简单到非常灵活。有不同的构建 Keras 模型的方式,以及不同的训练方式,满足不同的需求。因为所有这些工作流程都基于共享的 API,如 LayerModel,所以任何工作流程的组件都可以在任何其他工作流程中使用——它们可以相互通信。

7.2 构建 Keras 模型的不同方式

Keras 有三种构建模型的 API(见图 7.1):

  • Sequential 模型,最易接近的 API——基本上就是一个 Python 列表。因此,它仅限于简单的层堆叠。
  • 功能 API 专注于类似图形的模型架构。它在可用性和灵活性之间找到了一个很好的中间点,因此它是最常用的模型构建 API。
  • 模型子类化,一种低级选项,您可以从头开始编写所有内容。如果您想要对每一点都有完全控制,这是理想的选择。但是,您将无法访问许多内置的 Keras 功能,并且更容易出错。

图 7.1 逐步揭示模型构建的复杂性

7.2.1 Sequential 模型

构建 Keras 模型的最简单方法是使用已知的 Sequential 模型。

列表 7.1 Sequential

from tensorflow import keras 
from tensorflow.keras import layers
model = keras.Sequential([
    layers.Dense(64, activation="relu"),
    layers.Dense(10, activation="softmax")
])

请注意,可以通过 add() 方法逐步构建相同的模型,这类似于 Python 列表的 append() 方法。

列表 7.2 逐步构建一个顺序模型

model = keras.Sequential()
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dense(10, activation="softmax"))

在第四章中,您看到层只有在第一次调用它们时才会构建(也就是说,创建它们的权重)。这是因为层的权重形状取决于它们的输入形状:在输入形状未知之前,它们无法被创建。

因此,前面的 Sequential 模型没有任何权重(列表 7.3),直到您实际在一些数据上调用它,或者使用输入形状调用其 build() 方法(列表 7.4)。

列表 7.3 尚未构建的模型没有权重

>>> model.weights           # ❶
ValueError: Weights for model sequential_1 have not yet been created.

❶ 在那时,模型尚未构建。

列表 7.4 第一次调用模型以构建它

>>> model.build(input_shape=(None, 3))       # ❶
>>> model.weights                            # ❷
[<tf.Variable "dense_2/kernel:0" shape=(3, 64) dtype=float32, ... >,
 <tf.Variable "dense_2/bias:0" shape=(64,) dtype=float32, ... >
 <tf.Variable "dense_3/kernel:0" shape=(64, 10) dtype=float32, ... >,
 <tf.Variable "dense_3/bias:0" shape=(10,) dtype=float32, ... >]

❶ 构建模型 - 现在模型将期望形状为(3,)的样本。输入形状中的 None 表示批次大小可以是任意值。

❷ 现在你可以检索模型的权重。

模型构建完成后,你可以通过summary()方法显示其内容,这对调试很有帮助。

列表 7.5 summary()方法

>>> model.summary()
Model: "sequential_1" 
_________________________________________________________________
Layer (type)                 Output Shape              Param # 
=================================================================
dense_2 (Dense)              (None, 64)                256 
_________________________________________________________________
dense_3 (Dense)              (None, 10)                650 
=================================================================
Total params: 906 
Trainable params: 906 
Non-trainable params: 0 
_________________________________________________________________

如你所见,这个模型恰好被命名为“sequential_1”。你可以为 Keras 中的所有内容命名 - 每个模型,每个层。

列表 7.6 使用name参数为模型和层命名

>>> model = keras.Sequential(name="my_example_model")
>>> model.add(layers.Dense(64, activation="relu", name="my_first_layer"))
>>> model.add(layers.Dense(10, activation="softmax", name="my_last_layer"))
>>> model.build((None, 3))
>>> model.summary()
Model: "my_example_model" 
_________________________________________________________________
Layer (type)                 Output Shape              Param # 
=================================================================
my_first_layer (Dense)       (None, 64)                256 
_________________________________________________________________
my_last_layer (Dense)        (None, 10)                650 
=================================================================
Total params: 906 
Trainable params: 906 
Non-trainable params: 0 
_________________________________________________________________

逐步构建 Sequential 模型时,能够在添加每个层后打印当前模型的摘要非常有用。但在构建模型之前无法打印摘要!实际上,有一种方法可以让你的Sequential动态构建:只需提前声明模型输入的形状即可。你可以通过Input类实现这一点。

列表 7.7 预先指定模型的输入形状

model = keras.Sequential()
model.add(keras.Input(shape=(3,)))               # ❶
model.add(layers.Dense(64, activation="relu"))

❶ 使用 Input 声明输入的形状。请注意,shape 参数必须是每个样本的形状,而不是一个批次的形状。

现在你可以使用summary()来跟踪模型输出形状随着添加更多层而变化的情况:

>>> model.summary()
Model: "sequential_2" 
_________________________________________________________________
Layer (type)                 Output Shape              Param # 
=================================================================
dense_4 (Dense)              (None, 64)                256 
=================================================================
Total params: 256 
Trainable params: 256 
Non-trainable params: 0 
_________________________________________________________________
>>> model.add(layers.Dense(10, activation="softmax"))
>>> model.summary()
Model: "sequential_2" 
_________________________________________________________________
Layer (type)                 Output Shape              Param # 
=================================================================
dense_4 (Dense)              (None, 64)                256 
_________________________________________________________________
dense_5 (Dense)              (None, 10)                650 
=================================================================
Total params: 906 
Trainable params: 906 
Non-trainable params: 0 
_________________________________________________________________

处理转换输入的层(如第八章中将学习的卷积层)时,这是一个相当常见的调试工作流程。

7.2.2 功能 API

Sequential 模型易于使用,但其适用性极为有限:它只能表达具有单个输入和单个输出的模型,按顺序一个接一个地应用各个层。实际上,很常见遇到具有多个输入(例如图像及其元数据)、多个输出(关于数据的不同预测)或非线性拓扑的模型。

在这种情况下,你将使用功能 API 构建模型。这是你在实际应用中遇到的大多数 Keras 模型所使用的方法。它既有趣又强大,感觉就像玩乐高积木一样。

一个简单的例子

让我们从一些简单的东西开始:我们在上一节中使用的两个层的堆叠。其功能 API 版本如下列表所示。

列表 7.8 具有两个Dense层的简单功能模型

inputs = keras.Input(shape=(3,), name="my_input")
features = layers.Dense(64, activation="relu")(inputs)
outputs = layers.Dense(10, activation="softmax")(features)
model = keras.Model(inputs=inputs, outputs=outputs)

让我们一步一步地过一遍这个过程。

我们首先声明了一个Input(请注意,你也可以为这些输入对象命名,就像其他所有内容一样):

inputs = keras.Input(shape=(3,), name="my_input")

这个inputs对象保存了关于模型将处理的数据形状和 dtype 的信息:

>>> inputs.shape
(None, 3)          # ❶
>>> inputs.dtype   # ❷
float32

❶ 模型将处理每个样本形状为(3,)的批次。每批次的样本数量是可变的(由 None 批次大小表示)。

❷ 这些批次将具有 dtype float32。

我们称这样的对象为符号张量。它不包含任何实际数据,但它编码了模型在使用时将看到的实际数据张量的规格。它代表未来的数据张量。

接下来,我们创建了一个层并在输入上调用它:

features = layers.Dense(64, activation="relu")(inputs)

所有 Keras 层都可以在实际数据张量和这些符号张量上调用。在后一种情况下,它们将返回一个新的符号张量,带有更新的形状和 dtype 信息:

>>> features.shape
(None, 64)

在获得最终输出后,我们通过在Model构造函数中指定其输入和输出来实例化模型:

outputs = layers.Dense(10, activation="softmax")(features)
model = keras.Model(inputs=inputs, outputs=outputs)

这是我们模型的摘要:

>>> model.summary()
Model: "functional_1" 
_________________________________________________________________
Layer (type)                 Output Shape              Param # 
=================================================================
my_input (InputLayer)        [(None, 3)]               0 
_________________________________________________________________
dense_6 (Dense)              (None, 64)                256 
_________________________________________________________________
dense_7 (Dense)              (None, 10)                650 
=================================================================
Total params: 906 
Trainable params: 906 
Non-trainable params: 0 
_________________________________________________________________

多输入,多输出模型

与这个玩具模型不同,大多数深度学习模型看起来不像列表,而更像图形。例如,它们可能具有多个输入或多个输出。正是对于这种类型的模型,功能 API 真正发挥作用。

假设你正在构建一个系统,根据优先级对客户支持票据进行排名并将其路由到适当的部门。你的模型有三个输入:

  • 票据的标题(文本输入)
  • 票据的文本主体(文本输入)
  • 用户添加的任何标签(假定为独热编码的分类输入)

我们可以将文本输入编码为大小为vocabulary_size的一维数组(有关文本编码技术的详细信息,请参阅第十一章)。

您的模型还有两个输出:

  • 票证的优先级分数,介于 0 和 1 之间的标量(sigmoid 输出)
  • 应处理票证的部门(对部门集合进行 softmax)

您可以使用几行代码使用函数式 API 构建此模型。

列表 7.9 多输入、多输出函数式模型

vocabulary_size = 10000 
num_tags = 100 
num_departments = 4 
title = keras.Input(shape=(vocabulary_size,), name="title")                # ❶
text_body = keras.Input(shape=(vocabulary_size,), name="text_body")        # ❶
tags = keras.Input(shape=(num_tags,), name="tags")                         # ❶
features = layers.Concatenate()([title, text_body, tags])                  # ❷
features = layers.Dense(64, activation="relu")(features)                   # ❸
priority = layers.Dense(1, activation="sigmoid", name="priority")(features)# ❹
department = layers.Dense(
    num_departments, activation="softmax", name="department")(features)    # ❹
model = keras.Model(inputs=[title, text_body, tags],                       # ❺
                    outputs=[priority, department])                        # ❺

❶ 定义模型输入。

❷ 通过将它们连接起来,将输入特征组合成一个张量 features。

❸ 应用中间层以将输入特征重新组合为更丰富的表示。

❹ 定义模型输出。

❺ 通过指定其输入和输出来创建模型。

函数式 API 是一种简单、类似于乐高的、但非常灵活的方式,用于定义这样的层图。

训练多输入、多输出模型

您可以像训练序贯模型一样训练模型,通过使用输入和输出数据的列表调用fit()。这些数据列表应与传递给Model构造函数的输入顺序相同。

列表 7.10 通过提供输入和目标数组列表来训练模型

import numpy as np
num_samples = 1280 
title_data = np.random.randint(0, 2, size=(num_samples, vocabulary_size))     # ❶
text_body_data = np.random.randint(0, 2, size=(num_samples, vocabulary_size)) # ❶
tags_data = np.random.randint(0, 2, size=(num_samples, num_tags))             # ❶
priority_data = np.random.random(size=(num_samples, 1))                       # ❷
department_data = np.random.randint(0, 2, size=(num_samples, num_departments))# ❷
model.compile(optimizer="rmsprop",
              loss=["mean_squared_error", "categorical_crossentropy"],
              metrics=[["mean_absolute_error"], ["accuracy"]])
model.fit([title_data, text_body_data, tags_data],
          [priority_data, department_data],
          epochs=1)
model.evaluate([title_data, text_body_data, tags_data],
               [priority_data, department_data])
priority_preds, department_preds = model.predict(
    [title_data, text_body_data, tags_data])

❶ 虚拟输入数据

❷ 虚拟目标数据

如果您不想依赖输入顺序(例如,因为您有许多输入或输出),您还可以利用给Input对象和输出层命名的名称,并通过字典传递数据。

列表 7.11 通过提供输入和目标数组的字典来训练模型

model.compile(optimizer="rmsprop",
              loss={"priority": "mean_squared_error", "department":
                    "categorical_crossentropy"},
              metrics={"priority": ["mean_absolute_error"], "department":
                       ["accuracy"]})
model.fit({"title": title_data, "text_body": text_body_data,
           "tags": tags_data},
          {"priority": priority_data, "department": department_data},
          epochs=1)
model.evaluate({"title": title_data, "text_body": text_body_data,
                "tags": tags_data},
               {"priority": priority_data, "department": department_data})
priority_preds, department_preds = model.predict(
    {"title": title_data, "text_body": text_body_data, "tags": tags_data})

函数式 API 的强大之处:访问层连接性

函数式模型是一种显式的图数据结构。这使得可以检查层如何连接并重用先前的图节点(即层输出)作为新模型的一部分。它还很好地适应了大多数研究人员在思考深度神经网络时使用的“心智模型”:层的图。这使得两个重要用例成为可能:模型可视化和特征提取。

让我们可视化我们刚刚定义的模型的连接性(模型的拓扑结构)。您可以使用plot_model()实用程序将函数式模型绘制为图形(参见图 7.2)。

keras.utils.plot_model(model, "ticket_classifier.png")

图 7.2 由plot_model()在我们的票证分类器模型上生成的图

您可以在此图中添加模型中每个层的输入和输出形状,这在调试过程中可能会有所帮助(参见图 7.3)。

keras.utils.plot_model(
    model, "ticket_classifier_with_shape_info.png", show_shapes=True)

图 7.3 添加形状信息的模型图

张量形状中的“None”表示批处理大小:此模型允许任意大小的批处理。

访问层连接性还意味着您可以检查和重用图中的单个节点(层调用)。model.layers 模型属性提供组成模型的层列表,对于每个层,您可以查询layer.inputlayer.output

列表 7.12 检索函数式模型中层的输入或输出

>>> model.layers
[<tensorflow.python.keras.engine.input_layer.InputLayer at 0x7fa963f9d358>,
 <tensorflow.python.keras.engine.input_layer.InputLayer at 0x7fa963f9d2e8>,
 <tensorflow.python.keras.engine.input_layer.InputLayer at 0x7fa963f9d470>,
 <tensorflow.python.keras.layers.merge.Concatenate at 0x7fa963f9d860>,
 <tensorflow.python.keras.layers.core.Dense at 0x7fa964074390>,
 <tensorflow.python.keras.layers.core.Dense at 0x7fa963f9d898>,
 <tensorflow.python.keras.layers.core.Dense at 0x7fa963f95470>]
>>> model.layers[3].input
[<tf.Tensor "title:0" shape=(None, 10000) dtype=float32>,
 <tf.Tensor "text_body:0" shape=(None, 10000) dtype=float32>,
 <tf.Tensor "tags:0" shape=(None, 100) dtype=float32>]
>>> model.layers[3].output
<tf.Tensor "concatenate/concat:0" shape=(None, 20100) dtype=float32>

这使您能够进行特征提取,创建重用另一个模型中间特征的模型。

假设您想要向先前的模型添加另一个输出—您想要估计给定问题票证解决所需时间,一种难度评级。您可以通过三个类别的分类层来实现这一点:“快速”、“中等”和“困难”。您无需从头开始重新创建和重新训练模型。您可以从先前模型的中间特征开始,因为您可以访问它们,就像这样。

列表 7.13 通过重用中间层输出创建新模型

features = model.layers[4].output                                            # ❶
difficulty = layers.Dense(3, activation="softmax", name="difficulty")(features)
new_model = keras.Model(
    inputs=[title, text_body, tags],
    outputs=[priority, department, difficulty])

❶ 层[4] 是我们的中间密集层

让我们绘制我们的新模型(参见图 7.4):

keras.utils.plot_model(
    new_model, "updated_ticket_classifier.png", show_shapes=True)

图 7.4 我们新模型的绘图

7.2.3 继承 Model 类

你应该了解的最后一个模型构建模式是最高级的一个:Model子类化。你在第三章学习了如何子类化Layer类来创建自定义层。子类化Model与此类似:

  • __init__()方法中,定义模型将使用的层。
  • call()方法中,定义模型的前向传递,重用先前创建的层。
  • 实例化你的子类,并在数据上调用它以创建其权重。

将我们之前的例子重写为一个子类模型

让我们看一个简单的例子:我们将使用Model子类重新实现客户支持票务管理模型。

图 7.14 一个简单的子类模型

class CustomerTicketModel(keras.Model):
    def __init__(self, num_departments):
        super().__init__()                                           # ❶
        self.concat_layer = layers.Concatenate()                     # ❷
        self.mixing_layer = layers.Dense(64, activation="relu")      # ❷
        self.priority_scorer = layers.Dense(1, activation="sigmoid") # ❷
        self.department_classifier = layers.Dense(                   # ❷
            num_departments, activation="softmax")
    def call(self, inputs):                                          # ❸
        title = inputs["title"]
        text_body = inputs["text_body"]
        tags = inputs["tags"]
        features = self.concat_layer([title, text_body, tags])
        features = self.mixing_layer(features)
        priority = self.priority_scorer(features)
        department = self.department_classifier(features)
        return priority, department

❶ 不要忘记调用 super()构造函数!

❷ 在构造函数中定义子层。

❸ 在 call()方法中定义前向传递。

一旦你定义了模型,你可以实例化它。请注意,它只会在第一次在一些数据上调用它时创建它的权重,就像Layer子类一样:

model = CustomerTicketModel(num_departments=4)
priority, department = model(
    {"title": title_data, "text_body": text_body_data, "tags": tags_data})

到目前为止,一切看起来与Layer子类化非常相似,这是你在第三章遇到的工作流程。那么,Layer子类和Model子类之间的区别是什么呢?很简单:一个“层”是你用来创建模型的构建块,而一个“模型”是你实际上将要训练、导出用于推断等的顶层对象。简而言之,一个Modelfit()evaluate()predict()方法。层没有。除此之外,这两个类几乎是相同的。(另一个区别是你可以保存模型到磁盘上的文件中,我们将在几节中介绍。)

你可以像编译和训练 Sequential 或 Functional 模型一样编译和训练Model子类:

model.compile(optimizer="rmsprop",
              loss=["mean_squared_error", "categorical_crossentropy"],  # ❶
              metrics=[["mean_absolute_error"], ["accuracy"]])          # ❶
model.fit({"title": title_data,                                         # ❷
           "text_body": text_body_data,                                 # ❷
           "tags": tags_data},                                          # ❷
          [priority_data, department_data],                             # ❸
          epochs=1)
model.evaluate({"title": title_data,
                "text_body": text_body_data,
                "tags": tags_data},
               [priority_data, department_data])
priority_preds, department_preds = model.predict({"title": title_data,
                                                  "text_body": text_body_data,
                                                  "tags": tags_data})

❶ 作为损失和指标参数传递的结构必须与 call()返回的完全匹配——这里是两个元素的列表。

❷ 输入数据的结构必须与 call()方法所期望的完全匹配——这里是一个具有标题、正文和标签键的字典。

❸ 目标数据的结构必须与 call()方法返回的完全匹配——这里是两个元素的列表。

Model子类化工作流是构建模型的最灵活方式。它使你能够构建无法表示为层的有向无环图的模型——想象一下,一个模型在call()方法中使用层在一个for循环内,甚至递归调用它们。任何事情都是可能的——你有控制权。

警告:子类模型不支持的内容

这种自由是有代价的:对于子类模型,你需要负责更多的模型逻辑,这意味着你的潜在错误面更大。因此,你将需要更多的调试工作。你正在开发一个新的 Python 对象,而不仅仅是将 LEGO 积木拼在一起。

函数式模型和子类模型在本质上也有很大的不同。函数式模型是一个显式的数据结构——层的图,你可以查看、检查和修改。子类模型是一段字节码——一个带有包含原始代码的call()方法的 Python 类。这是子类化工作流程灵活性的源泉——你可以编写任何你喜欢的功能,但它也引入了新的限制。

例如,因为层之间的连接方式隐藏在call()方法的内部,你无法访问该信息。调用summary()不会显示层连接,并且你无法通过plot_model()绘制模型拓扑。同样,如果你有一个子类模型,你无法访问层图的节点进行特征提取,因为根本没有图。一旦模型被实例化,其前向传递就变成了一个完全的黑匣子。

7.2.4 混合和匹配不同的组件

重要的是,选择这些模式之一——Sequential 模型、Functional API 或 Model 子类化——不会将您排除在其他模式之外。Keras API 中的所有模型都可以平滑地相互操作,无论它们是 Sequential 模型、Functional 模型还是从头开始编写的子类化模型。它们都是同一系列工作流的一部分。

例如,您可以在 Functional 模型中使用子类化层或模型。

列表 7.15 创建包含子类化模型的 Functional 模型

class Classifier(keras.Model):
    def __init__(self, num_classes=2):
        super().__init__()
        if num_classes == 2:
            num_units = 1 
            activation = "sigmoid" 
        else:
            num_units = num_classes
            activation = "softmax" 
        self.dense = layers.Dense(num_units, activation=activation)
    def call(self, inputs):
        return self.dense(inputs)
inputs = keras.Input(shape=(3,))
features = layers.Dense(64, activation="relu")(inputs)
outputs = Classifier(num_classes=10)(features)
model = keras.Model(inputs=inputs, outputs=outputs)

相反地,您可以将 Functional 模型用作子类化层或模型的一部分。

列表 7.16 创建包含 Functional 模型的子类化模型

inputs = keras.Input(shape=(64,))
outputs = layers.Dense(1, activation="sigmoid")(inputs)
binary_classifier = keras.Model(inputs=inputs, outputs=outputs)
class MyModel(keras.Model):
    def __init__(self, num_classes=2):
        super().__init__()
        self.dense = layers.Dense(64, activation="relu")
        self.classifier = binary_classifier
    def call(self, inputs):
        features = self.dense(inputs)
        return self.classifier(features)
model = MyModel()

7.2.5 记住:使用合适的工具来完成工作

您已经了解了构建 Keras 模型的工作流程的范围,从最简单的工作流程 Sequential 模型到最先进的工作流程模型子类化。何时应该使用其中一个而不是另一个?每种方法都有其优缺点——选择最适合手头工作的方法。

一般来说,Functional API 为您提供了易用性和灵活性之间的很好的权衡。它还为您提供了直接访问层连接性的功能,这对于模型绘图或特征提取等用例非常强大。如果您可以使用 Functional API——也就是说,如果您的模型可以表示为层的有向无环图——我建议您使用它而不是模型子类化。

今后,本书中的所有示例都将使用 Functional API,仅因为我们将使用的所有模型都可以表示为层的图。但是,我们将经常使用子类化层。一般来说,使用包含子类化层的 Functional 模型既具有高开发灵活性,又保留了 Functional API 的优势。

7.3 使用内置的训练和评估循环

逐步披露复杂性的原则——从非常简单到任意灵活的工作流程的访问,一步一步——也适用于模型训练。Keras 为您提供了不同的训练模型的工作流程。它们可以简单到在数据上调用 fit(),也可以高级到从头开始编写新的训练算法。

您已经熟悉了 compile()fit()evaluate()predict() 的工作流程。作为提醒,请查看以下列表。

列表 7.17 标准工作流程:compile()fit()evaluate()predict()

from tensorflow.keras.datasets import mnist
def get_mnist_model():                                                # ❶
    inputs = keras.Input(shape=(28 * 28,))
    features = layers.Dense(512, activation="relu")(inputs)
    features = layers.Dropout(0.5)(features)
    outputs = layers.Dense(10, activation="softmax")(features)
    model = keras.Model(inputs, outputs)
    return model
(images, labels), (test_images, test_labels) = mnist.load_data()      # ❷
images = images.reshape((60000, 28 * 28)).astype("float32") / 255 
test_images = test_images.reshape((10000, 28 * 28)).astype("float32") / 255 
train_images, val_images = images[10000:], images[:10000]
train_labels, val_labels = labels[10000:], labels[:10000]
model = get_mnist_model()
model.compile(optimizer="rmsprop",                                    # ❸
              loss="sparse_categorical_crossentropy",                 # ❸
              metrics=["accuracy"])                                   # ❸
model.fit(train_images, train_labels,                                 # ❹
          epochs=3,                                                   # ❹
          validation_data=(val_images, val_labels))                   # ❹
test_metrics = model.evaluate(test_images, test_labels)               # ❺
predictions = model.predict(test_images)                              # ❻

❶ 创建一个模型(我们将其分解为一个单独的函数,以便以后重用)。

❷ 加载数据,保留一些用于验证。

❸ 通过指定其优化器、要最小化的损失函数和要监视的指标来编译模型。

❹ 使用 fit() 训练模型,可选择提供验证数据以监视在未见数据上的性能。

❺ 使用 evaluate() 在新数据上计算损失和指标。

❻ 使用 predict() 在新数据上计算分类概率。

有几种方法可以自定义这个简单的工作流程:

  • 提供您自己的自定义指标。
  • callbacks 传递给 fit() 方法以安排在训练过程中的特定时间点执行的操作。

让我们来看看这些。

Python 深度学习第二版(GPT 重译)(三)(2)https://developer.aliyun.com/article/1485270

相关文章
|
机器学习/深度学习 算法 算法框架/工具
Python 深度学习第二版(GPT 重译)(四)(2)
Python 深度学习第二版(GPT 重译)(四)
27 2
|
机器学习/深度学习 API 算法框架/工具
Python 深度学习第二版(GPT 重译)(三)(3)
Python 深度学习第二版(GPT 重译)(三)
19 2
|
机器学习/深度学习 算法 算法框架/工具
Python 深度学习第二版(GPT 重译)(二)(3)
Python 深度学习第二版(GPT 重译)(二)
40 1
|
机器学习/深度学习 搜索推荐 TensorFlow
Python 深度学习第二版(GPT 重译)(二)(4)
Python 深度学习第二版(GPT 重译)(二)
47 1
Python 深度学习第二版(GPT 重译)(二)(4)
|
机器学习/深度学习 算法 算法框架/工具
Python 深度学习第二版(GPT 重译)(二)(1)
Python 深度学习第二版(GPT 重译)(二)
72 1
|
机器学习/深度学习 数据可视化 定位技术
Python 深度学习第二版(GPT 重译)(四)(4)
Python 深度学习第二版(GPT 重译)(四)
17 3
|
12天前
|
机器学习/深度学习 算法框架/工具 计算机视觉
Python 深度学习第二版(GPT 重译)(三)(4)
Python 深度学习第二版(GPT 重译)(三)
21 5
|
机器学习/深度学习 监控 算法框架/工具
Python 深度学习第二版(GPT 重译)(三)(2)
Python 深度学习第二版(GPT 重译)(三)
35 1
|
机器学习/深度学习 搜索推荐 TensorFlow
Python 深度学习第二版(GPT 重译)(二)(2)
Python 深度学习第二版(GPT 重译)(二)
80 1
|
机器学习/深度学习 数据可视化 测试技术
Python 深度学习第二版(GPT 重译)(四)(3)
Python 深度学习第二版(GPT 重译)(四)
20 1