Keras函数式API

Note

如果模型本身就不是顺序的,那么就不能使用顺序API,可以选择使用函数式API。
本节我们使用加州房价数据集训练一个回归模型来演示keras函数式API的使用。

加州房价数据集

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler


#@save
def load_california_housing():
    """
    载入加州房价数据集
    输入8维,输出为房价
    """
    # 使用sklearn.datasets载入数据
    housing = fetch_california_housing()
    # 分割为训练集、验证集、测试集
    X_train_val, X_test, y_train_val, y_test = train_test_split(housing.data, housing.target)
    X_train, X_val, y_train, y_val = train_test_split(X_train_val, y_train_val)
    # 标准化
    std = StandardScaler()
    # 以训练集为基准进行标准化
    X_train = std.fit_transform(X_train)
    X_val = std.transform(X_val)
    X_test = std.transform(X_test)
    return (X_train, y_train), (X_val, y_val), (X_test, y_test)


(X_train, y_train), (X_val, y_val), (X_test, y_test) = load_california_housing()
# 查看shape
X_train.shape, y_train.shape
((11610, 8), (11610,))

定义模型

from tensorflow import keras


# Input层需指定shape,类似于Flatten层需指定input_shape
input_ = keras.layers.Input(shape=X_train.shape[1:])
# 函数式API: output = layer(input)
hidden1 = keras.layers.Dense(30, activation="relu")(input_)
hidden2 = keras.layers.Dense(30, activation="relu")(hidden1)
# 这里输入不仅有hidden2还有input_,因此不是顺序模型
concat = keras.layers.Concatenate()([input_, hidden2])
output = keras.layers.Dense(1)(concat)
# 最后指定模型的输入和输出即可
model = keras.Model(inputs=[input_], outputs=[output])
model.summary()
Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 8)]          0                                            
__________________________________________________________________________________________________
dense (Dense)                   (None, 30)           270         input_1[0][0]                    
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 30)           930         dense[0][0]                      
__________________________________________________________________________________________________
concatenate (Concatenate)       (None, 38)           0           input_1[0][0]                    
                                                                 dense_1[0][0]                    
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 1)            39          concatenate[0][0]                
==================================================================================================
Total params: 1,239
Trainable params: 1,239
Non-trainable params: 0
__________________________________________________________________________________________________
# 图形化展示模型
# 需安装pydot, graphviz
keras.utils.plot_model(model)
../_images/2.functional_6_0.png

获取模型参数

开一个支线,简单演示一下获取keras模型参数的方法。

# 模型各层
model.layers
[<keras.engine.input_layer.InputLayer at 0x7fe1407fe9a0>,
 <keras.layers.core.Dense at 0x7fe1407fea90>,
 <keras.layers.core.Dense at 0x7fe12889d220>,
 <keras.layers.merge.Concatenate at 0x7fe12889d700>,
 <keras.layers.core.Dense at 0x7fe1289252b0>]
# 获取其中一层
hidden1 = model.layers[1]
# 获取参数
weights, biases = hidden1.get_weights()
weights.shape, biases.shape
((8, 30), (30,))

训练

# 编译
# 因为是回归模型,所以使用均方误差
model.compile(loss="mse",
              # 在优化器中指定学习率
              optimizer=keras.optimizers.Adam(learning_rate=0.001))
# 训练
model.fit(X_train, y_train, 
          epochs=10, 
          validation_data=(X_val, y_val))
Epoch 1/10
363/363 [==============================] - 1s 1ms/step - loss: 1.0701 - val_loss: 0.9041
Epoch 2/10
363/363 [==============================] - 0s 768us/step - loss: 0.4653 - val_loss: 0.6863
Epoch 3/10
363/363 [==============================] - 0s 755us/step - loss: 0.4226 - val_loss: 0.9916
Epoch 4/10
363/363 [==============================] - 0s 782us/step - loss: 0.3989 - val_loss: 0.9223
Epoch 5/10
363/363 [==============================] - 0s 768us/step - loss: 0.3992 - val_loss: 0.6446
Epoch 6/10
363/363 [==============================] - 0s 770us/step - loss: 0.3742 - val_loss: 0.3592
Epoch 7/10
363/363 [==============================] - 0s 777us/step - loss: 0.3546 - val_loss: 0.4163
Epoch 8/10
363/363 [==============================] - 0s 779us/step - loss: 0.3460 - val_loss: 0.3627
Epoch 9/10
363/363 [==============================] - 0s 757us/step - loss: 0.3418 - val_loss: 0.7494
Epoch 10/10
363/363 [==============================] - 0s 764us/step - loss: 0.3547 - val_loss: 0.8993
<keras.callbacks.History at 0x7fe12968aeb0>
# 保存模型
model.save("my_california_housing_model")
INFO:tensorflow:Assets written to: my_california_housing_model/assets