Is a Keras base model preprocessing layer used during model prediction? - keras

My concern stems from how I currently have a preprocessing layer required for altering the input to the transfer learning base model, but I want to add several other preprocessing layers for data augmentation.
I want the base model preprocessing layer to apply to test data during predict() calls, but don't want the layers added for data augmentation to do so. According to the Keras documentation, "Data augmentation is inactive at test time so input images will only be augmented during calls to Model.fit (not Model.evaluate or Model.predict).", but is that the same for a base model preprocessing layer too?
Model Construction:
# layer construction
input_layer = layers.Input(shape=(targetWidth, targetHeight, 3))
preprocc_input = applications.inception_v3.preprocess_input
base_model = applications.InceptionV3(
input_shape=(targetWidth, targetHeight, 3),
include_top=False,
)
base_model.trainable = False
global_avg_pool_layer = layers.GlobalAveragePooling2D()
fc_layer = layers.Dense(1024, activation='relu')
#dropout_layer = layers.Dropout(0.2)
output_layer = layers.Dense(
units=1,
activation=keras.activations.sigmoid #'softmax'
)
#layer connecting
x = preprocc_input(input_layer)
x = base_model(x, training=False)
x = global_avg_pool_layer(x)
x = fc_layer(x)
#x = dropout_layer(x)
predictions = output_layer(x)
model = keras.Model(input_layer, predictions)

Related

Problem with using multiple inputs with embedding layers in a Keras Model

I am trying to build a basic NN using Keras using multiple input layers, some of which are connected to Embedding layers. I am using the data for Kaggle's Housing Prices competition.
Here is the structure of the model I am using:
I use a scikit-learn Pipeline to transform the data. For the embedding layers, I transform the data using label encoding. The rest of the code I am using to build the model:
##################### CREATE INPUT AND EMBEDDING LAYERS FOR CATEGORICAL FEATURES #####################
# Input and embedding layer for MSSubClass feature
no_of_unique_categories = X_train['MSSubClass'].nunique() + 1
embedding_size = int(max(min(np.ceil((no_of_unique_categories)/2), 50),2))
input_cat_layer_1 = Input(shape=(1,))
embedding_layer_1 = Embedding(
input_dim=no_of_unique_categories,
output_dim=embedding_size,
input_length=1)(input_cat_layer_1)
flattened_layer_1 = Flatten()(embedding_layer_1)
no_of_unique_categories = X_train['MSZoning'].nunique() + 1
embedding_size = int(max(min(np.ceil((no_of_unique_categories)/2), 50),2))
# Input and embedding layer for MSZoning feature
input_cat_layer_2 = Input(shape=(1,))
embedding_layer_2 = Embedding(
input_dim=no_of_unique_categories,
output_dim=embedding_size,
input_length=1)(input_cat_layer_2)
flattened_layer_2 = Flatten()(embedding_layer_2)
# Input layer for all the numerical features
no_of_numeric_features = len(numeric_columns)
numeric_input = Input(shape=(no_of_numeric_features,))
##################### BUILD THE MODEL #####################
concatenate = Concatenate()([numeric_input, flattened_layer_1, flattened_layer_2])
hidden = Dense(110, activation='relu')(concatenate)
output = Dense(1)(hidden)
model = Model(inputs=[numeric_input, input_cat_layer_1, input_cat_layer_2], outputs=output, name='final_model')
print(model.summary())
plot_model(model, show_shapes=True, show_layer_names=True, to_file='model_structure.png')
optimizer = Adam(learning_rate=0.001)
model.compile(loss='mse', optimizer=optimizer, metrics=['RootMeanSquaredError'])
##################### TRANSFORM DATA TO USE IN MODEL #####################
X_train_transformed = preprocessor.fit_transform(X_train)
X_test_transformed = preprocessor.transform(X_test)
model.fit(X_train_transformed, y_train, epochs=200, validation_data=(X_test_transformed, y_test))
mse_test = model.evaluate(X_test_transformed, y_test)
predictions = model.predict(X_test_transformed)
mse = mean_squared_error(y_test, predictions)
rmse = np.sqrt(mse)
The problem I am running into is when I try and fit the model to the training data, I receive the following error:
ValueError: Layer "final_model" expects 3 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, 37) dtype=float32>]
I cannot figure out why this is happening and what I can do to fix it.

How to reinitialize a layer in Keras but not the weights

I want to copy some layers of a given model in an other new model (with all their attributes like stride, padding etc.). I want to keep the weights and attributes but not the inbound_node/outbound_node property linked to the old model.
I don't think there is any function in Keras to do that but it's very easy with the get_config, get_weights() and set_weights() method of Keras Layers.
new_fresh_layer = layer.__class__(**layer.get_config())
old_layer_weights = layer.get_weights()
x = new_fresh_layer(layer_inputs)
new_fresh_layer.set_weights(old_layer_weights)
if also works when adding layers sequentialy to a model:
model1 = Sequential()
old_layer = Dense(10, input_shape=(10,))
model1.add(old_layer)
model2 = Sequential()
new_layer = old_layer.__class__(**old_layer.get_config())
model2.add(new_layer)
new_layer.set_weights(old_layer.get_weights())
assert (new_layer.get_weights()[0] == old_layer.get_weights()[0]).all()
assert (new_layer.get_weights()[1] == old_layer.get_weights()[1]).all()

How to apply triplet loss function in resnet50 for the purpose of deepranking

I try to create image embeddings for the purpose of deep ranking using a triplet loss function. The idea is that we can take a pretrained CNN (e.g. resnet50 or vgg16), remove the FC layers and add an L2 normalization function to retrieve unit vectors which can then be compared via a distance metric (e.g. cosine similarity). As far as I understand the predicted vectors that come out of a pretrained CNN are not optimal, but are a good start. By adding the triplet loss function we can re-train the network to keep similar pictures 'close' to each other and different pictures 'far' apart in the feature space. Inspired by this notebook , I tried to setup the following code, but I get an error ValueError: The name "conv1_pad" is used 3 times in the model. All layer names should be unique..
# Anchor, Positive and Negative are numpy arrays of size (200, 256, 256, 3), same for the test images
pic_size=256
def shared_dnn(inp):
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(3, pic_size, pic_size),
input_tensor=inp)
x = base_model.output
x = Flatten()(x)
x = Lambda(lambda x: K.l2_normalize(x,axis=1))(x)
for layer in base_model.layers[15:]:
layer.trainable = False
return x
anchor_input = Input((3, pic_size,pic_size ), name='anchor_input')
positive_input = Input((3, pic_size,pic_size ), name='positive_input')
negative_input = Input((3, pic_size,pic_size ), name='negative_input')
encoded_anchor = shared_dnn(anchor_input)
encoded_positive = shared_dnn(positive_input)
encoded_negative = shared_dnn(negative_input)
merged_vector = concatenate([encoded_anchor, encoded_positive, encoded_negative], axis=-1, name='merged_layer')
model = Model(inputs=[anchor_input,positive_input, negative_input], outputs=merged_vector)
#ValueError: The name "conv1_pad" is used 3 times in the model. All layer names should be unique.
model.compile(loss=triplet_loss, optimizer=adam_optim)
model.fit([Anchor,Positive,Negative],
y=Y_dummy,
validation_data=([Anchor_test,Positive_test,Negative_test],Y_dummy2), batch_size=512, epochs=500)
I am new to keras and I am not quite sure how to solve this. The author in the link above creates his own CNN from scratch, but I would like to build it upon resnet (or vgg16). How can I configure ResNet50 to use a triplet loss function (in the link above you find also the source code for the triplet loss function).
In your ResNet50 definition, you've written
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(3, pic_size, pic_size), input_tensor=inp)
Remove the input_tensor argument. Change input_shape=inp.
If you're using TF backend as you mentioned the input should be (256, 256, 3), then your input should be (pic_size, pic_size, 3).
def shared_dnn(inp):
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=inp)
x = base_model.output
x = Flatten()(x)
x = Lambda(lambda x: K.l2_normalize(x,axis=1))(x)
for layer in base_model.layers[15:]:
layer.trainable = False
return x
img_shape=(256, 256, 3)
anchor_input = Input(img_shape, name='anchor_input')
positive_input = Input(img_shape, name='positive_input')
negative_input = Input(img_shape, name='negative_input')
encoded_anchor = shared_dnn(anchor_input)
encoded_positive = shared_dnn(positive_input)
encoded_negative = shared_dnn(negative_input)
merged_vector = concatenate([encoded_anchor, encoded_positive, encoded_negative], axis=-1, name='merged_layer')
model = Model(inputs=[anchor_input,positive_input, negative_input], outputs=merged_vector)
model.compile(loss=triplet_loss, optimizer=adam_optim)
model.fit([Anchor,Positive,Negative],
y=Y_dummy,
validation_data=([Anchor_test,Positive_test,Negative_test],Y_dummy2), batch_size=512, epochs=500)
The model plot is as follows:
model_plot

How can I feed the output from last layer of mobilenet to a Unet model

I am trying to build an image segmentation model with a Keras mobilenet model pre-trained on imagenet dataset. How ever to train the model further, I want to add the U-net layers to the existing model and only train the layers of u-net architecture with mobilenet model helping as a backbone.
Problem: The last layer of mobilenet model is of dimensions (7x7x1024), which is a RelU layer, I wish want to re-shape this to (256x256x3) which can be understood by the U-net input layer.
not the last layer, but creating a unet on mobilenet can be done using the below code:
ALPHA = 1 # Width hyper parameter for MobileNet (0.25, 0.5, 0.75, 1.0). Higher width means more accurate but slower
IMAGE_HEIGHT = 224
IMAGE_WIDTH = 224
HEIGHT_CELLS = 28
WIDTH_CELLS = 28
def create_model(trainable=True):
model = MobileNet(input_shape=(IMAGE_HEIGHT, IMAGE_WIDTH, 3), include_top=False, alpha=ALPHA, weights="imagenet")
block0 = model.get_layer("conv_pw_1_relu").output
block = model.get_layer("conv_pw_1_relu").output
block1 = model.get_layer("conv_pw_3_relu").output
block2 = model.get_layer("conv_pw_5_relu").output
block3 = model.get_layer("conv_pw_11_relu").output
block4 = model.get_layer("conv_pw_13_relu").output
x = Concatenate()([UpSampling2D()(block4), block3])
x = Concatenate()([UpSampling2D()(x), block2])
x = Concatenate()([UpSampling2D()(x), block1])
x = Concatenate()([UpSampling2D()(x), block])
# x = Concatenate()([UpSampling2D()(x), block0])
x = UpSampling2D()(x)
x = Conv2D(1, kernel_size=1, activation="sigmoid")(x)
x = Reshape((IMAGE_HEIGHT, IMAGE_HEIGHT))(x)
return Model(inputs=model.input, outputs=x)

Is it possible to train using same model with two inputs?

Hello I have a some question for keras.
currently i want implement some network
using same cnn model, and use two images as input of cnn model
and use two result of cnn model, provide to Dense model
for example
def cnn_model():
input = Input(shape=(None, None, 3))
x = Conv2D(8, (3, 3), strides=(1, 1))(input)
x = GlobalAvgPool2D()(x)
model = Model(input, x)
return model
def fc_model(cnn1, cnn2):
input_1 = cnn1.output
input_2 = cnn2.output
input = concatenate([input_1, input_2])
x = Dense(1, input_shape=(None, 16))(input)
x = Activation('sigmoid')(x)
model = Model([cnn1.input, cnn2.input], x)
return model
def main():
cnn1 = cnn_model()
cnn2 = cnn_model()
model = fc_model(cnn1, cnn2)
model.compile(optimizer='adam', loss='mean_squared_error')
model.fit(x=[image1, image2], y=[1.0, 1.0], batch_size=1, ecpochs=1)
i want to implement model something like this, and train models
but i got error message like below :
'All layer names should be unique'
Actually i want use only one CNN model as feature extractor and finally use two features to predict one float value as 0.0 ~ 1.0
so whole system -->>
using two images and extract features from same CNN model, and features are provided to Dense model to get one floating value
Please, help me implement this system and how to train..
Thank you
See the section of the Keras documentation on shared layers:
https://keras.io/getting-started/functional-api-guide/
A code snippet from the documentation above demonstrating this:
# This layer can take as input a matrix
# and will return a vector of size 64
shared_lstm = LSTM(64)
# When we reuse the same layer instance
# multiple times, the weights of the layer
# are also being reused
# (it is effectively *the same* layer)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)
# We can then concatenate the two vectors:
merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1)
# And add a logistic regression on top
predictions = Dense(1, activation='sigmoid')(merged_vector)
# We define a trainable model linking the
# tweet inputs to the predictions
model = Model(inputs=[tweet_a, tweet_b], outputs=predictions)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit([data_a, data_b], labels, epochs=10)

Resources