I have trained a model using the Functional API and two different kind of pre-trained model: EfficientNet B5 and MobileNet V2. After tranining with the saved model, I'm running an application which uses that model to make some predictions.
I'm fronting a doubt relatated to what is the correct way to pass the images to "model.prediction()" arguments.
Model:
self.feature_extractor1 = EfficientNetB5(#weights='imagenet',
input_shape=self.input_shape,
include_top=False)
self.feature_extractor2 = MobileNetV2(#weights='imagenet',
input_shape=self.input_shape,
include_top=False)
for layer in self.feature_extractor1.layers:
layer.trainable = False
for layer in self.feature_extractor2.layers:
layer.trainable = False
input_ = Input(shape=self.input_shape)
processed_input1 = b5_preprocess_input(input_)
processed_input2 = mbv2_preprocess_input(input_)
x1 = self.feature_extractor1(processed_input1)
x1 = GlobalAveragePooling2D()(x1)
x1 = Dropout(0.2)(x1)
x1 = Flatten()(x1)
x2 = self.feature_extractor2(processed_input2)
x2 = GlobalAveragePooling2D()(x2)
x2 = Dropout(0.2)(x2)
x2 = Flatten()(x2)
x = Concatenate()([x1, x2])
x = Dense(512, activation='relu')(x) #,kernel_initializer=initializer,kernel_regularizer=regularizers.l2(0.001))
x = Dense(1024, activation='relu')(x)
output_shape = Dense(shape_categories, activation='softmax', name='shape')(x)
model = Model(inputs=input_,
outputs=output_shape)
adam_kwargs = {'beta_1': 0.9, 'beta_2': 0.9, 'epsilon': 1e-7}
sgd_kwargs = {'decay': 1e-6, 'momentum': 0.9, 'nesterov': True}
optimizer = self.optimizers(kwargs=adam_kwargs)
model.compile(loss='categorical_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
model.summary()
STEP_SIZE_TRAIN = self.phase_gen[0].n// self.phase_gen[0].batch_size
STEP_SIZE_VALID = self.phase_gen[1].n// self.phase_gen[1].batch_size
if self.phases == 3:
STEP_SIZE_TEST = self.phase_gen[2].n// self.phase_gen[2].batch_size
checkpoint = ModelCheckpoint(self.model_dir,
monitor='val_accuracy',
verbose=1,
save_best_only=True,
mode='max')
tensorboard = TensorBoard(log_dir=self.model_dir + '/logs',
histogram_freq=5,
embeddings_freq=5)
#[EarlyStopping(monitor='val_loss', patience=8)]
callbacks = [checkpoint, tensorboard]
hist = model.fit_generator(generator=self.phase_gen[0],
steps_per_epoch=STEP_SIZE_TRAIN,
validation_data=self.phase_gen[1],
validation_steps=STEP_SIZE_VALID,
epochs=self.epochs,
callbacks=callbacks
)
In another script, I have the prediction method:
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input as mbv2_preprocess_input
from tensorflow.keras.applications.efficientnet import preprocess_input as b5_preprocess_input
def preprocess_image(img):
img = Image.open(io.BytesIO(img))
img = img.resize((224, 224), Image.ANTIALIAS)
img = image.img_to_array(img)
img = np.expand_dims(img, axis=0)
#return [b5_preprocess_input(img), mbv2_preprocess_input(img)]
return [img, img]
modelSHP = get_modelSHP()
@app.route('/part_numbers', methods=['POST'])
def part_number():
img = request.files.get('image').read()
processed_image = preprocess_image(img)
predict_shape = modelSHP.predict(processed_image)
My first thought was that I would need to pass the input (image) pre processed by the correct function and in the same order I have used it during the model training. But when I have done it, my prediction accuracy stays around zero. Passing just the image, withouth any preprocessing, the results got better.
The way which I'm passing the image input to model.prediction is right (without preprocessing)? I was wondering if using the Functional API and in the way I built the model, the pre processing became such as a layer into each branch model.