keras
keras copied to clipboard
TypeError: Cannot serialize object Ellipsis of type <class 'ellipsis'>
In chapter 8 the book "Deep Learning with Python" it explains how to use a pretrained model. However, the provided code doesn't run, and an error message is obtained when executing model.fit:
TypeError: Cannot serialize object Ellipsis of type <class 'ellipsis'>.
To be serializable, a class must implement the 'get_config()' method.
I am using Tensorflow version 2.15.0 and keras version 3.0.4
The program uses the dogs-vs-cats dataset from kaggle. It creates a smaller subset and creates a training, validation and test dataset. This all works as it is used for some other examples in the book. It then uses the pretrained VGG16 model and trains a dense layer connected to it.
Here it is the code:
data_augmentation = keras.Sequential(
[
keras.layers.RandomFlip("horizontal"),
keras.layers.RandomRotation(0.1),
keras.layers.RandomZoom(0.2)
]
)
inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = keras.applications.vgg16.preprocess_input(x)
x = conv_base(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(256)(x)
x = keras.layers.Dropout(0.5)(x)
outputs = keras.layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs, outputs)
model.compile(
loss="binary_crossentropy",
optimizer="rmsprop",
metrics=["accuracy"]
)
callbacks = [
keras.callbacks.ModelCheckpoint(
filepath="features_extraction_with_data_augmentation.keras",
save_best_only=True,
monitor="val_loss"
)
]
history = model.fit( # error thrown here
train_dataset,
epochs=50,
validation_data=validation_dataset,
callbacks=callbacks
)
Hi, Since the new .keras saving format, for custom objects, you must define a get_config() method. You can find complete details here https://keras.io/guides/serialization_and_saving/#custom-objects
I also encountered this error on tf 2.15.0. It reproduces with this snippet:
import tensorflow as tf
x = tf.keras.layers.Input(shape=(42,))
model = tf.keras.Model(x, x[...])
model.save("tmp.keras", save_format="keras")
# TypeError: Cannot serialize object Ellipsis of type <class 'ellipsis'>. To be serializable, a class must implement the `get_config()` method.
Yes, when the save_format="keras", you need to implement get_config() for Custom Objects.
@sachinprasadhs does my example have custom objects?
Here is what I think is happening:
TFSlicingOpDispatcheris used to create aSlicingOpLambdalayer, which will represent the tensor slicing. In the process, if transforms arguments with_slice_to_dict()._slice_to_dict()encodessliceinstances to dicts, but leaves everything else (ints and Ellipsis) as-is. These encoded args end up in the layer's config (get_config()is derived fromTFOpLambda).- When serializing a config with Ellipsis,
tf.keras.saving.serialize_keras_object(...)raises theTypeError, because...is not handled there.
A simple solution might be to handle ... (Ellipsis) in _slice_to_dict() and _dict_to_slice().
In the example I missed to include what conv_base(x) was. Here it is:
conv_base = keras.applications.vgg16.VGG16(
weights="imagenet",
include_top=False,
input_shape=(180, 180, 3))
So, there is no custom model per se, all that is being used is inside the Keras library:
- A data augmentation layer composed by keras layers:
RandomFlip,RandomRotationandRandomZoom. - A layer that uses the VGG16 architecture from keras
- Normal keras layers such as
Flatten,DenseorDropout.
@emosqueira I also got stuck on this code snippet from the book. I found a workaround by dropping the .keras extension from the filepath. This seems to save the model and all its metadata to a folder instead of packed into .keras file.
callbacks = [
keras.callbacks.ModelCheckpoint(
filepath="features_extraction_with_data_augmentation", # <-- removed the `.keras` ext
save_best_only=True,
monitor="val_loss"
)
]
I agree with you though, this isn't a custom model so I think the .keras file should work automatically.
Hey @emosqueira I found the same issue and solved it by following the solution* from https://stackoverflow.com/questions/77716307/typeerror-cannot-serialize-object-ellipsis-of-type-class-ellipsis:
You can simply wrap the function keras.applications.vgg16.preprocess_input in keras.layers.Lambda as follows:
#x = keras.applications.vgg16.preprocess_input(x)
x = keras.layers.Lambda(lambda x: keras.applications.vgg16.preprocess_input(x))(x)
and you would need to set safe_mode=False when you load the model with Lambda layer:
test_model = keras.models.load_model("feature_extraction_with_data_augmentation.keras", safe_mode=False)
Hope this helps~~
*Only worked on google colab (tensorflow==2.15.0 and keras==2.15.0), still having an error on my local machine with tensorflow==2.16.1 and keras==3.0.5:
NotImplementedError: Exception encountered when calling Lambda.call().
We could not automatically infer the shape of the Lambda's output. Please specify the `output_shape` argument for this Lambda layer.
Arguments received by Lambda.call():
• args=('<KerasTensor shape=(None, 180, 180, 3), dtype=float32, sparse=False, name=keras_tensor_645>',)
• kwargs={'mask': 'None'}
This issue is stale because it has been open for 14 days with no activity. It will be closed if no further activity occurs. Thank you.
This works for me.
@tf.keras.utils.register_keras_serializable()
class PreprocessInput(tf.keras.layers.Layer):
def call(self,inputs):
return tf.reverse(inputs, axis=[-1]) - tf.constant([103.939, 116.779, 123.68], dtype=tf.float32)
This issue is stale because it has been open for 14 days with no activity. It will be closed if no further activity occurs. Thank you.
This issue was closed because it has been inactive for 28 days. Please reopen if you'd like to work on this further.