如何在 Keras 的顺序模型中更改输入形状
How to change input shape in Sequential model in Keras
我有一个在 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,))
有没有办法修改模型输入形状?
想想在那种情况下改变输入形状意味着什么。
你的第一个模特
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())
请记住,模型 1 第一层(又名 model1.layers[0])仍未经过训练
有点相关,所以希望有人会发现这很有用:如果您有一个现有模型,其中输入是一个占位符,看起来像 (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')
这是另一种解决方案,无需从头开始定义模型的每一层。对我来说关键是使用“_layers”而不是 "layers"。后者好像只return一份。
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)
我有一个在 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,))
有没有办法修改模型输入形状?
想想在那种情况下改变输入形状意味着什么。
你的第一个模特
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())
请记住,模型 1 第一层(又名 model1.layers[0])仍未经过训练
有点相关,所以希望有人会发现这很有用:如果您有一个现有模型,其中输入是一个占位符,看起来像 (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')
这是另一种解决方案,无需从头开始定义模型的每一层。对我来说关键是使用“_layers”而不是 "layers"。后者好像只return一份。
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)