【问题标题】:How to change input shape in Sequential model in Keras如何在 Keras 的顺序模型中更改输入形状
【发布时间】:2017-06-30 10:57:55
【问题描述】:

我有一个在 Keras 中构建的顺序模型。 我试图弄清楚如何改变输入的形状。在下面的例子中

model = Sequential()
model.add(Dense(32, input_shape=(500,)))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop',
      loss='categorical_crossentropy',
      metrics=['accuracy'])

假设我想建立一个具有不同输入形状的新模型,概念上应该是这样的:

model1 = model
model1.layers[0] = Dense(32, input_shape=(250,))

有没有办法修改模型输入形状?

【问题讨论】:

    标签: keras keras-layer


    【解决方案1】:

    有些相关,所以希望有人会发现这很有用:如果您有一个现有模型,其中输入是一个类似于 (None, None, None, 3) 的占位符,您可以加载模型,替换第一个具有具体形状输入的层。例如,当您想在 iOS CoreML 中使用模型时,这种转换非常有用(在我的情况下,模型的输入是 MLMultiArray 而不是 CVPixelBuffer,并且模型编译失败)

    from keras.models import load_model
    from keras import backend as K
    from keras.engine import InputLayer
    import coremltools
    
    model = load_model('your_model.h5')
    
    # Create a new input layer to replace the (None,None,None,3) input layer :
    input_layer = InputLayer(input_shape=(272, 480, 3), name="input_1")
    
    # Save and convert :
    model.layers[0] = input_layer
    model.save("reshaped_model.h5")    
    coreml_model = coremltools.converters.keras.convert('reshaped_model.h5')    
    coreml_model.save('MyPredictor.mlmodel')
    

    【讨论】:

      【解决方案2】:

      想想在这种情况下改变输入形状意味着什么。

      你的第一个模型

      model.add(Dense(32, input_shape=(500,)))
      

      有一个真正是 500x32 矩阵的密集层。

      如果您将输入更改为 250 个元素,则图层的矩阵和输入维度会不匹配。

      但是,如果您试图实现的是从前 500 个元素的输入模型中重用最后一层的训练参数,您可以通过 get_weights 获得这些权重。然后你可以重建一个新模型并使用 set_weights 在新模型上设置值。

      model1 = Sequential()
      model1.add(Dense(32, input_shape=(250,)))
      model1.add(Dense(10, activation='softmax'))
      model1.layers[1].set_weights(model1.layers[1].get_weights())
      

      请记住,model1 的第一层(又名 model1.layers[0])仍然是未经训练的

      【讨论】:

      • 有没有办法保留整个模型,只改变输入层?实际上我有一个复杂的模型,我想用完整的输入集和部分输入集来训练它并比较结果。我正在寻找一种方法来修改 modell1 中的输入维度,同时保持模型的其余部分相同(当然除了输入维度和第一层)
      • 我认为不是。正如我所说,尺寸会不匹配。如果您想了解您的模型对部分输入的效果如何,我建议您仅使用您的部分输入训练一个不同的模型。但是,如果您真的想在具有不同大小输入的两种情况下使用相同的模型,您可以做的是使用 RNN 而不是 MLP。
      【解决方案3】:

      这是另一种解决方案,无需从头开始定义模型的每一层。对我来说,关键是使用“_layers”而不是“layers”。后者似乎只返回一个副本。

      import keras
      import numpy as np
      
      def get_model():
          old_input_shape = (20, 20, 3)
          model = keras.models.Sequential()
          model.add(keras.layers.Conv2D(9, (3, 3), padding="same", input_shape=old_input_shape))
          model.add(keras.layers.MaxPooling2D((2, 2)))
          model.add(keras.layers.Flatten())
          model.add(keras.layers.Dense(1, activation="sigmoid"))
          model.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['acc'], )
          model.summary()
          return model
      
      def change_model(model, new_input_shape=(None, 40, 40, 3)):
          # replace input shape of first layer
          model._layers[1].batch_input_shape = new_input_shape
      
          # feel free to modify additional parameters of other layers, for example...
          model._layers[2].pool_size = (8, 8)
          model._layers[2].strides = (8, 8)
      
          # rebuild model architecture by exporting and importing via json
          new_model = keras.models.model_from_json(model.to_json())
          new_model.summary()
      
          # copy weights from old model to new one
          for layer in new_model.layers:
              try:
                  layer.set_weights(model.get_layer(name=layer.name).get_weights())
              except:
                  print("Could not transfer weights for layer {}".format(layer.name))
      
          # test new model on a random input image
          X = np.random.rand(10, 40, 40, 3)
          y_pred = new_model.predict(X)
          print(y_pred)
      
          return new_model
      
      if __name__ == '__main__':
          model = get_model()
          new_model = change_model(model)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-12
        • 1970-01-01
        • 2017-09-30
        • 2017-12-24
        • 2019-01-26
        • 2020-09-26
        • 2020-11-20
        相关资源
        最近更新 更多