在 cnn 中为所有预测获得相同的结果

数据挖掘 Python 图像分类 美国有线电视新闻网
2022-02-18 06:58:48

这是我第一次在 cnn 中训练模型并预测结果,但是对于我输入的图像,我得到了相同的值。这是我的代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.optimizers import Adam
from keras.layers.normalization import BatchNormalization
from keras.utils import np_utils
from keras.layers import Conv2D, MaxPooling2D, ZeroPadding2D, 
GlobalAveragePooling2D
from keras.layers.advanced_activations import LeakyReLU 
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
classifier=Sequential()
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train/=255
X_test/=255
number_of_classes = 10
Y_train = np_utils.to_categorical(y_train, number_of_classes)
Y_test = np_utils.to_categorical(y_test, number_of_classes)
classifier.add(Convolution2D(32,3,3,input_shape= 
(28,28,1),activation='relu'))
classifier.add(BatchNormalization(axis=-1))
classifier.add(MaxPooling2D(pool_size=(2,2)))

classifier.add(Convolution2D(32,3,3,activation='relu'))
classifier.add(BatchNormalization(axis=-1))
classifier.add(MaxPooling2D(pool_size=(2,2)))

classifier.add(Flatten())

classifier.add(Dense(output_dim=256,activation='relu'))
classifier.add(BatchNormalization())
classifier.add(Dense(output_dim=10,activation='softmax'))

classifier.compile(optimizer='adam',loss='categorical_crossentropy',metrics=            
['accuracy'])
gen = ImageDataGenerator(rotation_range=8, width_shift_range=0.08,         
shear_range=0.3, height_shift_range=0.08, zoom_range=0.08)

test_gen = ImageDataGenerator()
train_generator = gen.flow(X_train, Y_train, batch_size=64)
test_generator = test_gen.flow(X_test, Y_test, batch_size=64)
classifier.fit_generator(train_generator, steps_per_epoch=60000, epochs=1, 
                validation_data=test_generator, validation_steps=10000)
import cv2
image = cv2.imread("pitrain.png")
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # grayscale
ret,thresh = cv2.threshold(gray,150,255,cv2.THRESH_BINARY_INV) 
#threshold
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
dilated = cv2.dilate(thresh,kernel,iterations = 13) # dilate
im2,contours, hierarchy =             
cv2.findContours(dilated,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) 
# get contours
# for each contour found, draw a rectangle around it on original image
for contour in contours:

# get rectangle bounding contour

[x,y,w,h] = cv2.boundingRect(contour)
# discard areas that are too large

if h>300 and w>300:

    continue
# discard areas that are too small

if h<40 or w<40:

    continue
# draw rectangle around contour on original image

cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,255),2)
image.shape
image=image[:,:,:1]
newimg = cv2.resize(image,(28,28))
img.shape
img = np.reshape(newimg,[1,28,28,1])
cv2.imshow("screen",img)
classifier.predict(img)

我得到的输出是零数组,第三个位置是 1。这是我从https://www.quora.com/How-do-I-extract-a-particular-object-from-images-using-OpenCV复制轮廓部分的地方

Epoch 等于 1,因为我只想测试我的模型,但我的准确率仍然在 99% 以上

1个回答

好的,所以我更改了您的模型以简化培训,例如。我将在下面详细介绍示例。当您将来自不同分布的值提供给您的模型时,您总是面临错误分类的风险。例如,您的模型是使用手写数字训练的,因此模型错误分类打字数字也就不足为奇了。当然,更深更复杂的模型可以做到这一点。


获取数据

MNIST 数据的大小为 28 x 28。我们将这些值转换为浮点值,然后将它们标准化为 0 到 1 的范围。我们还将确定我们有 10 个输出类。

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.callbacks import ModelCheckpoint
from keras.models import model_from_json
from keras import backend as K
from keras.datasets import mnist
import numpy as np

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

# The known number of output classes.
num_classes = 10
# Input image dimensions
img_rows, img_cols = 28, 28

接下来,我们需要重塑数据,使其与我们将在 Keras 引擎下使用的 Tensorflow 框架相匹配。这要求实例是第一个维度,并且还需要通道维度作为最后一个维度。因此对于我们需要的 MNIST 数据(6000,28,28,1).

# Channels go last for TensorFlow backend
x_train_reshaped = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test_reshaped = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)

然后我们将输出合并为 one-hot-encoded 向量

# Convert class vectors to binary class matrices. This uses 1 hot encoding.
y_train_binary = keras.utils.to_categorical(y_train, num_classes)
y_test_binary = keras.utils.to_categorical(y_test, num_classes)

让我们构建我们的简单模型,您可以添加更多层以使其更健壮

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

让我们训练我们的模型

epochs = 4
batch_size = 128
# Fit the model weights.
model.fit(x_train_reshaped, y_train_binary,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test_reshaped, y_test_binary))

这应该在验证集上产生大约 98.75%。这非常好,应该足以使用该集合测试一些新数据。


使用 MNIST 验证结果

让我们从 MNIST 数据集中传递一些随机值,看看它们是否被我们的模型正确分类。请注意我如何设置数据的维度。即使我们只有一个要预测的实例以及通道维度,实例维度也必须存在

ix = 0

plt.imshow(X_test[ix,:,:,0], 'gray')
plt.show()

temp = np.zeros((1,28,28,1))
temp[0,:,:,0] = X_test[ix,:,:,0]

model.predict_classes(temp)

在此处输入图像描述

数组([7],dtype=int64)

好的,这样就成功了!让我们尝试另一个ix = 100

在此处输入图像描述

数组([6],dtype=int64)

那也有效!


在新数据上验证模型

您起诉的图像必须在风格上与 MNIST 数据集中的图像匹配。理想情况下,它们应该具有相同的分布。幸运的是,您提供的图像得到了正确分类,但应注意,其他打字数字可能并非如此。如果你想让你的算法检测到这些,那么你真的应该用打字的数字和手写的数字来训练。

from skimage.transform import resize

def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])

im = plt.imread("7 type.jpg")
im = rgb2gray(im)
im = resize(im, (28, 28))

plt.imshow(im[:,:], 'gray')
plt.show()

temp = np.zeros((1,28,28,1))
temp[0,:,:,0] = im

model.predict_classes(temp)

在此处输入图像描述

数组([7],dtype=int64)

验证手绘数字

更现实的是使用手绘数字,因为这是我们过去训练的。我只是用Paint画了这个。

在此处输入图像描述

数组([8],dtype=int64)

在此处输入图像描述

数组(2,dtype=int64)