首页 > 解决方案 > 如何在 Keras 的模型中“展平”模型

问题描述

所以假设我有一些我喜欢的 Keras 模型:

from keras.layers import Input, Dense, BatchNormalization, Subtract
from keras.models import Model

input_layer = Input((10, ))
x = Dense(5)(input_layer)
output_layer = Dense(10)(x)

model = Model(input_layer, output_layer)

我可以通过该功能了解我的模型,summary()并得到:

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 10)                0
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 55
_________________________________________________________________
dense_2 (Dense)              (None, 10)                60
=================================================================
Total params: 115
Trainable params: 115
Non-trainable params: 0
_________________________________________________________________

现在我想尝试向模型添加一些预处理和后处理步骤,例如我可以执行以下操作:

# Add preprocessing layers
new_input = Input((10,))
x = BatchNormalization()(new_input)
model.layers.pop(0) # remove original input
x = model(x)
# Change the model to residual modeling with a subtract layer
new_output = Subtract()([new_input, x])
new_model = Model(new_input, new_output)

但是现在当我打电话时,summary()我只了解前处理层和后处理层,而不是我的原始模型:

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to
==================================================================================================
input_2 (InputLayer)            (None, 10)           0
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 10)           40          input_2[0][0]
__________________________________________________________________________________________________
model_1 (Model)                 (None, 10)           115         batch_normalization_1[0][0]
__________________________________________________________________________________________________
subtract_1 (Subtract)           (None, 10)           0           input_2[0][0]
                                                                 model_1[1][0]
==================================================================================================
Total params: 155
Trainable params: 135
Non-trainable params: 20
__________________________________________________________________________________________________

这意味着在内部,不是将第一个模型中的每一层都添加到new_model.layers新模型中,而是将整个模型作为单个元素添加到new_model.layers列表中。我希望它实际上使单个元素变平,因此摘要看起来更像这样:


Layer (type)                    Output Shape         Param #     Connected to
==================================================================================================
input_2 (InputLayer)            (None, 10)           0
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 10)           40          input_2[0][0]
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 5)            55          batch_normalization_1[0][0]
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 10)           60          dense_1[0]
__________________________________________________________________________________________________
subtract_1 (Subtract)           (None, 10)           0           input_2[0][0]
                                                                 dense_2[1][0]
==================================================================================================
Total params: 155
Trainable params: 135
Non-trainable params: 20
__________________________________________________________________________________________________

我为什么在乎?基本上,我正在尝试一些不同的建模方法,我可以尝试不同的预处理和后处理组合以及不同的基础模型,看看它如何影响我的结果。然而,当关于基本模型及其参数的信息都包裹在包装模型的单个“模型”层中,该层只包含有关预处理和后处理的信息时,很难进行比较分析。

标签: pythonpython-3.xkeraskeras-layer

解决方案


这是 Keras 的正确行为,因为它Model实际上继承自Layer. 您可以将基本模型包装成一个函数,以阻止它包装成一个Model

def base_model(input=None):
  input_layer = input or Input((10, ))
  x = Dense(5)(input_layer)
  output_layer = Dense(10)(x)
  if input is None:
    return Model(input_layer, output_layer)
  return output_layer
# Then use it
# Add preprocessing layers
new_input = Input((10,))
x = BatchNormalization()(new_input)
x = base_model(x)
# Change the model to residual modeling with a subtract layer
new_output = Subtract()([new_input, x])
new_model = Model(new_input, new_output)

如果您传递一个现有层,它将不会包裹,如果您不传递,它将返回一个Model实例。


推荐阅读