Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keras layer with int inputs cannot be built

I have a complex keras model in which one of the layers is a custom pretrained layer which expects "int32" as inputs. This model is implemented as a class that inherits from Model and it is implemented like this:

class MyModel(tf.keras.models.Model):

    def __init__(self, size, input_shape):
        super(MyModel, self).__init__()
        self.layer = My_Layer()
        self.build(input_shape)

    def call(self, inputs):
        return self.layer(inputs)

But when it reaches the self.build method, it throws the next error:

ValueError: You cannot build your model by calling `build` if your layers do not support float type inputs. Instead, in order to instantiate and build your model, `call` your model on real tensor data (of the correct dtype).

How can I fix it?

like image 997
Rodrigo Serna Pérez Avatar asked Sep 09 '25 23:09

Rodrigo Serna Pérez


2 Answers

The exception is thrown when building a model with model.build.

model.build function build a model based on given input shape.

The error is raised because when we trying to build a model, it first calls a model with x argument depending on input shape type in the following code

if (isinstance(input_shape, list) and
    all(d is None or isinstance(d, int) for d in input_shape)):
  input_shape = tuple(input_shape)
if isinstance(input_shape, list):
  x = [base_layer_utils.generate_placeholders_from_shape(shape)
        for shape in input_shape]
elif isinstance(input_shape, dict):
  x = {
      k: base_layer_utils.generate_placeholders_from_shape(shape)
      for k, shape in input_shape.items()
  }
else:
  x = base_layer_utils.generate_placeholders_from_shape(input_shape)

x is a TensorFlow placeholder here. So when trying to call a model with x as an input it will pop a TypeError and the result except for block will work and give an error.

I assume your input shape is 16x16. Instead of using self.build([(16,16)]) this, call the model based on real tensor

inputs = tf.keras.Input(shape=(16,))
self.call(inputs)

like image 85
Zerzavot Avatar answered Sep 12 '25 14:09

Zerzavot


Workaround

I've encountered the same problem when trying to export model with multiple Int-typed input tensor as SavedModel. I worked around by overriding the build method and manually specifying self._build_input_shape. So you solution would look like:

class MyModel(tf.keras.models.Model):
    def __init__(self, size, input_shape):
        super(MyModel, self).__init__()
        self.layer = My_Layer()
        self.build(input_shape)

    def call(self, inputs):
        return self.layer(inputs)

    def build(self, input_shapes):
        super(tf.keras.Model, self).build(input_shapes)

What happened in the original code

The default build method of tf.keras.Model object will treat by default input tensors as float tensors, which ends up throwing the exception. Such behavior of tf.keras.Model is defined here, where inputs for your model are created by base_layer_utils.generate_placeholders_from_shape, which will specify dtype as float.

What would happen with the workaround

As tf.keras.Model.build would finally invoke it's super class's build function tf.keras.layer.Layer.build, the workaround skips tf.keras.Model.build logic that causes the problem, but you may have to add complemental code after that in case you rely on other logics in defined in tf.keras.Model.build

like image 25
Boris Polonsky Avatar answered Sep 12 '25 13:09

Boris Polonsky