I have a function that returns a Keras model. However, as an exercise, I’m trying to convert it to a keras.Model class, but I’m having difficulty.
This is the function:
def siamese_loss_network():
inputs = keras.layers.Input((128, 128, 3))
x = keras.applications.efficientnet.preprocess_input(inputs)
base = keras.applications.EfficientNetB0(include_top=False, input_tensor=inputs, pooling = 'max')
head = base.output
x = keras.layers.Dense(256, activation="relu")(head)
x = keras.layers.Dense(32)(x)
embedding_network = keras.Model(inputs, x)
input_1 = keras.layers.Input((128, 128, 3),name="input_layer_base_r")
input_2 = keras.layers.Input((128, 128, 3),name="input_layer_base_l")
tower_1 = embedding_network(input_1)
tower_2 = embedding_network(input_2)
merge_layer = keras.layers.Lambda(euclidean_distance, output_shape=(1,))(
[tower_1, tower_2]
)
output_layer = keras.layers.Dense(1, activation="sigmoid")(merge_layer)
siamese = keras.Model(inputs=[input_1, input_2], outputs=output_layer)
return siamese
def euclidean_distance(vects):
x, y = vects
sum_square = ops.sum(ops.square(x - y), axis=1, keepdims=True)
return ops.sqrt(ops.maximum(sum_square, keras.backend.epsilon()))
When running:
model = siamese_loss_network()
model.compile(optimizer=Adam(), loss=loss())
model.summary()
I get the following output:
Model: "functional_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃ Connected to ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ input_layer_base_r │ (None, 128, 128, 3) │ 0 │ - │
│ (InputLayer) │ │ │ │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ input_layer_base_l │ (None, 128, 128, 3) │ 0 │ - │
│ (InputLayer) │ │ │ │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ functional (Functional) │ (None, 32) │ 4,385,731 │ input_layer_base_r[0][0], │
│ │ │ │ input_layer_base_l[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ lambda (Lambda) │ (None, 1) │ 0 │ functional[0][0], │
│ │ │ │ functional[1][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ dense_2 (Dense) │ (None, 1) │ 2 │ lambda[0][0] │
└───────────────────────────────┴───────────────────────────┴─────────────────┴────────────────────────────┘
Total params: 4,385,733 (16.73 MB)
Trainable params: 4,343,710 (16.57 MB)
Non-trainable params: 42,023 (164.16 KB)
So here is my adaptation for a class that inherits keras.Model:
class SiameseModel(keras.Model):
def __init__(self):
super().__init__()
self.inputs = keras.layers.Input((128, 128, 3))
self.input_1 = keras.layers.Input((128, 128, 3),name="input_layer_base_r")
self.input_2 = keras.layers.Input((128, 128, 3),name="input_layer_base_l")
self.base = keras.applications.EfficientNetB0(include_top=False, input_tensor=self.inputs, pooling = 'max')
self.dense_1 = keras.layers.Dense(256, activation="relu")
self.dense_2 = keras.layers.Dense(32)
self.merge_layer = keras.layers.Lambda(euclidean_distance, output_shape=(1,))
self.output_layer = keras.layers.Dense(1, activation="sigmoid")
def call(self, inputs):
head = self.base.output
x = self.dense_1(head)
x = self.dense_2(x)
embedding_network = keras.Model(inputs, x)
tower_1 = embedding_network(self.input_1)
tower_2 = embedding_network(self.input_2)
merge = self.merge_layer([tower_1, tower_2])
output = self.output_layer(merge)
return keras.Model(inputs=[self.input_1, self.input_2], outputs=output)
When running:
model = SiameseModel()
model.compile(optimizer=Adam(), loss=loss())
model.summary()
i got the error:
Traceback (most recent call last):
File "D:[project path]main.py", line 20, in <module>
model.summary()
File "C:[user path].condaenvs[env path]libsite-packageskerassrcutilstraceback_utils.py", line 122, in error_handler
raise e.with_traceback(filtered_tb) from None
File "C:[user path].condaenvs[env path]libsite-packagesoptreeops.py", line 594, in tree_map
return treespec.unflatten(map(func, *flat_args))
ValueError: Undefined shapes are not supported.
If I try to run mode.fit()
, the model trains without any problems, but it’s strange not being able to run model.summary()
first. I feel like something is wrong.
I read this issue on Keras repo, but i honestly didn’t understand the reason for the error, nor how to resolve it. Could anyone enlighten me about this?
Python version: Python 3.10.13
pip version: 24.0
Tensorflow version: 2.16.1
Keras version: Version: 3.4.1
Grateful for the attention!
1