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

CNN披萨牛排分类模型训练精度高但预测表现异常求助

披萨牛排分类模型训练与预测准确率不符问题

问题概述

基于披萨牛排数据集训练的CNN模型,训练集准确率达88.7%,验证集准确率85%,但用自定义的load_and_prep_image函数测试6张披萨/牛排图片时,仅3张分类正确,准确率约50%,调整超参数、网络层数、预处理方式均无改善。


相关代码

训练代码

# Load images and split them into batches
images_train = Images(
    images_dir_train,
    image_size = (224, 224),
    batch_size = 32
)
 
images_test = Images(
    images_dir_test,
    image_size = (224, 224),
    batch_size = 32
)
 
model_augmented = tf.keras.Sequential()
model_augmented.add(tf.keras.Input(shape = (224, 224, 3)))
model_augmented.add(layers.Rescaling(1.0/255))
# model_augmented.add(layers.RandomFlip("horizontal_and_vertical"))
# model_augmented.add(layers.RandomRotation(0.1))
model_augmented.add(layers.Conv2D(filters = 10, kernel_size = 3, activation = 'relu'))
model_augmented.add(layers.Conv2D(filters = 10, kernel_size = 3, activation = 'relu'))
model_augmented.add(layers.MaxPool2D(pool_size = 2, padding = 'valid'))
model_augmented.add(layers.Conv2D(filters = 10, kernel_size = 3, activation = 'relu'))
model_augmented.add(layers.Conv2D(filters = 10, kernel_size = 3, activation = 'relu'))
model_augmented.add(layers.MaxPool2D(pool_size = 2))
model_augmented.add(layers.Flatten())
model_augmented.add(layers.Dense(1, activation = 'sigmoid'))
 
model_augmented.compile(
    loss = 'binary_crossentropy', 
    optimizer = 'adam', 
    metrics = ['accuracy']
)
 
history_augmented = model_augmented.fit(
    images_train, 
    validation_data = images_test, 
    epochs = 7
)
 
model_augmented.summary()

图片加载预处理函数

def load_and_prep_image(filename, img_shape=224):
    '''
    Reads an image from filename, turns it into tensor and reshapes it to (img_shape, img_shape, color_channels)
    '''
    # Read the image
    img = tf.keras.utils.load_img(filename, target_size=(img_shape, img_shape))
    # Convert image to tensor
    img_array = tf.keras.utils.img_to_array(img)
    # Create a batch
    img_array = tf.expand_dims(img_array, 0)
    return img_array

预测代码

pizza = load_and_prep_image("DataSets/prediction_data/pizza-vegetarienne.jpg")
steak = load_and_prep_image("DataSets/prediction_data/steak.jpg")
margherita = load_and_prep_image("DataSets/prediction_data/margherita.jpg")
other_steak = load_and_prep_image("DataSets/prediction_data/other_steak.jpg")
steakA = load_and_prep_image("DataSets/prediction_data/steakA.jpg")
steakB = load_and_prep_image("DataSets/prediction_data/steakB.jpg")
pred_pizza = model.predict(pizza)
pred_margherita = model.predict(margherita)
pred_steak = model.predict(steak)
pred_other_steak = model.predict(other_steak)
pred_steakA = model.predict(steakA)
pred_steakB = model.predict(steakB)
pred_pizza = images_train.class_names[int(tf.round(pred_pizza))]
print('PIZZA ', pred_pizza)
pred_margherita = images_train.class_names[int(tf.round(pred_margherita))]
print('PIZZA ', pred_margherita)
pred_steak = images_train.class_names[int(tf.round(pred_steak))]
print('STEAK ', pred_steak)
pred_other_steak = images_train.class_names[int(tf.round(pred_other_steak))]
print('STEAK ', pred_other_steak)
pred_steakA = images_train.class_names[int(tf.round(pred_steakA))]
print('STEAK ', pred_steakA)
pred_steakB = images_train.class_names[int(tf.round(pred_steakB))]
print('STEAK ', pred_steakB)

预测输出

1/1 [==============================] - 0s 50ms/step
1/1 [==============================] - 0s 46ms/step
1/1 [==============================] - 0s 48ms/step
1/1 [==============================] - 0s 44ms/step
1/1 [==============================] - 0s 41ms/step
1/1 [==============================] - 0s 43ms/step
PIZZA  steak
PIZZA  pizza
STEAK  pizza
STEAK  steak
STEAK  steak
STEAK  pizza

问题根源

核心问题是训练与预测阶段的图片预处理不匹配:

  • 训练时,模型内部通过Rescaling(1.0/255)将输入图片的像素值从0-255缩放至0-1区间
  • 但预测时,load_and_prep_image函数返回的是原始0-255像素值的张量,未做归一化,导致输入数据分布和训练时完全不一致,模型无法正确识别

修复方案

方案1:修改预处理函数,添加归一化

在load_and_prep_image中加入和训练时一致的归一化操作:

def load_and_prep_image(filename, img_shape=224):
    # 读取图片
    img = tf.keras.utils.load_img(filename, target_size=(img_shape, img_shape))
    # 转成张量
    img_array = tf.keras.utils.img_to_array(img)
    # 归一化,和训练时的Rescaling层逻辑一致
    img_array = img_array / 255.0
    # 增加batch维度
    img_array = tf.expand_dims(img_array, 0)
    return img_array

方案2:将归一化移至数据加载阶段(更规范)

把Rescaling层从模型中移除,转而在数据加载时统一处理,确保训练和预测的预处理逻辑完全对齐:

# 训练数据加载时添加归一化
images_train = Images(
    images_dir_train,
    image_size=(224, 224),
    batch_size=32,
    rescale=1.0/255
)

images_test = Images(
    images_dir_test,
    image_size=(224, 224),
    batch_size=32,
    rescale=1.0/255
)

# 模型中移除Rescaling层
model_augmented = tf.keras.Sequential()
model_augmented.add(tf.keras.Input(shape=(224, 224, 3)))
# 去掉这一行:model_augmented.add(layers.Rescaling(1.0/255))
# 后续层保持不变...

额外验证点

  • 打印预测的原始概率值(如print(pred_pizza)),查看模型置信度,确认是否是输入问题导致的预测混乱
  • 核对images_train.class_names的顺序,确保类别索引和实际图片类别对应正确(比如是否是['pizza', 'steak']而非反过来)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:31:00