- 1. 顺序模型(也可看做是函数式模型的一种特殊情况)
- 2. 函数式模型
[tr]两种方式优点缺点[/tr]
顺序模型 | 单输入单输出,搭建比较简单,是多个网络层的线性堆叠,不发生分叉,编译速度快 | 不能定义复杂模型 |
函数式模型 | 灵活,层与层之间可以任意连接可以定义复杂模型(如多输出模型、有向无环图,或具有共享层的模型) | 搭建复杂,编译速度慢 |
顺序模型也可看做是函数式模型的一种特殊情况。
以下以mnist为例分别进行说明:
1 顺序模型Sequential
顺序模型也即一层叠一层,所以模型不发生分叉,单输入单输出,这意味着顺序模型不支持共享图层或多输入多输出模型。
第0讲顺序模型搭建mnist的代码如下:
方式1:采用model.add 一层层添加
import tensorflow as tf
import tensorflow.
keras as keras
print(
keras.
__version__)
(
x_train,
y_train), (
x_valid,
y_valid) =
keras.
datasets.
mnist.
load_data()
assert x_train.
shape == (
60000,
28,
28)
assert x_valid.
shape == (
10000,
28,
28)
assert y_train.
shape == (
60000,)
assert y_valid.
shape == (
10000,)
# step1: use sequential
model =
keras.
models.
Sequential()
# step2: add layer
model.
add(
keras.
layers.
Flatten(
input_shape=(
x_train.
shape[
1],
x_train.
shape[
2])))
model.
add(
keras.
layers.
Dense(
units=
784,
activation=
"relu",
input_dim=
784))
model.
add(
keras.
layers.
Dense(
units=
10,
activation=
"softmax"))
# step3: compile model
model.
compile(
optimizer=
"Adam",
loss=
'sparse_categorical_crossentropy',
metrics=[
'accuracy'])
print(
"model:")
model.
summary()
# step4: train
model.
fit(
x_train,
y_train,
batch_size=
64,
epochs=
5)
# step5: evaluate model
model.
Evaluate (x_valid,
y_valid)
# save model
model.
save(
'keras_mnist.h5')
方式2:初始化Sequential时同时定义层
import tensorflow as tf
import tensorflow.
keras as keras
print(
keras.
__version__)
(
x_train,
y_train), (
x_valid,
y_valid) =
keras.
datasets.
mnist.
load_data()
assert x_train.
shape == (
60000,
28,
28)
assert x_valid.
shape == (
10000,
28,
28)
assert y_train.
shape == (
60000,)
assert y_valid.
shape == (
10000,)
# step1, step2: Init sequential
model =
keras.
models.
Sequential([
keras.
layers.
Flatten(
input_shape=(
x_train.
shape[
1],
x_train.
shape[
2])),
keras.
layers.
Dense(
units=
784,
activation=
"relu",
input_dim=
784),
keras.
layers.
Dense(
units=
10,
activation=
"softmax")
])
# step3: compile model
model.
compile(
optimizer=
"Adam",
loss=
'sparse_categorical_crossentropy',
metrics=[
'accuracy'])
print(
"model:")
model.
summary()
# step4: train
model.
fit(
x_train,
y_train,
batch_size=
64,
epochs=
5)
# step5: evaluate model
model.
evaluate(
x_valid,
y_valid)
# save model
model.
save(
'keras_mnist.h5')
2 函数式API模型
顺序模型允许逐层创建模型以解决许多问题,但是有时我们需要创建更加复杂的模型,比如具有共享图层或多输入多输出的模型,这时我们可以使用keras提供的函数式API模型,它定义了每一层的输入输出,像函数调用一样,用上一层的输出作为这一层的入参,这一层的输出作为函数返回值,这就是函数式API的由来,(这一点不同与顺序模型,顺序模型每层的输入输出是一定的,不需要专门指定)。
同样的,利用函数式API模型搭建与之前等价的mnist模型,代码如下:
import tensorflow as tf
import tensorflow.
keras as keras
print(
keras.
__version__)
(
x_train,
y_train), (
x_valid,
y_valid) =
keras.
datasets.
mnist.
load_data()
assert x_train.
shape == (
60000,
28,
28)
assert x_valid.
shape == (
10000,
28,
28)
assert y_train.
shape == (
60000,)
assert y_valid.
shape == (
10000,)
# step1: Model structure
# 层的实例是可调用的,它以张量为参数,并且返回一个张量
input =
keras.
Input(
shape=(
x_train.
shape[
1],
x_train.
shape[
2]))
x =
keras.
layers.
Flatten()(
input)
x =
keras.
layers.
Dense(
units=
784,
activation=
"relu",
input_dim=
784)(
x)
output =
keras.
layers.
Dense(
units=
10,
activation=
"softmax")(
x)
# step2: define Model
model =
keras.
Model(
inputs=
input,
outputs=
output)
# step3: compile model
model.
compile(
optimizer=
"Adam",
loss=
'sparse_categorical_crossentropy',
metrics=[
'accuracy'])
print(
"model:")
model.
summary()
# step4: train
model.
fit(
x_train,
y_train,
batch_size=
64,
epochs=
5)
# step5: evaluate model
model.
evaluate(
x_valid,
y_valid)
# save model
model.
save(
'keras_mnist.h5')
由这个例子可见:函数式API可以搭建顺序模型Sequential,所以顺序模型也可看做是函数式模型的一种特殊情况。
还有另外一种Model子类的搭建方法,这是利用python call方法的一种写法,我觉得只是写法上的区别,本质也是函数式API,代码如下:
import tensorflow as tf
import tensorflow.
keras as keras
print(
keras.
__version__)
(
x_train,
y_train), (
x_valid,
y_valid) =
keras.
datasets.
mnist.
load_data()
assert x_train.
shape == (
60000,
28,
28)
assert x_valid.
shape == (
10000,
28,
28)
assert y_train.
shape == (
60000,)
assert y_valid.
shape == (
10000,)
# step1: Model structure
class MnistModel(
tf.
keras.
Model):
def __init__(
self):
super(
MnistModel,
self).
__init__()
self.
x0 =
keras.
layers.
Flatten()
self.
x1 =
keras.
layers.
Dense(
units=
784,
activation=
"relu",
input_dim=
784)
self.
x2 =
keras.
layers.
Dense(
units=
10,
activation=
"softmax")
def call(
self,
input):
x =
self.
x0(
input)
x =
self.
x1(
x)
x =
self.
x2(
x)
return x
# step2: define Model
model =
MnistModel()
# step3: compile model
model.
compile(
optimizer=
"Adam",
loss=
'sparse_categorical_crossentropy',
metrics=[
'accuracy'])
# step4: train
model.
fit(
x_train,
y_train,
batch_size=
64,
epochs=
5)
# 要放到model.fit之后
print(
"model:")
model.
summary()
# step5: evaluate model
model.
evaluate(
x_valid,
y_valid)
# save model (不能使用)
# model.save('keras_mnist.h5')采用model子类方法有几个问题需要注意:1. 采用model子类方法时,model.summary方法需要放到model.fit之后才能调用,否则报如下错误:
ValueError: This model has not yet been built. Build the model first by calling `build()` or by calling the model on a batch of data.2. 采用model子类方法时,调用model.save会失败:
NotImplementedError: Saving the model to HDF5 format requires the model to be a Functional model or a Sequential model. It does not work for subclassed models, because such models are defined via the body of a Python method, which isn't safely serializable. Consider saving to the Tensorflow SavedModel format (by setting save_format="tf") or using `save_weights`.