7

I have trained two keras models with different datasets for same class labels. How could I ensemble the models keras_model.h5 and keras_model2.h5 together and make another keras model say keras_ensemble.h5. I have tried referring various internet sources but not luck. Can someone help me with the code for ensembling it? Here are the models I've trained

Please assist me through this.Thank you.

Edit: This was my code which i was able to get through with the help of the one who responded to my question Frightera

 import tensorflow.keras
    import tensorflow as tf
    from PIL import Image, ImageOps
    import numpy as np
    
    # Disable scientific notation for clarity
    np.set_printoptions(suppress=True)
    
    # Load the model
    keras_model = tensorflow.keras.models.load_model('keras_model.h5', compile=False)
    keras_model._name = 'model1'
    keras_model2 = tensorflow.keras.models.load_model('keras_model2.h5', compile=False)
    keras_model2._name = 'model2'
    models = [keras_model, keras_model2]
    #model_input = tf.keras.Input(shape=(125, 125, 3))
    model_input = tf.keras.Input(shape=(224, 224, 3))
    model_outputs = [model(model_input) for model in models]
    ensemble_output = tf.keras.layers.Average()(model_outputs)
    ensemble_model = tf.keras.Model(inputs=model_input, outputs=ensemble_output)

EDIT How do i get the keras ensemble model in h5 format??

Suriya
  • 113
  • 1
  • 8

2 Answers2

17

You can average-ensemble them like this:

models = [keras_model, keras_model2]
model_input = tf.keras.Input(shape=(125, 125, 3))
model_outputs = [model(model_input) for model in models]
ensemble_output = tf.keras.layers.Average()(model_outputs)
ensemble_model = tf.keras.Model(inputs=model_input, outputs=ensemble_output)

enter image description here


Edit: If you want to create weighted ensemble you can create a custom layer like this:

class WeightedAverageLayer(tf.keras.layers.Layer):
    def __init__(self, w1, w2, **kwargs):
        super(WeightedAverageLayer, self).__init__(**kwargs)
        self.w1 = w1
        self.w2 = w2

    def call(self, inputs):
        return self.w1 * inputs[0] + self.w2 * inputs[1]

So the output layer should look like this:

ensemble_output = WeightedAverageLayer(0.6, 0.4)(model_outputs)

Here, first model's output is scaled with a factor of 0.6. Same thing applies for the second model, with a factor of 0.4.

Note: WeightedAverageLayer(0.5, 0.5) will be identical to tf.keras.layers.Average().

Frightera
  • 4,773
  • 2
  • 13
  • 28
  • Thank you very much, I ended up with a couple of errors. I'd be really grateful if you'd look into it. I edited my question after executing your suggestion. – Suriya May 22 '21 at 13:47
  • 1
    (125,125,3) was just an example here, you need to change it according to your needings. In your case (224,224,3). And are you sure both of the models contain same class labels? Seems like one has 12 labels other has 13 labels. @ShooriyaSridharan – Frightera May 22 '21 at 13:56
  • it turned out i had 13 labels in one of the models, I've rectified it and it works fine now. How do I get a keras(h5) of the new ensemble model? – Suriya May 22 '21 at 19:30
  • 1
    Same with any other keras models. Just save it with `model.save()` – Frightera May 22 '21 at 19:31
  • In here model average was used, so how should I change the code if I want to use weighted technique and give weights to the two models separately ? – ArchieVon Mar 13 '22 at 17:16
  • @ArchieVon You can do this with a custom layer. I've edited the answer. Let me know if it is helpful. – Frightera Mar 13 '22 at 17:33
  • Could we have different model_input for these sub-models? – Jiadong Chen Nov 22 '22 at 07:54
  • How different? Completely different or have same channels, like 3? @JiadongChen – Frightera Nov 22 '22 at 11:59
  • @Frightera thanks for the solution, it works! How do I evaluate this model? Again, I am trying to implement a stack ensemble model and I am stuck at a point. I am attaching the link if you can help me. Link: https://stackoverflow.com/questions/75327384/valueerror-input-data-in-numpyarrayiterator-should-have-rank-4-you-passed – Rezuana Haque Feb 03 '23 at 14:46
  • Model can be evulated by using `model.evaluate()` like any Keras model. – Frightera Feb 04 '23 at 21:53
3
import tensorflow.keras
import tensorflow as tf
from PIL import Image, ImageOps
import numpy as np

# Disable scientific notation for clarity
np.set_printoptions(suppress=True)

# Load the model
keras_model = tensorflow.keras.models.load_model('APPLE/apple_model1.h5', compile=False)
keras_model._name = 'model1'
keras_model2 = tensorflow.keras.models.load_model('APPLE/apple_model2.h5', compile=False)
keras_model2._name = 'model2'
models = [keras_model, keras_model2]
#model_input = tf.keras.Input(shape=(125, 125, 3))
model_input = tf.keras.Input(shape=(224, 224, 3))
model_outputs = [model(model_input) for model in models]
ensemble_output = tf.keras.layers.Average()(model_outputs)
ensemble_model = tf.keras.Model(inputs=model_input, outputs=ensemble_output)  

ensemble_model.save('APPLE/ensemble_apple.h5')
Suriya
  • 113
  • 1
  • 8