CNN模型所有预测结果均相同的问题排查求助
问题分析与解决方案
嘿,我看你遇到了一个挺让人困惑的问题——不管输入什么图像,CNN模型的预测结果都完全一致,虽然训练时显示准确率超过99%。咱们来一步步拆解代码里的问题,找到根源:
核心问题:预测时的图像预处理和训练完全不一致
这是导致预测结果固定的最关键原因,模型训练时是用归一化后的像素值,但预测时完全没做对应的预处理:
1. 缺少归一化操作
训练时你对输入做了X_train/=255和X_test/=255,把像素值缩放到了0-1之间,但预测时的newimg还是原始的0-255像素值,模型拿到完全不在训练分布里的数据,自然会输出异常的固定结果。
2. 图像处理逻辑错误
你在轮廓提取环节已经对图像做了灰度化、二值化、膨胀等处理,但最后却回到原始彩色图像image去裁剪和resize,这完全偏离了训练数据的分布(MNIST是手写数字的灰度二值图)。应该用处理后的二值化图像来进行后续的裁剪和resize操作。
3. 代码里的小bug
- 变量名错误:
img.shape这里应该是newimg.shape,否则会报错(img还没定义) - 窗口显示问题:
cv2.imshow("screen",img)这里的img是四维张量,cv2无法直接显示,应该用newimg或者squeeze后的二维数组
修正后的预测代码片段
import cv2 import numpy as np # 读取图像并预处理 image = cv2.imread("pitrain.png") gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # 转灰度 ret, thresh = cv2.threshold(gray,150,255,cv2.THRESH_BINARY_INV) # 二值化(和MNIST的黑底白字对齐) kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3)) dilated = cv2.dilate(thresh,kernel,iterations = 13) # 膨胀 # 提取轮廓并处理 im2, contours, hierarchy = cv2.findContours(dilated,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) for contour in contours: x,y,w,h = cv2.boundingRect(contour) # 过滤不合理的轮廓尺寸 if h>300 and w>300: continue if h<40 or w<40: continue # 从二值化图像中裁剪数字区域 digit_roi = thresh[y:y+h, x:x+w] # 调整尺寸到MNIST的28x28 newimg = cv2.resize(digit_roi,(28,28)) # 归一化(和训练时一致) newimg = newimg.astype('float32') / 255.0 # 调整维度为模型需要的[1,28,28,1] img = np.reshape(newimg,[1,28,28,1]) # 预测 pred = classifier.predict(img) print("预测结果:", np.argmax(pred)) # 显示裁剪后的数字 cv2.imshow("digit", newimg) cv2.waitKey(0) cv2.destroyAllWindows()
额外的训练代码优化点
你训练时的fit_generator参数有问题:
steps_per_epoch应该设置为len(X_train)//batch_size也就是60000//64=937,而不是60000,否则一个epoch会重复遍历训练数据几十次,导致训练效率极低,准确率的计算也会失真。- 同样
validation_steps应该是10000//64=157而不是10000。
修正后的训练代码:
classifier.fit_generator( train_generator, steps_per_epoch=60000//64, epochs=5, # 可以多训练几个epoch,效果会更好 validation_data=test_generator, validation_steps=10000//64 )
内容的提问来源于stack exchange,提问作者haik
相关产品推荐
相关产品推荐

