Keras 函数式 API
参考: tensorflow 文档。
深度学习库 Tensorflow 2 里的 Keras 模块提供了函数式风格的 应用程序接口 (API)。这让我们可以用相当不同的风格,构建出同样的神经网络模型。
面向对象 API
Keras 里我们可以用下面的代码创建模型。
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Input(5, ),
tf.keras.layers.Dense(2, activation="relu", name="layer1"),
tf.keras.layers.Dense(3, activation="relu", name="layer2"),
tf.keras.layers.Dense(4, name="layer3"),
])
通过创建 tf.keras.layers 里的对象(Dense),我们得到了不同的三个「层」。之后 Sequential 函数把这些「层」依序连接起来,得到了模型。
函数式 API
Keras 同时也允许我们把 同样的代码 用函数式风格写出:
import tensorflow as tf
inputs = tf.keras.Input(shape=(5,))
x = tf.keras.layers.Dense(2, activation="relu", name="layer1")(inputs)
x = tf.keras.layers.Dense(3, activation="relu", name="layer2")(x)
outputs = tf.keras.layers.Dense(4, activation="relu", name="layer3")(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
这会得到同样的模型。
深入理解
在面向对象 API 里,我们的使用的语法如下
model = tf.keras.Sequential(
[输入, 第一层, 第二层, 第三层,...]
)
其中,我们使用函数得到了不同「层」,我把我得到的东西想象成对象。下面是我们得到「第一层」的语句。
第一层 = tf.keras.layers.Dense(2, activation="relu", name="layer1")
这样的想象是对的,不过 tf.keras.layers 里的函数返回给我们的实际上是,另一个函数。下面的代码解释了这个行为。
import tensorflow as tf
l1 = tf.keras.layers.Dense(2)
l2 = tf.keras.layers.Dense(3)
l3 = tf.keras.layers.Dense(4)
x = tf.ones((1, 5))
y = l3(l2(l1(x))) # shape 1, 4
我们可以用 数学公式 表示最后一行代码
\[\begin{aligned} x_1 &= l_1(x)\\ x_2 &= l_2(x_1)\\ y &= l_3(x_2) \end{aligned}\]没有输入的模型
在我创建模型的时候,我通常会指定输入数据的形状。譬如,下面的代码 将 输入数据 固定为 5 个数字。
tf.keras.layers.Input(5, )
但是,我也可以创造一个没有输入的模型。一个最简单的例子如下,
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Dense(2)
])
此时,我们不能直接使用 model.summary() 来得到模型的描述。因为我们不知道 输入数据的结构,因而无法确定 模型中 参数的数目。同时我会得到这样的错误警告:
ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.
当我“使用”过一次模型之后,模型的输入就会被确定。譬如,下面的代码片段可以顺利执行。
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Dense(2)
])
x = tf.ones((1, 5))
model(x)
model.summary()
我们「不能」将模型套用在「形状不同的输入」上。譬如,下面的代码会产生错误。
import tensorflow as tf
model = tf.keras.Sequential([
tf.keras.layers.Dense(2)
])
x = tf.ones((1, 5))
model(x) # 顺利执行,模型的输入被固定为 5
x = tf.ones((1, 8))
model(x) # 程序报错