如何将现有的keras模型拆分为两个独立的模型?

时间:2018-02-13 21:15:29

标签: python keras

我有一个keras模型(已经过训练),我想分成两部分(一部分计算原始输入的内部表示,另一部分计算预计算内部表示的输出)

获得第一部分很简单(输入到内部表示) 但第二部分是有问题的

我找到了两个相关的答案,但在我的案例中它们是有问题的

这些答案中描述的方法是:

  1. How to split a model into two seperate models?
  2. 在此解决方案中,您重新定义了网络的第二部分 - 这似乎是可行的,但需要大量的代码重复(网络非常复杂)

    1. How do I split an convolutional autoencoder?
    2. 在此解决方案中,模型由两个模型的组合定义 - 这看起来是一个很好的解决方案,但与现有的经过培训的网络无关

3 个答案:

答案 0 :(得分:2)

我找到的最佳解决方案:

  1. 定义“嵌套”模型(子模型的组合) - this答案中的建议

  2. 确保图层名称与旧模型中的图层名称相对应 - 这是重要的部分,因为它使图层映射更简单

  3. 将权重从旧模型复制到新模型 - 如下例所示:

    for sub_model in filter(lambda l: isinstance(l, keras.models.Model), new_model.model.layers):
      for layer in filter(lambda l: l.weights, sub_model.layers):
        layer.set_weights(original_model.model.get_layer(layer.name).get_weights())
    

答案 1 :(得分:1)

这是我的解决方案(仅适用于顺序模型)。我在MobileNet2上使用了它,它对我来说效果很好,只需调用该函数并提供预训练的模型和要分割的索引,它将返回两个分割的模型:

    def split_keras_model(model, index):
      '''
      Input: 
        model: A pre-trained Keras Sequential model
        index: The index of the layer where we want to split the model
      Output:
        model1: From layer 0 to index
        model2: From index+1 layer to the output of the original model 
      The index layer will be the last layer of the model_1 and the same shape of that layer will be the input layer of the model_2
      '''
      # Creating the first part...
      # Get the input layer shape
      layer_input_1 = Input(model.layers[0].input_shape[1:])
      # Initialize the model with the input layer
      x = layer_input_1
      # Foreach layer: connect it to the new model
      for layer in model.layers[1:index]:
            x = layer(x)
      # Create the model instance
      model1 = Model(inputs=layer_input_1, outputs=x)


      # Creating the second part...
      # Get the input shape of desired layer
      input_shape_2 = model.layers[index].get_input_shape_at(0)[1:] 
      print("Input shape of model 2: "+str(input_shape_2))
      # A new input tensor to be able to feed the desired layer
      layer_input_2 = Input(shape=input_shape_2) 

      # Create the new nodes for each layer in the path
      x = layer_input_2
      # Foreach layer connect it to the new model
      for layer in model.layers[index:]:
          x = layer(x)

      # create the model
      model2 = Model(inputs=layer_input_2, outputs=x)

      return (model1, model2)

答案 2 :(得分:0)

您可以使用以下函数来拆分模型

from keras.layers import Input
from keras.models import Model
def get_bottom_top_model(model, layer_name):
    layer = model.get_layer(layer_name)
    bottom_input = Input(model.input_shape[1:])
    bottom_output = bottom_input
    top_input = Input(layer.output_shape[1:])
    top_output = top_input

    bottom = True
    for layer in model.layers:
        if bottom:
            bottom_output = layer(bottom_output)
        else:
            top_output = layer(top_output)
        if layer.name == layer_name:
            bottom = False

    bottom_model = Model(bottom_input, bottom_output)
    top_model = Model(top_input, top_output)

    return bottom_model, top_model
bottom_model, top_model = get_bottom_top_model(model, "dense_1")

Layer_name 只是您要拆分的图层的名称。