Reputation: 364
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
)
Upvotes: 0
Views: 403
Reputation: 631
https://keras.io/examples/vision/captcha_ocr/
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
Upvotes: 0
Reputation: 631
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!
Upvotes: 2