0

I trained a Keras model:

class CTCLayer(layers.Layer):
    def __init__(self, name=None):
        super().__init__(name=name)
        self.loss_fn = keras.backend.ctc_batch_cost

    def call(self, y_true, y_pred):
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        batch_len = tf.cast(tf.shape(y_true)[0], dtype="int64")
        input_length = tf.cast(tf.shape(y_pred)[1], dtype="int64")
        label_length = tf.cast(tf.shape(y_true)[1], dtype="int64")

        input_length = input_length * tf.ones(shape=(batch_len, 1), dtype="int64")
        label_length = label_length * tf.ones(shape=(batch_len, 1), dtype="int64")

        loss = self.loss_fn(y_true, y_pred, input_length, label_length)
        self.add_loss(loss)

        # At test time, just return the computed predictions
        return y_pred




def build_model():
    # Inputs to the model
    input_img = layers.Input(
        shape=(img_width, img_height, 4), name="image", dtype="float32"
    )
    labels = layers.Input(name="label", shape=(None,), dtype="float32")

    # First conv block
    x = layers.Conv2D(
        32,
        (3,3),
        activation="relu",
        kernel_initializer="he_normal",
        padding="same",
        name="Conv1",
    )(input_img)
    x = layers.MaxPooling2D((2, 2), name="pool1")(x)

    # Second conv block
    x = layers.Conv2D(
        64,
        (3, 3),
        activation="relu",
        kernel_initializer="he_normal",
        padding="same",
        name="Conv2",
    )(x)
    x = layers.MaxPooling2D((2, 2), name="pool2")(x)


    # We have used two max pool with pool size and strides 2.
    # Hence, downsampled feature maps are 4x smaller. The number of
    # filters in the last layer is 64. Reshape accordingly before
    # passing the output to the RNN part of the model
    new_shape = ((img_width // 4), (img_height // 4) * 64)
    x = layers.Reshape(target_shape=new_shape, name="reshape")(x)
    x = layers.Dense(64, activation="relu", name="dense1")(x)
    x = layers.Dropout(0.2)(x)

    # RNNs
    x = layers.Bidirectional(layers.LSTM(128, return_sequences=True, dropout=0.1))(x)
    x = layers.Bidirectional(layers.LSTM(64, return_sequences=True, dropout=0.1))(x)

    # Output layer
    x = layers.Dense(len(characters) + 1, activation="softmax", name="dense2")(x)

    # Add CTC layer for calculating CTC loss at each step
    output = CTCLayer(name="ctc_loss")(labels, x)

    # Define the model
    model = keras.models.Model(
        inputs=[input_img, labels], outputs=output, name="ocr_model_v1"
    )
    # Optimizer
    opt = keras.optimizers.Adam(learning_rate=1e-4)
    # Compile the model and return
    model.compile(optimizer=opt)
    return model


# Get the model
model = build_model()
model.summary()


epochs = 100
early_stopping_patience = 10
# Add early stopping
early_stopping = keras.callbacks.EarlyStopping(
    monitor="val_loss", patience=early_stopping_patience, restore_best_weights=True
)

# Train the model
history = model.fit(
    train_dataset,
    validation_data=validation_dataset,
    epochs=epochs,
    callbacks=[early_stopping],
)
# serialize model to JSON
model_json = model.to_json()
with open("model.json", "w") as json_file:
    json_file.write(model_json)
# serialize weights to HDF5
model.save_weights("model.h5")

But when I try to load it like this in another code:

# # load json and create model
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
model = model_from_json(loaded_model_json,custom_objects={'CTCLayer': CTCLayer})

# load weights into new model
model.load_weights("model.h5")
print("Loaded model from disk")

opt = keras.optimizers.Adam(learning_rate=1e-4)
# Compile the model
model.compile(loss="ctc_loss",optimizer=opt)

# Get the prediction model by extracting layers till the output layer
prediction_model = keras.models.Model(
    model.get_layer(name="image").input, model.get_layer(name="dense2").output
)
prediction_model.summary()

And then evaluate it:

for batch in validation_dataset.take(1):
    batch_images = batch["image"]    
    prediction_model.evaluate(batch_images)

I get the following error:

    RuntimeError: You must compile your model before training/testing. Use `model.compile(optimizer, loss)`.

But I've already compiled my model. So what's wrong?

If all of this looks messy, in summary, I was basically trying to implement this Keras tutorial and I can save the model but I can't load the model. Can anyone point me in the right direction? I shall note that I think one of the reasons I cannot use trivial methods to save and load the model is the fact that the model has a custom layer/loss function. (CTCLayer)

2 Answers 2

2
prediction_model = keras.models.Model(
    model.get_layer(name="image").input, model.get_layer(name="dense2").output
)
# Optimizer
opt = keras.optimizers.Adam()
# Compile the model and return# Biên dịch mô hình
prediction_model.compile(optimizer=opt)
prediction_model.summary()

### Evaluate the model
loss = prediction_model.evaluate(validation_dataset)#(x_valid, y_valid, verbose=2)

This worked for me. and you should see this TypeError: __init__() got an unexpected keyword argument 'trainable' there is a error in class CTCLayer(layers.Layer) however, I have been unsucessful in loading this model https://keras.io/examples/vision/captcha_ocr/ it's bad in predicting help me!

Sign up to request clarification or add additional context in comments.

Comments

0

https://keras.io/examples/vision/captcha_ocr/ enter image description here

error exactly is in here each time you use trained model to predict, characters set will be loaded again; and split_data will return other result if ur characters set lacks something in my case, my characters set lacks some characters (<24 characters) and maybe some numbers (3, 5, 6 for example)

update:

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import string


class LabelCharacters(object):
    characters_set = ['0']
def __init__(self, characters_set=None):
    if characters_set:
        self.characters_set = characters_set
    self.characters_dic = {c: p for p, c in enumerate(characters_set)}
    self.char_to_num = layers.experimental.preprocessing.StringLookup(
        vocabulary=list(self.characters_set), mask_token=None)
    # Mapping integers back to original characters
    self.num_to_char = layers.experimental.preprocessing.StringLookup(
        vocabulary=self.char_to_num.get_vocabulary(), mask_token=None, invert=True)
    self.num_class = len(self.characters_set) + 1
    super().__init__()

# A utility function to decode the output of the network
def decode_batch_predictions(self, pred, max_length):
    input_len = np.ones(pred.shape[0]) * pred.shape[1]
    # Use greedy search. For complex tasks, you can use beam search
    results = keras.backend.ctc_decode(pred, input_length=input_len, greedy=True)[0][0][:, :max_length]
    # Iterate over the results and get back the text
    output_text = [tf.strings.reduce_join(self.num_to_char(res)).numpy().decode("utf-8") for res in results]
    return output_text

def encode_label(self, label):
    return self.char_to_num(tf.strings.unicode_split(label, input_encoding="UTF-8"))

def decode_label(self, label):
    try:
        return tf.strings.reduce_join(self.num_to_char(label)).numpy().decode("utf-8")
    except:
        return 'FAIL'

s = [z for z in string.ascii_uppercase]
zs = [z for z in range(10)]
s.extend(zs)

label_digit = LabelCharacters(characters_set = s)
##label_digit = LabelCharacters(characters_set=['{0}'.format(_) for _ in range(0, 10)]) ` 

label.py and in main py file:

from label import label_digit

5 Comments

Okay, but how to fix this?
import string characters = [z for z in string.ascii_uppercase]; zs = [z for z in range(10)]; characters.extend(zs);
and put it in other file, then import
This is a complex problem. Please edit your post with corrected code.
I have updated my answer; is there any thing more I can help; do u succeed?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.