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
相关产品推荐
相关产品推荐

