蔬菜分类神经网络验证准确率90%但预测错误问题排查
蔬菜分类神经网络预测错误问题排查
我搭建了一个用于预测不同种类蔬菜的神经网络,模型验证准确率约为90%,但每次预测都会输出错误的蔬菜类别。以下是完整代码及训练信息:
训练代码及过程
import tensorflow as tf import matplotlib.pyplot as plt import numpy as np import cv2 import os from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.preprocessing import image from tensorflow.keras.optimizers import RMSprop from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau from keras.utils import to_categorical from keras.models import Sequential from keras.layers import Dense, Flatten, Conv2D, MaxPool2D, Dropout train = ImageDataGenerator(rescale=1/255) validation = ImageDataGenerator(rescale=1/255) train_data_set = train.flow_from_directory(r"C:\Users\roshn\Desktop\Vegetable Images\train",target_size=(200,200),batch_size =15,class_mode='categorical')
找到15000张图像,分属15个类别。
val_data_set = train.flow_from_directory(r"C:\Users\roshn\Desktop\Vegetable Images\validation",target_size=(200,200),batch_size =15,class_mode='categorical')
找到3000张图像,分属15个类别。
train_data_set.class_indices
{'Bean': 0,
'Bitter_Gourd': 1,
'Bottle_Gourd': 2,
'Brinjal': 3,
'Broccoli': 4,
'Cabbage': 5,
'Capsicum': 6,
'Carrot': 7,
'Cauliflower': 8,
'Cucumber': 9,
'Papaya': 10,
'Potato': 11,
'Pumpkin': 12,
'Radish': 13,
'Tomato': 14}
model = tf.keras.models.Sequential([tf.keras.layers.Conv2D(16,(3,3),activation ='relu',input_shape =(200,200,3)), tf.keras.layers.MaxPool2D(2,2), ## tf.keras.layers.Conv2D(32,(3,3),activation ='relu'), tf.keras.layers.MaxPool2D(2,2), ## tf.keras.layers.Flatten(), ## tf.keras.layers.Dense(1000,activation ='relu'), ## tf.keras.layers.Dropout(0.5), ## tf.keras.layers.Dense(500,activation='relu'), ## tf.keras.layers.Dropout(0.5), ## tf.keras.layers.Dense(250,activation='relu'), ## tf.keras.layers.Dense(15,activation='softmax')]) model.compile(loss='categorical_crossentropy',optimizer ='adam',metrics=['accuracy']) es = EarlyStopping(monitor='val_accuracy',patience=2,verbose=1,mode='max') mc = ModelCheckpoint('checkpoint/',monitor='val_accuracy',mode='max',save_best_only=True,verbose=1) lr = ReduceLROnPlateau(monitor='val_accuracy',factor=0.1,min_lr=0.001,patience=15,mode='max',verbose=1) model_fit=model.fit(train_data_set, epochs=10, batch_size=64, validation_data=val_data_set, callbacks=[es,mc,lr],validation_split =0.2)
模型结构
model.summary()
Model: "sequential_23" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_63 (Conv2D) (None, 198, 198, 16) 448 max_pooling2d_63 (MaxPoolin (None, 99, 99, 16) 0 g2D) conv2d_64 (Conv2D) (None, 97, 97, 32) 4640 max_pooling2d_64 (MaxPoolin (None, 48, 48, 32) 0 g2D) flatten_22 (Flatten) (None, 73728) 0 dense_54 (Dense) (None, 1000) 73729000 dropout_8 (Dropout) (None, 1000) 0 dense_55 (Dense) (None, 500) 500500 dropout_9 (Dropout) (None, 500) 0 dense_56 (Dense) (None, 250) 125250 dense_57 (Dense) (None, 15) 3765 ================================================================= Total params: 74,363,603 Trainable params: 74,363,603 Non-trainable params: 0 ___________________________________________________
预测代码
dir_path =r"C:\Users\roshn\Desktop\Vegetable Images\train\Bitter_Gourd\0001.jpg" img =image.load_img(dir_path,target_size =(200,200,3)) plt.imshow(img) plt.show() x= image.img_to_array(img) x=np.expand_dims(x,axis =0) images =np.vstack([x]) vl = model.predict(images) t = train_data_set.class_indices classes = list(t.keys()) values = t.values() list_index=list(values) x=vl for i in range(15): for j in range(15): if x[0][list_index[i]] > x[0][list_index[j]]: temp=list_index[i] list_index[i]=list_index[j] list_index[j]=temp print(list_index) for i in range (5): print(classes[list_index[i]],':',round(vl[0][list_index[i]])*100,"%")
问题原因及修正方案
1. 预测图像未做归一化
训练时使用rescale=1/255将图像像素值缩放到0-1区间,但预测时直接输入0-255范围的像素值,数据分布和训练集不一致,导致模型无法正确预测。
修正:添加归一化步骤:
x= image.img_to_array(img) x = x / 255.0 # 新增归一化 x=np.expand_dims(x,axis =0)
2. 排序逻辑错误
当前排序代码将类别索引按预测概率升序排列,输出的前5个都是概率最低的类别,自然和实际不符,需要改为降序排列。
修正:修改排序条件:
for i in range(15): for j in range(15): if x[0][list_index[i]] < x[0][list_index[j]]: # 改为小于号实现降序 temp=list_index[i] list_index[i]=list_index[j] list_index[j]=temp
3. 其他优化建议(不影响核心预测,但提升代码规范性)
- 验证集生成器应使用
validation而非train:val_data_set = validation.flow_from_directory(...) model.fit中validation_data和validation_split冲突,删除validation_split =0.2即可。
修正后的完整预测代码
dir_path =r"C:\Users\roshn\Desktop\Vegetable Images\train\Bitter_Gourd\0001.jpg" img =image.load_img(dir_path,target_size =(200,200,3)) plt.imshow(img) plt.show() x= image.img_to_array(img) x = x / 255.0 # 归一化 x=np.expand_dims(x,axis =0) vl = model.predict(x) # 单张图无需vstack,直接输入 t = train_data_set.class_indices classes = list(t.keys()) # 按概率降序排序类别 class_probs = [(cls, vl[0][idx]) for idx, cls in enumerate(classes)] class_probs.sort(key=lambda x: x[1], reverse=True) # 输出前5个预测结果 for cls, prob in class_probs[:5]: print(f"{cls}: {round(prob * 100, 2)}%")
内容的提问来源于stack exchange,提问作者ROSHANI KUAMARI
相关产品推荐
相关产品推荐

