How to combine 2 trained models in Keras - merge

I want to to concatenate the last layer before the output of 2 trained models and have a new model that uses the merged layer to give predictions. below is the relevant parts of my code:
model1 = load_model("model1_location.model")
model2 = load_model("model1_location.model")
merged_model = Sequential(name='merged_model')
merged_model.add(merge([model1.layers[-1],model2.layers[-1]]))
merged_model.add(Dense(3, activation='softmax'))
The above code gives the following error:
ValueError: Layer merge_2 was called with an input that isn't a symbolic tensor. Received type: <class 'keras.layers.core.Dense'>.
What is the correct way to combine those models, Alternatively how do I get a symbolic tensor from a layer?

you need to get the output attribute like so:
merged_model.add(merge([model1.layers[-1].output, model2.layers[-1].output]))

Related

NSLocalizedDescription = "The size of the output layer 'Identity' in the neural network does not match the number of classes in the classifier."

I just created a model that does a binary classification and has a dense layer of 1 unit at the end. I used Sigmoid activation. However, I get this error now when I wanna convert it to CoreML.
I tried to change the number of units to 2 and activation to softmax but still didn't work.
import coremltools as ct
#1. define input size
image_input = ct.ImageType(scale=1/255)
#2. give classifier
classifier_config = coremltools.ClassifierConfig(class_labels=[0, 1]) #ERROR here
#3. convert the model
coreml_model = coremltools.convert("mask_detection_model_surgical_mask.h5",
inputs=[image_input], classifier_config=classifier_config)
#4. load and resize an example image
example_image = Image.open("Unknown3.jpg").resize((256, 256))
# Make a prediction using Core ML
out_dict = coreml_model.predict({mymodel.input_names[0]: example_image})
print(out_dict["classLabels"])
# save to disk
#coreml_model.save("FINALLY.mlmodel")
I found the answer to my question.
Use Softmax activation and 2 Dense units as the final layer with either loss='binary_crossentropy' or `loss='categorical_crossentropy'
Good luck to hundreds of people who posted a similar question but received no answer.

merge different models with different inputs Keras

I would like to train two different Conv models in Keras with different input dimensions.
I have:
input_size=4
input_sizeB=6
model=Sequential()
model.add(Conv2D(filters=10,input_shape=
(1,time_steps,input_size),kernel_size(24,3),activation='relu',data_format='channels_first',kernel_regularizer=regularizers.l2(0.001)))
model.add(Flatten())
A= model.add(Dense(25,
activation='tanh',kernel_regularizer=regularizers.l2(0.003)))
model2=Sequential()
model2.add(Conv2D(filters=10,input_shape=
(1,time_steps,input_sizeB),kernel_size(24,3),activation='relu',data_format='channels_first',kernel_regularizer=regularizers.l2(0.001)))
model2.add(Flatten())
B= model2.add(Dense(25,
activation='tanh',kernel_regularizer=regularizers.l2(0.003)))
Now I would merge the two dense layers at the end of both Conv net.
How I should do?
Using the Sequential API, you can use the Merge layer (doc) as follows:
merged_layer = Merge([model, model2], mode='concat') # mode='sum', 'ave', etc.
merged_model = Sequential()
merged_model.add(merged_layer)
Note that this will throw a warning (depending on your version, the code should still work), as sequential Merge is getting deprecated. You could otherwise consider the Functional API, which offers some more flexibility in that regards c.f. the several pre-defined merge layers Keras provides depending on the operation you want to use (doc). Find an example below:
merged_layer = Concatenate()([model.output, model2.output])
merged_model = Model([model.input, model2.input], merged_layer)

Keras - use part of the input at later stage in sequential model

I'm training a CNN. My input is an image and a few metadata. I'd like to train a CNN that only looks at the image in the convolutional stages, and then uses the output of the convolutional stages and the metadata in the final dense layers.
metadata -----------------
|-> dense -> output
image -> Convolutions -
How can I do this with Keras? Can I feed input that has not a rectangular shape?
For instance if the image is (255, 255, 3) and the metadata (10) how would this work?
I've found this issue that seems related but I don't get how they split the input and merge the second part with the intermediate output later on.
You need to use the Functional API with a multi-input model.
An example could be:
from keras.layers import Input, Conv1D, Dense, concatenate
#Image data
conv_input = Input(shape=conv_input_shape)
conv_output = Conv1D(nfilters,kernel_shape)(conv_input)
#Metadata
metadata_input = Input(shape=metadata_shape)
#Merge and add dense layer
merge_layer = concatenate([metadata_input, conv_output])
main_output = Dense(dense_size)(merge_layer)
# Define model with two inputs
model = Model(inputs=[conv_input, metadata_input], outputs=[main_output])
Hope this helps!

Using hidden activations in loss function

I want to create a custom loss function for a double-input double-output model in Keras that:
minimizes the reconstruction error of two autoencoders;
maximizes the correlation of the bottleneck features of the autoencoders.
For this I need to pass to the loss function:
both inputs;
both outputs / reconstructions;
output of intermediate layers for both (hidden activations).
I know I can pass both inputs and outputs to Model, but am struggling to find a way to pass the hidden activations.
I could create two new Models that have the output of the intermediate layers and pass that to loss, like:
intermediate_layer_model1 = Model(input=input1, output=autoencoder.get_layer('encoded1').output)
intermediate_layer_model2 = Model(input=input2, output=autoencoder.get_layer('encoded2').output)
autoencoder.compile(optimizer='adadelta', loss=loss(intermediate_layer_model1, intermediate_layer_model2))
But still, I would need to find a way to match the y_true in loss to the correct intermediate model.
What is the right way to approach this?
Edit
Here's an approach that I think should work. Simplified:
# autoencoder 1
input1 = Input(shape=(input_dim,))
encoded1 = Dense(encoding_dim, activation='relu', name='encoded1')(input1)
decoded1 = Dense(input_dim, activation='sigmoid', name='decoded1')(encoded1)
# autoencoder 2
input2 = Input(shape=(input_dim,))
encoded2 = Dense(encoding_dim, activation='relu', name='encoded2')(input2)
decoded2 = Dense(input_dim, activation='sigmoid', name='decoded2')(encoded2)
# merge encodings
merge_layer = merge([encoded1, encoded2], mode='concat', name='merge', concat_axis=1)
model = Model(input=[input1, input2], output=[decoded1, decoded2, merge_layer])
model.compile(optimizer='rmsprop', loss={
'decoded1': 'binary_crossentropy',
'decoded2': 'binary_crossentropy',
'merge': correlation,
})
Then in correlation I can split y_pred and do the calculations.
How about:
Defining a single model with a multiple outputs (be sure that you named a coding and reconstruction layer properly):
duo_model = Model(input=input, output=[coding_layer, reconstruction_layer])
Compiling your model with two different losses (or even performing a loss reweighting):
duo_model.compile(optimizer='rmsprop',
loss={'coding_layer': correlation_loss,
'reconstruction_layer': 'mse'})
Taking your final model as a:
encoder = Model(input=input, output=[coding_layer])
autoencoder = Model(input=input, output=[reconstruction_layer])
After proper compilation this should do the job.
When it comes to defining a proper correlation loss function there are two ways:
when coding layer and your output layer have the same dimension -
you could easly use predefinied cosine_proximity function from
Keras library.
when coding layer has different dimensonality -
you shoud first find embedding of coding vector and reconstruction vector to the same space and then - compute correlation there. Remember that this embedding should either be a Keras layer / function or Theano / Tensor flow operation (depending on which backend you are using). Of course you can compute both embedding and correlation function as a part of one loss function.

How do I assign classes to a Matlab dataset?

I'm currently trying to create a diagnostic tool for predicting disease outcome. I want to do this by training a Nearest Mean Classifier (NMC) over candidate genes and evaluate its error by using a test set. For this end I generated a train dataset and test dataset using gendat from PrTools. Only, when I want to train the NMC Matlab gives the error that the train dataset doesn't have classes. How do I assign classes to the dataset?
load vantVeer.mat
% D.data is data from vantVeer
[train_data,test_data,I_train,I_test]=gendat(D.data',39);
W=nmc(train_data)
Error using isvaldfile (line 48)
Labeled datafile(set) expected
Error in nmc (line 52)
isvaldfile(a,1,2); % at least 1 object per class, 2 classes
You should generate a dataset with the data and its classes like below:
traindataset = dataset(train_data, train_classes);
testdataset = dataset(test_data, test_classes);
W = nmc(traindataset)