Tensorflow:Model 是用形状 (None, 28, 28) 构建的,但它在形状不兼容的输入上被调用 (None, 28)

时间:2021-06-04 14:35:26

标签: python tensorflow image-recognition

我正在使用 keras 中的 MNIST 数据集解决数字识别任务。 任务本身运行顺利,但后来我尝试使用相同的模型 对于我用“paint”创建的其他一些手写数字。 由于原始大小是 (192, 188, 3),所以我特意将大小调整为 (28, 28)。 但是,一旦我在这个新创建的数字上尝试模型(见附件),这是我收到的警告消息:

警告:tensorflow:模型是用形状 (None, 28, 28) 构建的,用于输入 KerasTensor(type_spec=TensorSpec(shape=(None, 28, 28), dtype=tf.float32, name='flatten_input'), name='flatten_input', description="created by layer 'flatten_input'"),但它在形状不兼容的输入上被调用(无,28)

除此错误消息外:

ValueError:输入 0 层密集与层不兼容:输入形状的预期轴 -1 具有值 784,但接收到形状为 (None, 28) 的输入

这是我的代码:

import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
# %matplotlib inline
import numpy as np
import pandas as pd
import cv2 as cv

(X_train, y_train),(X_test, y_test)=keras.datasets.mnist.load_data()
# Normalize the train dataset
X_train = tf.keras.utils.normalize(X_train, axis=1)
# Normalize the test dataset
X_test = tf.keras.utils.normalize(X_test, axis=1)

#Build the model object
model = tf.keras.models.Sequential()
# Add the Flatten Layer
model.add(tf.keras.layers.Flatten())
# Build the input and the hidden layers
model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))
# Build the output layer
model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax))

# Compile the model
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", 
metrics=["accuracy"]) 
model.fit(x=X_train, y=y_train, epochs=20) # Start training process

# Evaluate the model performance
test_loss, test_acc = model.evaluate(x=X_test, y=y_test)
# Print out the model accuracy 
print('\nTest accuracy:', test_acc)

predictions = model.predict([X_test]) # Make prediction

# TRY SAME MODEL WITH NEW DIGIT 

img_6 =  cv.imread("6.png")
img_7 =  cv.imread("7.png")
img_2 =  cv.imread("2.png")


from tensorflow.keras.preprocessing import image

img =  img_7 

img=cv.resize(img, X_train[0].shape, 
            interpolation = cv.INTER_AREA) 
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) 

plt.imshow(img)
plt.show()
img=np.invert(np.array([img]))
img=np.reshape(img, ( 784, 1))
print(img.shape,'fghjkljkhjgfgfgcgvhbjnmnbjv')
plt.imshow(img)
plt.show()

img=np.expand_dims(img, axis=0) # will move it to (1,784)
print(img.shape,'fghjkljkhjgfgfgcgvhbjnmnbjv')
plt.imshow(img)
plt.show()
prediction=model.predict(img) # predict
print ('prediction=',np.argmax(prediction))
plt.imshow(img)
plt.show()

6 7 2

2 个答案:

答案 0 :(得分:0)

您的代码的问题在于您的模型需要一个 3 维输入 (batch_size, width, height),而您给它的是一个二维图像 (width, height)

您可以先将输入图像重塑为正确的形状,如下所示:

np.reshape(img_6, (1, 28, 28))

答案 1 :(得分:0)

模型的第一层是 tf.keras.layers.Flatten(),即展平。意味着它就像一个数组。数组长度是 784(28X28X1 ~ 长 x 宽 x 通道)是多少。所以如果你把 model.summary() 放在第一层是:

Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0   

所以这意味着 predict 期望输入数据为 (1,784)。您可以调整输入图像的大小并使其变灰,但还需要更多步骤。请参考以下代码并对每一行进行注释:

from tensorflow.keras.preprocessing import image # import image preprocessing
img_6 =  cv.imread("6.png") # shape if (352, 324, 3) for screen snap, this could be different based on read image.
img_6=cv.resize(img_6, X_train[0].shape, 
                interpolation = cv.INTER_AREA) # now its in shape (28, 28, 3) which is~ 2352(28x28x3)
img_6 = cv.cvtColor(img_6, cv.COLOR_BGR2GRAY) # now gray image
img_6=image.img_to_array(img_6) # shape (28, 28, 1) i.e channel 1
img_6= img_6.flatten() # flatten it as model is expecting (None,784) , this will be (784,) i.e 28x28x1 =
img_6=np.expand_dims(img_6, axis=0) # will move it to (1,784)
prediction=model.predict(im1) # predict
print (np.argmax(prediction))