Python 格式化图像数据以预测MNIST数据模型图像中的数字

Python 格式化图像数据以预测MNIST数据模型图像中的数字,python,numpy,machine-learning,neural-network,keras,Python,Numpy,Machine Learning,Neural Network,Keras,我和MNIST在试Keras时遇到了问题。我有一个保存的模型,精度超过99%,但当我用它来预测一些图像时,它总是预测1。我想这是因为我在test.py文件中以错误的方式重新塑造了输入的图像数据 我得到了一个错误: ValueError: Error when checking : expected conv2d_1_input to have 4 dimensions, but got array with shape (28, 28) 或者,如果我尝试随机重塑(1,1,28,28),我会得到

我和MNIST在试Keras时遇到了问题。我有一个保存的模型,精度超过99%,但当我用它来预测一些图像时,它总是预测1。我想这是因为我在test.py文件中以错误的方式重新塑造了输入的图像数据

我得到了一个错误:

ValueError: Error when checking : expected conv2d_1_input to have 4 dimensions, but got array with shape (28, 28)
或者,如果我尝试随机重塑(1,1,28,28),我会得到以下错误:

ValueError: Error when checking : expected conv2d_1_input to have shape (None, 28, 28, 1) but got array with shape (1, 1, 28, 28)
因此,我尝试在我的image_to_data函数中添加以下内容:

image_data = image_data.reshape((1, 28, 28, 1))
现在代码运行,但总是预测相同的值。我如何重塑图像数据28 x 28像素,使其适合模型中的第一层,以正确的方式预测一幅图像的类别

train.py

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 import backend as K

batch_size = 128
num_classes = 10
epochs = 20

# input image dimensions
img_rows, img_cols = 28, 28

# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = 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'])

model.fit(x_train, y_train,
      batch_size=batch_size,
      epochs=epochs,
      verbose=1,
      validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

# serialize model to YAML
model_yaml = model.to_yaml()
with open("model-new.yaml", "w") as yaml_file:
yaml_file.write(model_yaml)
# serialize weights to HDF5
model.save_weights("model-new.h5")
print("Saved model to disk")
test.py

from PIL import Image
from keras.models import model_from_yaml
import numpy as np

def load_model():
    # load YAML and create model
    yaml_file = open('model.yaml', 'r')
    model_yaml = yaml_file.read()
    yaml_file.close()
    model = model_from_yaml(model_yaml)
    # load weights into new model
    model.load_weights("model.h5")
    print("Loaded model from disk")
    model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
    return model

def image_to_data(image):
    image_data = np.array(image) / 255
    image_data = image_data.reshape((1, 28, 28, 1))
    return image_data

def predict(model, image):
    data = image_to_data(image)
    prediction = model.predict_classes(data)
    return prediction

def predict_image(model, filename):
    image = Image.open(filename)
    data = image_to_data(image)
    prediction = predict(model, data)
    return prediction

model = load_model()
print(predict_image(model, '3.png'))
print(predict_image(model, '6.png'))
print(predict_image(model, '8.png'))
可能的问题:

  • (不是您的情况)MNIST数据在0和1之间标准化,您的图像可能像往常一样在0到255之间(比较
    image\u data.max()
    x\u train.max()
  • MNIST数据可能具有与图像相反的黑白颜色。确保所有内容均在0和1之间标准化后,使用工具从
    x\u列
    绘制图像,并绘制
    image\u数据
    。看看颜色是否颠倒。或者尝试使用
    image\u data=1-image\u data
    进行预失真
  • 根据您加载图像的方式,您可能会对其进行转置。检查前两项后,您可以尝试
    image\u data=numpy.swapaxes(image\u data,1,2)
  • 如@hi_im_vinzent所述,过度装修。如果前面的三项都正常,请尝试使用训练图像进行预测,以查看模型是否正确
  • 如果前面的方法都不起作用,那么在保存/加载模型时可能会出现问题

首先,在训练模型时,我会尽量减少历次次数,模型可能已经过拟合(99%的准确率)。为了评估这一点,您可以很容易地使用keras实现交叉验证测试。这使您能够更真实地了解准确度,因为您可以在整个培训过程中流利地比较测试准确度(使用培训图片进行测试)和交叉验证准确度(使用模型从未见过的图片进行测试)。我从mnist数据(x_train,y_train)中有一个单独的测试集,(x_test,y_test)=mnist.load_data(),但也许我应该再次检查,以便模块在训练集中也没有该数据,我假设不会,因为在两个位置都有该数据是没有意义的。您也可以执行类似于np.expand_dims(image,axis=0)/255的操作。这将我的(256,256,3)图像转换为(1,256,256,3)。谢谢!那些好的点和@hl_im_vinzent的点一样。我会尝试检查彩色反转/旋转图像。只是我还认为图像数据。重塑((1,28,28,1))命令可能真的出了问题,我不确定这种神奇的重塑是如何发生的。我是numpy的新手,了解如何使用它。如何安全地将2d图像阵列重塑为(1,28,28,1)(我现在甚至无法在脑海中形象化新形状在多个维度上的外观)?正如你所说,我需要反转图像,现在已经完成了。我还从MNIST测试集中提取了两个图像进行尝试。无论图像如何,这两个都不会给出除1以外的任何其他值作为预测。如果拟合过度,至少MNIST图像应该给出正确的预测。我将进一步研究。Numpy数组是按维度分组的元素的直接序列。重塑时,只需更改分组,而无需任何形式的重新排序。这与转置、交换、滚动轴等不同,在转置、交换、滚动轴等中,数据实际上是重新排序以反映更改。任何形式的重塑(任意数量的1、28、任意数量的1、28、任意数量的1)不会对数据进行任何实际更改。(当然,keras只接受表格中的数据(批次,28,28,通道)。