如何使用 keras 加载保存的模型? (错误: : TypeError: __init__() 得到了一个意外的关键字参数“可训练”)

Posted

技术标签:

【中文标题】如何使用 keras 加载保存的模型? (错误: : TypeError: __init__() 得到了一个意外的关键字参数“可训练”)【英文标题】:How to load a saved model with keras? (Error : : TypeError: __init__() got an unexpected keyword argument 'trainable') 【发布时间】:2021-10-06 11:12:12 【问题描述】:

我根据 Keras 代码示例中提供的内容创建了一个验证码模型。 但是当我加载模型时,会弹出一个错误。

我向你展示我在 Jupyter notebook 中编写的代码。

STEP1) 模型构建

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, 1), 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.25))(x)
    x = layers.Bidirectional(layers.LSTM(64, return_sequences=True, dropout=0.25))(x)

    # Output layer
    x = layers.Dense(
        len(char_to_num.get_vocabulary()) + 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()
    # Compile the model and return
    model.compile(optimizer=opt)
    return model


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

STEP2) 训练模型

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],
)

STEP3) 检查预测

# 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()

# A utility function to decode the output of the network
def decode_batch_predictions(pred):
    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 = []
    for res in results:
        res = tf.strings.reduce_join(num_to_char(res)).numpy().decode("utf-8")
        output_text.append(res)
    return output_text


#  Let's check results on some validation samples
for batch in validation_dataset.take(1):
    batch_images = batch["image"]
    batch_labels = batch["label"]

    preds = prediction_model.predict(batch_images)
    pred_texts = decode_batch_predictions(preds)

    orig_texts = []
    for label in batch_labels:
        label = tf.strings.reduce_join(num_to_char(label)).numpy().decode("utf-8")
        orig_texts.append(label)

    _, ax = plt.subplots(4, 4, figsize=(15, 8))
    for i in range(len(pred_texts)):
        img = (batch_images[i, :, :, 0] * 255).numpy().astype(np.uint8)
        img = img.T
        title = f"Prediction: pred_texts[i]"
        ax[i // 4, i % 4].imshow(img, cmap="gray")
        ax[i // 4, i % 4].set_title(title)
        ax[i // 4, i % 4].axis("off")
plt.show()

STEP4) 保存模型

model.save("ocr_model.h5")

STEP5) 加载模型

model = load_model('./ocr_model.h5',custom_objects='CTCLayer':CTCLayer)

我收到以下错误消息。

TypeError: init() 得到了一个意外的关键字参数“可训练”

我又试了一次这段代码。

model = load_model('./ocr_model.h5')

我收到以下错误消息。

ValueError:未知层:CTCLayer。请确保将此对象传递给custom_objects 参数。详情请见https://www.tensorflow.org/guide/keras/save_and_serialize#registering_the_custom_object。

如何使用存储模型?

【问题讨论】:

【参考方案1】:

根据这个帖子:TypeError: __init__() got an unexpected keyword argument 'trainable',

您应该更新__init__ 以包含**kwargs 以解决您的问题(奇怪的是,我在TensorFlow 2.3.0 中使用了确切的模型+配置并且无法重现此问题(Ubuntu 18.04

【讨论】:

以上是关于如何使用 keras 加载保存的模型? (错误: : TypeError: __init__() 得到了一个意外的关键字参数“可训练”)的主要内容,如果未能解决你的问题,请参考以下文章

如何将保存的模型转换或加载到 TensorFlow 或 Keras?

使用 theano 后端加载 keras 模型时出现断言错误

如何将 keras 模型与其他数据一起保存并完全加载?

如何使用自定义损失函数加载 Keras 模型?

JSONDecodeError:加载 tf.Keras 模型时的期望值

如何在 Keras 中保存经过训练的模型以在应用程序中使用它?