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

蔬菜分类神经网络验证准确率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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:01:02