TensorFlow Keras报错:Shapes (None,6,36)与(None,216)不兼容求解
解决文本图像识别模型的形状不兼容错误
错误原因
你遇到的ValueError: Shapes (None, 6, 36) and (None, 216) are incompatible,核心是模型输出形状与标签形状不匹配:
- 标签数组是三维结构:
(样本数, 6, 36)对应6个字符,每个字符36种可能 - 模型最后一层输出是一维结构:
(None, 216)即6*36的扁平化结果
而categorical_crossentropy损失函数要求标签和模型输出的形状必须完全一致。
解决方案(二选一即可)
方案一:调整模型输出为三维结构(推荐)
通过添加Reshape层,把模型最后一层的一维输出转换成和标签一致的(6, 36)结构,同时修正最后一层的激活函数(分类任务需用softmax):
修改模型定义代码:
model = Sequential([ Conv2D(32, (3, 3), activation="relu", input_shape=(40, 180, 3)), MaxPooling2D(pool_size=(2, 2)), Conv2D(64, (3, 3), activation="relu"), MaxPooling2D(pool_size=(2, 2)), Flatten(), Dense(128, activation="relu"), # 输出6*36的特征,用softmax做分类激活 Dense(num_characters * len(characters), activation="softmax"), # 将一维结果重塑为(6,36),匹配标签形状 tf.keras.layers.Reshape((num_characters, len(characters))) ])
方案二:调整标签为一维结构
把三维的标签数组扁平化,转换成和模型输出一致的一维结构:
修改convert_to_arrays函数:
def convert_to_arrays(images, labels): images_array = np.array(images) / 255.0 num_samples = len(images) # 初始化一维标签数组 labels_array = np.zeros((num_samples, num_characters * len(characters))) for i, label in enumerate(labels): # 跳过长度不符的标签,避免索引错误 if len(label) != num_characters: continue for j, char in enumerate(label): # 计算一维索引位置 idx = j * len(characters) + characters.index(char) labels_array[i, idx] = 1 return images_array, labels_array
额外需要修正的小问题
- 图片解码错误:你用
tf.io.decode_png读取.jpg格式的图片,应该替换成tf.io.decode_jpeg,否则可能出现解码失败:
image = tf.io.decode_jpeg(tf.io.read_file(image_path), channels=num_channels)
- 固定样本数的潜在问题:原代码中
num_train_images固定为85,但实际文件夹中的图片数量可能不等于85,会导致标签数组初始化长度不匹配。修改所有依赖num_train_images的地方,改用实际加载的样本数:- 在
convert_to_arrays和split_arrays函数中,用len(images)或len(images_array)替代num_train_images(参考方案二中的修改)。
- 在
内容的提问来源于stack exchange,提问作者Juan Pablo Cuéllar Alvarado
相关产品推荐
相关产品推荐

