How to combine two keras models (one frozen), using functional API - tensorflow

How to combine two Keras models using functional API. I mean, I have two models (a, which is pretrained with freezer weights, and b). I want to create a c model by adding the b model to the bottom of the frozen model.
In detail, I have the following two models:
def define_neural_network_model_1st(input_shape, initializer, outputs = 1):
........
return model
def define_neural_network_model_2st(input_shape, initializer, outputs = 1):
........
return model
Since the first one is trained I am loading the weights and freezing the model.
neural_network_model_1st.load_weights('./../some_path.hdf5')
neural_network_model_1st.trainable = False
When I am trying to merge both blocks in the following way
merge_interpretation = Model(inputs=[neural_network_model_1st.inputs], outputs=neural_network_model_2st(neural_network_model_1st.inputs))
I am receiving:
What I am doing wrong? I am waiting to have 1 layer from the frozen model plus all layers in the second one.

Let suppose I have two models,
resnet_50 = tf.keras.applications.ResNet50(weights=None,
input_shape=(224 , 224 , 3),
classes = 2)
vgg_16 = tf.keras.applications.VGG16(
weights=None,
input_shape=(224,224,3),
classes=2,
include_top=False)
Now I want to merge these two models, first of all, I will make sure the output of the first model should be the same shape as the input of the second model, so for that first I have to do some pre-processing.
model = tf.keras.Model(vgg_16.inputs , vgg_16.layers[-2].output)
model2 = tf.keras.Model(resnet_50.get_layer('conv4_block6_out').input , resnet_50.output)
input = tf.keras.layers.Input(shape=(224 , 224 , 3))
out1 = model(input)
intermediate_layer = tf.keras.layers.Conv2D(model2.inputs[0][0].shape[2] , 1 , 1 , padding='same')(out1)
out2 = model2(intermediate_layer)
f_model = tf.keras.Model(input , out2)
tf.keras.utils.plot_model(
f_model,
show_shapes=True)
Now this is the output shape of the two models
[The Architecture of the combined two models][1]
[1]: https://i.stack.imgur.com/F7H8d.png
You can see the individual summary of the models by doing this
f_model.layers[1].summary() #This will show the summary of the first model VGG16
f_model.layers[3].summary() #This will show the summary of the second model Resnet18
But if you run the f_model.summary() this will not show the summary of the combined two models as one, because in the backend Keras take model one as a functional graph Node so it acts as a Node of the graph.

Related

concatenate models with weighting or leave seperate for manual weighting?

I have 2 models I am training, one for each column of data in my dataset.
It seems 1 model is fairly accurate in its results so I want to give it a better weight in determining the actual outputs.
I do not know if I should be trying to concatenate these to models and somehow provide the weights using something like a Rescaling layer in keras OR if I should leave them separate then just do my own processing after?
What are the pro's and con's of each?
def get_model(n_inputs_1, n_inputs_2, n_outputs):
DENSE_LAYER_SIZE = 20
inp1 = keras.layers.Input(shape=(n_inputs_1,))
de1 = keras.layers.Dense(DENSE_LAYER_SIZE, activation='relu')(inp1) #
dr1 = keras.layers.Dropout(.2)(de1)
inp2 = keras.layers.Input(shape=(n_inputs_2,))
de2 = keras.layers.Dense(DENSE_LAYER_SIZE, activation='relu')(inp2) #
dr2 = keras.layers.Dropout(.2)(de2)
rs2 = keras.layers.Rescaling(0.01)(dr2) # reduce impact of input 2 - is this ok?
conc = keras.layers.Concatenate()([dr1, rs2])
out = keras.layers.Dense(n_outputs, activation='sigmoid')(conc)
model = keras.models.Model([inp1, inp2], out)
opt = keras.optimizers.Adam(learning_rate=0.01)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['categorical_accuracy'])
return model
Full code here

How to specify input layer with Keras

I came across this code for tuning the topology of the neural network. However I am unsure of how I can instantiate the first layer without flatening the input.
My input is like this:
With M features (the rows) and N samples (the columns).
How can I create the first (input) layer?
# Initialize sequential API and start building model.
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28,28)))
# Tune the number of hidden layers and units in each.
# Number of hidden layers: 1 - 5
# Number of Units: 32 - 512 with stepsize of 32
for i in range(1, hp.Int("num_layers", 2, 6)):
model.add(
keras.layers.Dense(
units=hp.Int("units_" + str(i), min_value=32, max_value=512, step=32),
activation="relu")
)
# Tune dropout layer with values from 0 - 0.3 with stepsize of 0.1.
model.add(keras.layers.Dropout(hp.Float("dropout_" + str(i), 0, 0.3, step=0.1)))
# Add output layer.
model.add(keras.layers.Dense(units=10, activation="softmax"))
I know that Keras usually instantiates the first hidden layer along with the input layer, but I don't see how I can do it in this framework. Below is the code for instantiating input + first hidden layer at once.
model.add(Dense(100, input_shape=(CpG_num,), kernel_initializer='normal', activation='relu')
If you have multiple inputs and want to set your input shape, let's suppose you have a dataframe with m-> rows, n-> columns... then simply do this...
m = no_of_rows #1000
n = no_of_columns #10
no_of_layers = 64
#we will not write m because m will be taken as a batch here.
_input = tf.keras.layers.Input(shape=(n))
dense = tf.keras.layers.Dense(no_of_layers)(_input)
output = tf.keras.backend.function(_input , dense)
#Now, I can see that it is working or not...!
x = np.random.randn(1000 , 10)
print(output(x).shape)

tensorflow keras model for solving simple equation

I'm trying to understand how to create a simple tensorflow 2.2 keras model that can predict a simple function value:
f(a, b, c, d) = a < b : max(a/2, c/3) : max (b/2, d/3)
I know this exact question can be reduced to a categorical classification but my intention is to find a good way to build a model that can estimate the value and build more and more functions based on that with a more and more complex conditions later on.
For start I am stumbled upon understanding why a simple function works that hard.
For using with tensorflow on a created model I have:
def generate_input(multiplier):
return np.random.rand(1024 * multiplier, 4) * 1000
def generate_output(input):
def compute_func(row):
return max(row[0]/2, row[2]/3) if row[0] < row[1] else max(row[1]/2, row[3]/3)
return np.apply_along_axis(compute_func, 1, input)
for epochs in range(0, 512):
# print('Generating data...')
train_input = generate_input(1000)
train_output = generate_output(train_input)
# print('Training...')
fit_history = model.fit(
train_input, train_output,
epochs=1,
batch_size=1024
)
I have tried with different models that are less or more complex but I still didn't got a good conversion.
For example a simple liniar one:
input = Input(shape=(4,))
layer = Dense(8, activation=tanh)(input)
layer = Dense(16, activation=tanh)(layer)
layer = Dense(32, activation=tanh)(layer)
layer = Dense(64, activation=tanh)(layer)
layer = Dense(128, activation=tanh)(layer)
layer = Dense(32, activation=tanh)(layer)
layer = Dense(8, activation=tanh)(layer)
output = Dense(1)(layer)
model = Model(inputs=input, outputs=output)
model.compile(optimizer=Adam(), loss=mean_squared_error)
Can you give point to the direction one should follow in order to solve this type of conditional functions?
Or do I miss some pre-processing?
In my honest opinion, you have a pretty deep model, and therefore, you do not have enough data to train. I do not think you will need that much deep architecture.
Your problem definition is not what I would have done. You actually do not desire to generate the max value at the output, but you want the max value to get selected, right? If it is the case, I would go with a multiclass classification instead of a regression problem in my design. That's saying, I would go with an output = Dense(4)(layer,activation=softmax) as the last layer and in my optimizer, I would use a categorical cross-entropy. Of course, in the output generation, you need to manage to return an array of 3 zeros and one 1, something like this:
def compute_func(row):
ret_value=[0,0,0,0]
if row[0] < row[1]:
if row[0] < row[2]:
ret_value[2]=1
else:
ret_value[0]=1
else:
if row[1]< row[3]:
ret_value[3]=1
else:
ret_value[1]=1
return ret_value

Applying Keras Model to give an output value for each row

I am learning keras and would like to understand how I can apply a classifier (sequential) to all rows in my data set and not just the x% left for test validation.
The confusion I am having is, when I define my data split, I will have a portion for train and test. How would I apply model to full data set to show me the predicted values for each row? The end goal I have is to produce an concatenate the predicted value for every customer in the data set.
dataset = pd.read_csv('BankCustomers.csv')
X = dataset.iloc[:, 3:13]
y = dataset.iloc[:, 13]
feature_train, feature_test, label_train, label_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
sc = StandardScaler()
feature_train = sc.fit_transform(feature_train)
feature_test = sc.transform(feature_test)
For completeness the classifier looks like below.
# Initialising the ANN
classifier = Sequential()
# Adding the input layer and the first hidden layer
classifier.add(Dense(activation="relu", input_dim=11, units=6, kernel_initializer="uniform"))
# Adding the second hidden layer
classifier.add(Dense(activation="relu", units=6, kernel_initializer="uniform"))
# Adding the output layer
classifier.add(Dense(activation="sigmoid", units=1, kernel_initializer="uniform"))
# Compiling the ANN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
# Fitting the ANN to the Training set
classifier.fit(feature_train, label_train, batch_size = 10, nb_epoch = 100)
The course I am doing will suggest ways to get accuracy and predictions for the test set like below, but not the full batch.
# Predicting the Test set results
label_pred = classifier.predict(feature_test)
label_pred = (label_pred > 0.5) # FALSE/TRUE depending on above or below 50%
cm = confusion_matrix(label_test, label_pred)
accuracy=accuracy_score(label_test,label_pred)
I tried concatenating the model applied to both training and test data, but i then was unsure how to ascertain which index matched up with the original data set (i.e. I don't know which of the 20% test data is relative to the original set).
I apologise in advance if this question is superfluous, I have been looking for answers on stack and via the course but so far no luck.
You can utilize pandas indexes to sort your results back to the original order.
Predict on each feature_train and feature_test (not sure why you'd want to predict on feature_train though.)
Add a new column to each feature_train and feature_test, which would contain the predictions
feature_train["predictions"] = pd.Series(classifier.predict(feature_train))
feature_test["predictions"] = pd.Series(classifier.predict(feature_test))
If you look at the indexes of each data frame above, you can see they're shuffled (because of the train_test_split).
You can now concatenate them, use sort_index, and retrieve the predictions column, which would have the predictions according to the order that appeared in your initial dataframe (X)
pd.concat([feature_train, feature_test], axis=0).sort_index()

How to combine two layers in keras using specific weights and biasses?

I am trying to rewrite a piece of tflearn code using Keras.
The goals is to combine two inputs where one input skips the first layer. The following code works in tflearn:
# Two different inputs.
inputs = tflearn.input_data(shape=[None, 10])
action = tflearn.input_data(shape=[None, 10])
#First layer used only by the inputs
net = tflearn.fully_connected(inputs, 400, activation='relu')
# Add the action tensor in the 2nd hidden layer
# Use two temp layers to get the corresponding weights and biases
t1 = tflearn.fully_connected(net, 300)
t2 = tflearn.fully_connected(action, 300)
# Combine the two layers using the weights from t1 and t2 and the bias from t2
net = tflearn.activation(tf.matmul(net,t1.W) + tf.matmul(action, t2.W) + t2.b, activation='relu')
I am trying to replicate this code in Keras using the following code:
# Two different inputs.
inputs = tf.placeholder(tf.float32, [None, 10])
action = tf.placeholder(tf.float32, [None, 10])
#First layer used only by the inputs
t1 = Sequential()
t1.add(Dense(400, activation='relu', input_shape=(1,10)))
# Add the action tensor in the 2nd hidden layer
# Use two temp layers to get the corresponding weights and biases
t1.add(Dense(300))
t2 = Sequential()
t2.add(Dense(300, input_shape=(1,10)))
# Combine the two layers
critnet = Sequential()
critnet.add(Merge([t1, t2], mode='sum'))
critnet.add(Activation('relu'))
# Create the net using the inputs and action placeholder
net = critnet([inputs, action])
The code in keras behaves differently. How to combine two layers in keras in order to get the same result as in tflearn?
You could use a Lambda layer take takes your 2 layers as input and using keras.backend to merge them the same way. I think there is K.dot for matmul.