TensorFlow Keras 高阶应用
总体介绍
上一讲主要讲解了 TensorFlow 中的一些基本概念与一些低阶 API ,在工业使用时,为了能够快速搭建出模型,人们往往更愿意去选择高阶 API。因此,本次主要讲解 TensorFlow 中常用的高阶 API。
知识点
- TensorFlow
- Keras
简介
TensorFlow 中的高阶 API 主要有 Keras 和 Estimators 这两个模块。由于 Keras 入门简单,功能强大,所以本次主要讲解 Keras。
Keras
Keras 是一个用于构建和训练深度学习模型的高阶 API。它可用于快速设计原型、高级研究和生产,具有以下三个主要优势:
- 方便用户使用:Keras 具有针对常见用例做出优化的简单而一致的界面。它可针对用户错误提供切实可行的清晰反馈。
- 模块化和可组合:将可配置的构造块连接在一起就可以构建 Keras 模型,并且几乎不受限制。
- 易于扩展:可以编写自定义构造块以表达新的研究创意,并且可以创建新层、损失函数并开发先进的模型。
导入 tf.keras
tf.keras
是 TensorFlow 对 Keras API 规范 的实现。这是一个用于构建和训练模型的高阶 API,包含对 TensorFlow 特定功能(例如 Eager Execution、tf.data
管道和 Estimator)的顶级支持。 tf.keras
使 TensorFlow 更易于使用,并且不会牺牲灵活性和性能。
首先,导入 tf.keras
以设置 TensorFlow 程序:
1 | import tensorflow as tf |
tf.keras
可以运行任何与 Keras 兼容的代码,但请注意:
- 最新版 TensorFlow 中的
tf.keras
版本可能与 PyPI 中的最新keras
版本不同。请查看tf.keras.__version__
。 - 保存模型的权重时,
tf.keras
默认采用 检查点格式。请传递save_format='h5'
以使用 HDF5。
构建简单的模型
在 Keras 中,可以通过组合层来构建模型。模型通常是由层构成的图。最常见的模型类型是层的堆叠:tf.keras.Sequential
模型。
现在我们使用 tf.keras.Sequential()
来构建一个简单的全连接网络,代码如下:
1 | model = tf.keras.Sequential() # 定义模型 |
同通过上面仅 4 行代码,我们已经构建出了一个简单的神经网络模型,下面我们可以通过 summary
方法来查看所构建的模型信息。
1 | model.summary() |
配置层
上面主要讲述使用 tf.keras.Sequential()
来构建模型,现在讲解另一种 Keras 常用的构建模型方法: tf.keras.layers
,与 tf.keras.Sequential()
方法差不多,这两者都具有一些相同的构造函数参数:
activation
:设置层的激活函数。此参数由内置函数的名称指定,或指定为可调用对象。默认情况下,系统不会应用任何激活函数。kernel_initializer
和bias_initializer
:创建层权重的初始化方案。此参数是一个名称或可调用对象,默认为"Glorot uniform"
初始化器。kernel_regularizer
和bias_regularizer
:应用层权重的正则化方案,例如 L1 或 L2 正则化。默认情况下,系统不会应用正则化函数。
以下代码使用构造函数参数实例化 tf.keras.layers. Dense
层:
1 | # 创建一个层,输出单元为 64 ,激活函数为 sigmoid 函数 |
训练和评估
上面主要讲述 Keras 两种常用构建神经网络层的方法。两者也可以合起来使用,如下:
1 | model = tf.keras.Sequential([ |
构建好模型后,通过调用 compile
方法配置该模型的学习流程:
1 | model.compile(optimizer=tf.train.AdamOptimizer(0.001), |
tf.keras.Model.compile
主要含有三个重要参数:
optimizer
:此对象会指定训练过程。从tf.train
模块向其传递优化器实例,例如tf.train.AdamOptimizer
、tf.train.RMSPropOptimizer
或tf.train.GradientDescentOptimizer
。loss
:要在优化期间最小化的函数。常见选择包括均方误差 (mse
)、categorical_crossentropy
和binary_crossentropy
。损失函数由名称或通过从tf.keras.losses
模块传递可调用对象来指定。metrics
:用于监控训练。它们是tf.keras.metrics
模块中的字符串名称或可调用对象。
以下代码展示了配置模型以进行训练的几个示例:
1 | model.compile(optimizer=tf.train.AdamOptimizer(0.01), # 使用 Adam 优化算法 |
输入 NumPy 数据
当构建好模型之后,需要对其进行训练,而训练时需要加载数据。对于小型数据集,可以直接使用 NumPy 数组训练和评估模型。使用 fit
方法来训练模型:
1 | import numpy as np |
在训练时输出的日志中,sample - loss: 11.6251 表示损失值,categorical_accuracy: 0.1100 表示正确率,在该例子中,使用的数据集是随机产生的,因此准确率并不高。
tf.keras.Model.fit
采用三个重要参数:
epochs
:以周期为单位进行训练。一个周期是对整个输入数据的一次迭代(以较小的批次完成迭代)。batch_size
:当传递 NumPy 数据时,模型将数据分成较小的批次,并在训练期间迭代这些批次。此整数指定每个批次的大小。请注意,如果样本总数不能被批次大小整除,则最后一个批次可能更小。validation_data
:在对模型进行原型设计时,你需要轻松监控该模型在某些验证数据上达到的效果。传递此参数(输入和标签元组)可以让该模型在每个周期结束时以推理模式显示所传递数据的损失和指标。即我们通常所说的验证集或测试集。
下面是使用 validation_data 的示例:
1 | import numpy as np |
输入 tf.data 数据集
传入数据集还有另一种方法,就是使用 TensorFlow 提供的接口 tf.data
。 其提供的 Datasets API 可扩展为大型数据集或多设备训练。将 tf.data.Dataset
实例传递到 fit
方法:
1 | # 加载数据集 |
在上方代码中,fit 方法使用了 steps_per_epoch 参数表示模型在进入下一个周期之前运行的训练步数。由于 Dataset 会生成批次数据,因此该代码段不需要设置 batch_size。
同样该方法传入的数据集也可用于验证:
1 | dataset = tf.data.Dataset.from_tensor_slices((data, labels)) |
评估和预测
当模型训练完,我们需要对所训练完的模型进行评估时,可以使用 tf.keras.Model.evaluate
和 tf.keras.Model.predict
方法,并且这两种方法同样可以使用 NumPy 数据和 tf.data.Dataset
提供的数据。
要评估所提供数据的推理模式损失和指标,可以运行以下代码:
1 | data = np.random.random((1000, 32)) |
同样的方法,采用 tf.data.Dataset
提供的数据。
1 | model.evaluate(dataset, steps=30) |
要在所提供数据(采用 NumPy 数组形式)的推理中预测最后一层的输出,可以运行以下代码:
1 | result = model.predict(data, batch_size=32) |
构建高级模型
上面所讲述的 tf.keras.Sequential
模型是层的简单堆叠,这种方法构建模型简单,但往往无法构建出复杂模型。在 Keras 中,通常使用 Keras 函数式 API 来构建复杂的模型,例如:
- 多输入模型,
- 多输出模型,
- 具有共享层的模型(同一层被调用多次),
- 具有非序列数据流的模型(例如,剩余连接)。
使用函数式 API 构建的模型具有以下特征:
- 层实例可调用并返回张量。
- 输入张量和输出张量用于定义
tf.keras.Model
实例。 - 此模型的训练方式和
Sequential
模型一样。
以下示例使用函数式 API 构建一个简单的全连接网络:
1 | inputs = tf.keras.Input(shape=(32,)) # 创建一个输入层 |
在给定输入和输出的情况下实例化模型。
1 | # 实例化模型 |
模型子类化
我们也可以通过对 tf.keras.Model
进行子类化并定义前向传播来构建完全可自定义的模型。这种方法需要在 __init__
方法中创建层并将它们设置为类实例的属性。此外,需要在 call
方法中定义前向传播。
在启用 Eager Execution 时,模型子类化特别有用,因为可以命令式地编写前向传播。
虽然模型子类化较为灵活,但代价是复杂性更高且用户出错率更高。如果可能,请首选函数式 API。
以下示例展示了使用自定义前向传播进行子类化的 tf.keras.Model
:
1 | class MyModel(tf.keras.Model): |
实例化新模型类:
1 | model = MyModel(num_classes=10) # 模型实例化 |
自定义层
在我们构建模型时,有时候 Keras 提供的接口并不能满足我们的要求。因此可以通过对 tf.keras.layers.Layer
进行子类化并实现以下方法来创建自定义层:
build
:创建层的权重。使用add_weight
方法添加权重。call
:定义前向传播。compute_output_shape
:指定在给定输入形状的情况下如何计算层的输出形状。- 或者,可以通过实现
get_config
方法和from_config
类方法序列化层。
下面是一个使用核矩阵实现输入 matmul 的自定义层示例:
1 | class MyLayer(layers.Layer): |
使用自定义层创建模型:
1 | model = tf.keras.Sequential([ |
回调
回调是传递给模型的对象,用于在训练期间记录模型日志或防止模型出现意外等。你可以编写自定义回调,也可以使用包含以下方法的内置 tf.keras.callbacks
:
tf.keras.callbacks.ModelCheckpoint
:定期保存模型的检查点。tf.keras.callbacks.LearningRateScheduler
:动态更改学习速率。tf.keras.callbacks.EarlyStopping
:在验证效果不再改进时中断训练。tf.keras.callbacks.TensorBoard
:使用 TensorBoard 监控模型的行为。
要使用 tf.keras.callbacks.Callback
,请将其传递给模型的 fit
方法:
1 | callbacks = [ |
保存和恢复
在 Keras 中,可以使用 tf.keras.Model.save_weights
保存并加载模型的权重:
1 | model = tf.keras.Sequential([ |
默认情况下,会以 TensorFlow 检查点 文件格式保存模型的权重。权重也可以另存为 Keras HDF5 格式(Keras 多后端实现的默认格式):
1 | # S 保存为 HDF5 文件 |
保存配置
可以保存模型的配置,此操作会对模型架构(不含任何权重)进行序列化。即使没有定义原始模型的代码,保存的配置也可以重新创建并初始化相同的模型。Keras 支持 JSON 和 YAML 序列化格式:
1 | # 序列化模型为 json 形式 |
输出为:
1 | '{"class_name": "Sequential", "config": {"name": "sequential_6", "layers": [{"class_name": "Dense", "config": {"name": "dense_24", "trainable": true, "dtype": null, "units": 64, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null, "dtype": "float32"}}, "bias_initializer": {"class_name": "Zeros", "config": {"dtype": "float32"}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_25", "trainable": true, "dtype": null, "units": 10, "activation": "softmax", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null, "dtype": "float32"}}, "bias_initializer": {"class_name": "Zeros", "config": {"dtype": "float32"}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.1.6-tf", "backend": "tensorflow"}' |
1 | import json |
输出为:
1 | {'backend': 'tensorflow', |
从 json 重新创建模型(刚刚初始化)。
1 | # 加载模型 |
将模型序列化为 YAML 格式。
1 | yaml_string = model.to_yaml() |
输出为:
1 | backend: tensorflow |
从 YAML 重新创建模型
1 | fresh_model = tf.keras.models.model_from_yaml(yaml_string) |
整个模型
整个模型可以保存到一个文件中,其中包含权重值、模型配置乃至优化器配置。这样就可以对模型设置检查点并稍后从完全相同的状态继续训练,而无需访问原始代码。
1 | # 创建一个模型 |
总结
本次主要讲解了 TensorFlow 常用的高阶 API,并对其集成的 Keras 进行详细的讲解。相对于低阶 API ,高阶 API 往往会更加简单,因为其只要定义层即可。这也是 TensorFlow 官方极力推荐广大开发者使用高阶 API 的原因。
原文作者: 贺同学
原文链接: http://clarkhedi.github.io/2020/04/09/tensorflow-keras-gao-jie-ying-yong/
版权声明: 转载请注明出处(必须保留原文作者署名原文链接)