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

TensorFlow简单分类器输入形状错误求助:维度不匹配

解决VGG16训练时输入维度不匹配的问题

首先,咱们来拆解你遇到的错误:Error when checking input: expected input_1 to have 4 dimensions, but got array with shape (None, None, 224, 224, 3),核心问题出在数据预处理阶段的图像解码+尺寸不匹配,还有模型本身的几个小错误,我一步步给你讲怎么修:

1. 修复图像解码的维度问题

你的_parse_function里同时调用了tf.image.decode_jpeg和tf.image.decode_gif,这会导致冲突:

  • JPEG解码后是3维张量:(height, width, 3)
  • GIF解码后是4维张量:(num_frames, height, width, 3)

当你把GIF解码的结果传入resize后,输出还是带帧数维度的4维张量,再经过batch处理后,就变成了5维(batch_size, num_frames, 299, 299, 3),这完全不符合VGG16期望的4维输入(batch_size, height, width, 3)。

修改方案:
根据你的数据集(辛普森角色图片),应该都是JPEG格式,所以删掉tf.image.decode_gif那行代码,只保留JPEG解码:

def _parse_function(filename, label):
    image_string = tf.read_file(filename)
    # 只保留JPEG解码,删掉GIF解码的行
    image_decoded = tf.image.decode_jpeg(image_string, channels=3)  # 明确指定3通道
    image_resized = tf.image.resize_images(image_decoded, [img_rows, img_cols])
    label = tf.one_hot(label, num_classes)
    return image_resized, label

如果你的数据集里确实有GIF,那需要额外处理(比如取第一帧):

def _parse_function(filename, label):
    image_string = tf.read_file(filename)
    # 尝试先解码JPEG,失败则解码GIF并取第一帧
    try:
        image_decoded = tf.image.decode_jpeg(image_string, channels=3)
    except:
        image_decoded = tf.image.decode_gif(image_string)
        # 取GIF的第一帧,去掉帧数维度
        image_decoded = image_decoded[0]
    image_resized = tf.image.resize_images(image_decoded, [img_rows, img_cols])
    label = tf.one_hot(label, num_classes)
    return image_resized, label

2. 统一输入图像尺寸

你初始化VGG16时指定的输入形状是(224, 224, 3),但预处理里resize的尺寸是img_rows, img_cols = 299, 299,这两个必须一致!

修改方案:
把预处理的尺寸改成224x224,和VGG16要求的一致:

img_rows, img_cols = 224, 224  # 改成和VGG16输入匹配的尺寸

3. 修复模型输出层的类别数错误

你的数据集有5个类别(homer/marge/bart/lisa/maggie),但模型最后一层Dense(2, activation='softmax')只设置了2个输出,这会导致标签和输出不匹配的问题。

修改方案:
把输出层的神经元数量改成5:

predictions = Dense(num_classes, activation='softmax')(x)  # 用num_classes变量更灵活

4. 调整训练步数的计算

你的train_steps和val_steps计算明显有问题,应该用训练集总样本数 / batch_size,而不是固定的372/1和43/1:

batch_size = 10  # 你设置的batch size
train_steps = len(train_filenames_list) // batch_size
val_steps = len(val_filenames_list) // batch_size

最后,完整的修改后代码片段(关键部分)

# 统一输入尺寸
img_rows, img_cols = 224, 224
num_classes = 5

# 修复后的预处理函数
def _parse_function(filename, label):
    image_string = tf.read_file(filename)
    image_decoded = tf.image.decode_jpeg(image_string, channels=3)
    image_resized = tf.image.resize_images(image_decoded, [img_rows, img_cols])
    # 可选:归一化到VGG16要求的像素范围(0-255转成0-1,或者用preprocess_input)
    image_resized = tf.cast(image_resized, tf.float32) / 255.0
    # 或者用官方的预处理函数:
    # image_resized = tf.keras.applications.vgg16.preprocess_input(image_resized)
    label = tf.one_hot(label, num_classes)
    return image_resized, label

# 修复后的模型定义
base_model = tf.keras.applications.vgg16.VGG16(weights='imagenet', include_top=False, input_shape=(img_rows, img_cols, 3))
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)  # 要加完整的层路径,避免未定义错误
x = tf.keras.layers.Dense(512, activation='relu')(x)
x = tf.keras.layers.Dropout(0.3)(x)
predictions = tf.keras.layers.Dense(num_classes, activation='softmax')(x)
model = tf.keras.models.Model(inputs=base_model.input, outputs=predictions)

# 修复后的训练步数
batch_size = 10
train_steps = len(train_filenames_list) // batch_size
val_steps = len(val_filenames_list) // batch_size

history = model.fit(
    train_dataset,
    steps_per_epoch = train_steps,
    epochs = epochs,
    validation_data = valid_dataset,
    validation_steps = val_steps)

另外,还有个小细节:你在代码里重复设置了train_set_percentage = .9,第二次切割训练/验证集的操作其实是多余的,建议删掉,避免样本量意外减少。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:55:09