У меня есть модель Keras, которую я определил во время обучения как:
img = keras.Input(shape=[65, 65, 2])
bnorm = keras.layers.BatchNormalization()(img)
...
model = keras.Model(img, outputprob)
Во время подачи, мои входные данные поступают по-другому.Поэтому я определил входной слой (проверив, что форма to_img
также выглядит как (65, 65, 2)
) и попытался выполнить компоновку модели, используя:
to_img = keras.layers.Lambda(...)(json_input)
model_output = model(to_img)
serving_model = keras.Model(json_input, model_output)
Однако я получаю эту ошибку:
tensorflow.python.framework.errors_impl.InvalidArgumentError:
Shape must be rank 4 but is rank 3 for
'model/batch_normalization/cond/FusedBatchNorm' (op:
'FusedBatchNorm') with input shapes: [65,65,2],
[2], [2], [0], [0].
Кажется, это указывает на то, что пакетное измерение не прошло.Почему?
РЕДАКТИРОВАТЬ: То, что я пробовал:
(1) Явно установить trainable=False
во всех слоях, но это, похоже, не имеет никакого значения:
model_core = model
for layer in model_core.layers:
layer.trainable = False
model_output = model_core(to_img)
(2) Попытка расширения результата предварительной обработки:
to_img = keras.layers.Lambda(
lambda x : preproc(x))(json_input)
to_img = keras.layers.Lambda(
lambda x : tf.expand_dims(x, axis=0) )(to_img)
Это приводит к ошибке: AttributeError: 'Model' object has no attribute '_name'
в строке serving_model = keras.Model(json_input, model_output)
(3) Изменен лямбда-слой для отображения map_fn для индивидуальной обработки данных:
to_img = keras.layers.Lambda(
lambda items: K.map_fn(lambda x: preproc, items))(json_input)
Это вызвало ошибку формы, которая указывает на то, что функция preproc получает [65,2] элементов вместо [65,65,2].Это говорит о том, что лямбда-слой применяет функцию к примерам по одному.
(4) Вот полный код модели:
img = keras.Input(shape=[height, width, 2])
# convolutional part of model
cnn = keras.layers.BatchNormalization()(img)
for layer in range(nlayers):
nfilters = nfil * (layer + 1)
cnn = keras.layers.Conv2D(nfilters, (ksize, ksize), padding='same')(cnn)
cnn = keras.layers.Activation('elu')(cnn)
cnn = keras.layers.BatchNormalization()(cnn)
cnn = keras.layers.MaxPooling2D(pool_size=(2, 2))(cnn)
cnn = keras.layers.Flatten()(cnn)
cnn = keras.layers.Dropout(dprob)(cnn)
cnn = keras.layers.Dense(10, activation='relu')(cnn)
# feature engineering part of model
engfeat = keras.layers.Lambda(
lambda x: engineered_features(x, height//2))(img)
# concatenate the two parts
both = keras.layers.concatenate([cnn, engfeat])
ltgprob = keras.layers.Dense(1, activation='sigmoid')(both)
# create a model
model = keras.Model(img, ltgprob)
def rmse(y_true, y_pred):
import tensorflow.keras.backend as K
return K.sqrt(K.mean(K.square(y_pred - y_true), axis=-1))
optimizer = tf.keras.optimizers.Adam(lr=params['learning_rate'],
clipnorm=1.)
model.compile(optimizer=optimizer,
loss='binary_crossentropy',
metrics=['accuracy', 'mse', rmse])
и код функции предварительной обработки:
def reshape_into_image(features, params):
# stack the inputs to form a 2-channel input
# features['ref'] is [-1, height*width]
# stacked image is [-1, height*width, n_channels]
n_channels = 2
stacked = tf.concat([features['ref'], features['ltg']], axis=1)
height = width = PATCH_SIZE(params)
return tf.reshape(stacked, [height, width, n_channels])
и обслуживающий слой:
# 1. layer that extracts multiple inputs from JSON
height = width = PATCH_SIZE(hparams)
json_input = keras.layers.concatenate([
keras.layers.Input(name='ref', dtype=tf.float32, shape=(height * width,)),
keras.layers.Input(name='ltg', dtype=tf.float32, shape=(height * width,)),
], axis=0)
# 2. convert json_input to image (what model wants)
to_img = keras.layers.Lambda(
lambda x: reshape_into_image(features={
'ref': tf.reshape(x[0], [height * width, 1]),
'ltg': tf.reshape(x[1], [height * width, 1])
}, params=hparams),
name='serving_reshape')(json_input)
# 3. now, use trained model to predict
model_output = model(to_img)
# 4. create serving model
serving_model = keras.Model(json_input, model_output)