You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Keras构建手写识别模型时遇输入为空错误求助

手写文本识别模型训练报错:ValueError: inputs argument cannot be empty

环境配置

  • MacOS Sonoma 14.5,Python 3.12.3
  • VSCode(最新版本)
  • Tensorflow 2.16.1
  • Matplotlib 3.9.0
  • Keras 3.3.3

问题描述

跟随Keras官方教程构建手写文本识别模型(HTR),训练启动时失败,报错信息如下:

2024-06-02 19:26:11.552695: W tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
Traceback (most recent call last):
File "/Volumes/Ugreen SSD/Py/keras-HTR-ENG/model.py", line 355, in
prediction_model = keras.models.Model(
^^^^^^^^^^^^^^^^^^^
File "/Volumes/Ugreen SSD/Py/keras-HTR-ENG/.venv/lib/python3.12/site-packages/keras/src/models/model.py", line 143, in new
return functional.Functional(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Volumes/Ugreen SSD/Py/keras-HTR-ENG/.venv/lib/python3.12/site-packages/keras/src/utils/tracking.py", line 26, in wrapper
return fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^
File "/Volumes/Ugreen SSD/Py/keras-HTR-ENG/.venv/lib/python3.12/site-packages/keras/src/models/functional.py", line 162, in init
Function.init(self, inputs, outputs, name=name, **kwargs)
File "/Volumes/Ugreen SSD/Py/keras-HTR-ENG/.venv/lib/python3.12/site-packages/keras/src/ops/function.py", line 62, in init
raise ValueError(
ValueError: inputs argument cannot be empty. Received:
inputs=[]
outputs=<KerasTensor shape=(None, 32, 79), dtype=float32, sparse=False, name=keras_tensor_20>

问题代码片段

class EditDistanceCallback(keras.callbacks.Callback):
    def __init__(self, pred_model):
        super().__init__()
        self.prediction_model = pred_model

    def on_epoch_end(self, epoch, logs=None):
        edit_distances = []

        for i in range(len(validation_images)):
            labels = validation_labels[i]
            predictions = self.prediction_model.predict(validation_images[i])
            edit_distances.append(calculate_edit_distance(labels, predictions).numpy())

        print(
            f"Mean edit distance for epoch {epoch + 1}: {np.mean(edit_distances):.4f}"
        )
epochs = 10  # 要得到好结果至少需要训练50轮

model = build_model()
prediction_model = keras.models.Model(
    model.get_layer(name="image").input, model.get_layer(name="dense2").output
)
edit_distance_callback = EditDistanceCallback(prediction_model)

# 训练模型
history = model.fit(
    train_ds,
    validation_data=validation_ds,
    epochs=epochs,
    callbacks=[edit_distance_callback],
)

排查情况

猜测是向keras.models.Model传入了空值,但已确认模型能正确识别图像数量,参数输出正常:

Total params: 423,823 (1.62 MB)
 Trainable params: 423,823 (1.62 MB)
 Non-trainable params: 0 (0.00 B)

所有图片均为原始未编辑的.png格式,已多次下载数据集排除损坏问题。

模型构建代码

def build_model():
    # 模型输入
    input_img = keras.Input(shape=(image_width, image_height, 1), name="image")
    labels = keras.layers.Input(name="label", shape=(None,))

    # 第一个卷积块
    x = keras.layers.Conv2D(
        32,
        (3, 3),
        activation="relu",
        kernel_initializer="he_normal",
        padding="same",
        name="Conv1",
    )(input_img)
    x = keras.layers.MaxPooling2D((2, 2), name="pool1")(x)

    # 第二个卷积块
    x = keras.layers.Conv2D(
        64,
        (3, 3),
        activation="relu",
        kernel_initializer="he_normal",
        padding="same",
        name="Conv2",
    )(x)
    x = keras.layers.MaxPooling2D((2, 2), name="pool2")(x)

    # 我们用了两次池化,步长和池化大小都是2,因此特征图缩小为原来的1/4
    # 最后一层卷积有64个滤波器,需要先调整形状再传入RNN部分
    new_shape = ((image_width // 4), (image_height // 4) * 64)
    x = keras.layers.Reshape(target_shape=new_shape, name="reshape")(x)
    x = keras.layers.Dense(64, activation="relu", name="dense1")(x)
    x = keras.layers.Dropout(0.2)(x)

    # RNN层
    x = keras.layers.Bidirectional(
        keras.layers.LSTM(128, return_sequences=True, dropout=0.25)
    )(x)
    x = keras.layers.Bidirectional(
        keras.layers.LSTM(64, return_sequences=True, dropout=0.25)
    )(x)

    # +2是为了兼容CTC损失引入的两个特殊标记
    x = keras.layers.Dense(
        len(char_to_num.get_vocabulary()) + 2, activation="softmax", name="dense2"
    )(x)

    # 添加CTC层计算每一步的损失
    output = CTCLayer(name="ctc_loss")(labels, x)

    # 定义模型
    model = keras.models.Model(
        inputs=[input_img, labels], outputs=output, name="handwriting_recognizer"
    )
    # 优化器
    opt = keras.optimizers.Adam()
    # 编译模型并返回
    model.compile(optimizer=opt)
    return model


# 获取模型
model = build_model()
model.summary()

解决方案

报错核心原因是Keras 3中获取输入层的方式发生了变化,原代码中model.get_layer(name="image").input无法正确返回输入张量,导致传入keras.models.Model的inputs为空。

修改prediction_model的创建代码,直接从原模型的输入列表中取出图像输入:

# 替换原prediction_model创建代码
prediction_model = keras.models.Model(
    model.input[0], model.get_layer(name="dense2").output
)

或者更清晰的写法:

prediction_model = keras.models.Model(
    inputs=model.inputs[0], outputs=model.get_layer("dense2").output
)

Keras 3中,Model.get_layer().input返回的是该层的输入张量,但由于CTC层的特殊结构,原模型的输入层可能未被正确追踪,直接取model.inputs列表的第一个元素(对应图像输入)是更可靠的方式。


内容的提问来源于stack exchange,提问作者Adwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:07:12