「导语」TensorFlow 2.0 版发布以来,Keras 已经被深度集成于 TensorFlow 框架中,Keras API 也成为了构建深度网络模型的第一选择。使用 Keras 进行模型开发与迭代是每一个数据开发人员都需要掌握的一项基本技能,让我们一起走进 Keras 的世界一探究竟。
Keras 介绍
-
Keras
是一个用Python
编写的高级神经网络API
,它是一个独立的库,能够以TensorFlow
,CNTK
或者Theano
作为后端运行。TensorFlow
从1.0
版本开始尝试与Keras
做集成,到2.0
版发布后更是深度集成了Keras
,并紧密依赖tf.keras
作为其中央高级API
,官方亦高度推荐使用keras API
来完成深度模型的构建。 -
tf.keras
具有三个关键优势:-
对小白用户友好:
Keras
具有简单且一致的接口,并对用户产生的错误有明确可行的建议去修正。TensorFlow 2.0
之前的版本,由于其代码编写复杂,API
接口混乱而且各个版本之间兼容性较差,受到广泛的批评,使用Keras
进行统一化之后,会大大减少开发人员的工作量。 -
模块化且可组合:
Keras
模型通过可构建的模块连接在一起,没有任何限制,模型结构清晰,代码容易阅读。 -
便于扩展:当编写新的自定义模块时,可以非常方便的基于已有的接口进行扩展。
-
-
Keras
使得TensorFlow
更易于使用,而且不用损失其灵活性和性能。
Keras 模型构建
在 TensorFlow 2.x
版本中,可以使用三种方式来构建 Keras
模型,分别是 Sequential
, 函数式 (Functional) API
以及自定义模型 (Subclassed)
。下面就分别介绍下这三种构建方式。
Sequential Model
-
在
Keras
中,通常是将多个层 (layer
) 组装起来形成一个模型 (model
),最常见的一种方式就是层的堆叠,可以使用tf.keras.Sequential
来轻松实现。以上图中所示模型为例,其代码实现如下:import tensorflow as tf from tensorflow.keras import layers model = tf.keras.Sequential() # Adds a densely-connected layer with 64 units to the model: model.add(layers.Dense(64, activation='relu', input_shape=(16,))) # This is identical to the following: # model.add(layers.Dense(64, activation='relu', input_dim=16)) # model.add(layers.Dense(64, activation='relu', batch_input_shape=(None, 16))) # Add another: model.add(layers.Dense(64, activation='relu')) # Add an output layer with 10 output units: model.add(layers.Dense(10)) # model.build((None, 16)) print(model.weights)
-
注意对于
Sequential
添加的第一层,可以包含一个input_shape
或input_dim
或batch_input_shape
参数来指定输入数据的维度,详见注释部分。当指定了input_shape
等参数后,每次add
新的层,模型都在持续不断地创建过程中,也就说此时模型中各层的权重矩阵已经被初始化了,可以通过调用model.weights
来打印模型的权重信息。 -
当然,第一层也可以不包含输入数据的维度信息,称之为延迟创建模式,也就是说此时模型还未真正创建,权重矩阵也不存在。可以通过调用
model.build(batch_input_shape)
方法手动创建模型。如果未手动创建,那么只有当调用fit
或者其他训练和评估方法时,模型才会被创建,权重矩阵才会被初始化,此时模型会根据输入的数据来自动推断其维度信息。 -
input_shape
中没有指定batch
的大小而将其设置为None
,是因为在训练与评估时所采用的batch
大小可能不一致。如果设为定值,在训练或评估时会产生错误,而这样设置后,可以由模型自动推断batch
大小并进行计算,鲁棒性更强。 -
除了这种顺序性的添加 (
add
) 外,还可以通过将layers
以参数的形式传递给Sequential
来构建模型。示例代码如下所示:import tensorflow as tf from tensorflow.keras import layers model = tf.keras.Sequential([ layers.Dense(64, activation='relu', input_shape=(16, )), layers.Dense(64, activation='relu'), layers.Dense(10) ]) # model.build((None, 16)) print(model.weights)
函数式 API
-
Keras
的函数式 API
是比Sequential
更为灵活的创建模型的方式。它可以处理具有非线性拓扑结构的模型、具有共享层 (layers
) 的模型以及多输入输出的模型。深度学习的模型通常是由层 (layers
) 组成的有向无环图,而函数式 API
就是构建这种图的一种有效方式。 -
以
Sequential Model
一节中提到的模型为例,使用函数式 API
实现的方式如下所示:from tensorflow import keras from tensorflow.keras import layers inputs = keras.Input(shape=(16, )) dense = layers.Dense(64, activation='relu') x = dense(inputs) x = layers.Dense(64, activation='relu')(x) outputs = layers.Dense(10)(x) model = keras.Model(inputs=inputs, outputs=outputs, name='model') model.summary()
-
与使用
Sequential
方法构建模型的不同之处在于,函数式 API
通过keras.Input
指定了输入inputs
并通过函数调用
的方式生成了输出outputs
,最后使用keras.Model
方法构建了整个模型。 -
为什么叫
函数式 API
,从代码中可以看到,可以像函数调用一样来使用各种层 (layers
),比如定义好了dense
层,可以直接将inputs
作为dense
的输入而得到一个输出x
,然后又将x
作为下一层的输入,最后的函数返回值就是整个模型的输出。 -
函数式 API
可以将同一个层 (layers
) 作为多个模型的组成部分,示例代码如下所示:from tensorflow import keras from tensorflow.keras import layers encoder_input = keras.Input(shape=(16, ), name='encoder_input') x = layers.Dense(32, activation='relu')(encoder_input) x = layers.Dense(64, activation='relu')(x) encoder_output = layers.Dense(128, activation='relu')(x) encoder = keras.Model(encoder_input, encoder_output, name='encoder') encoder.summary() x = layers.Dense(