如何使用经过训练的模型预测 MNIST 数据(输入形状的预期轴 -1 的值为 784,但收到的输入形状为 (784, 1))

How to predict MNIST data with trained model (expected axis -1 of input shape to have value 784, but received input with shape (784, 1))

我已经学习了 tensorflow2 教程,但现在想使用该模型来预测图像。

我的代码:

import tensorflow
import tensorflow_datasets
import matplotlib.pyplot as plot
import numpy

def normalize_img(img, label):
  return tensorflow.cast(img, tensorflow.float32) / 255., label

(mnist_train, mnist_raw), mnist_info = tensorflow_datasets.load(
    'mnist',
    split=['train', 'test'],
    shuffle_files=True,
    as_supervised=True,
    with_info=True,
)

mnist_train = mnist_train.map(normalize_img, num_parallel_calls=tensorflow.data.AUTOTUNE)
mnist_train = mnist_train.cache()
mnist_train = mnist_train.shuffle(mnist_info.splits['train'].num_examples)
mnist_train = mnist_train.batch(128)
mnist_train = mnist_train.prefetch(tensorflow.data.AUTOTUNE)

mnist_test = mnist_raw.map(normalize_img, num_parallel_calls=tensorflow.data.AUTOTUNE)
mnist_test = mnist_test.batch(128)
mnist_test = mnist_test.cache()
mnist_test = mnist_test.prefetch(tensorflow.data.AUTOTUNE)

model = tensorflow.keras.models.Sequential([
  tensorflow.keras.layers.Flatten(input_shape=(28, 28)),
  tensorflow.keras.layers.Dense(128, activation='relu'),
  tensorflow.keras.layers.Dropout(0.16),
  tensorflow.keras.layers.Dense(10, activation="softmax")
])



model.compile(
    optimizer=tensorflow.keras.optimizers.Adam(0.001), 
    loss=tensorflow.keras.losses.SparseCategoricalCrossentropy(from_logits=True), 
    metrics=["accuracy"]
)

result = model.fit(mnist_train, epochs=6, validation_data=mnist_test)

it = mnist_test.as_numpy_iterator()
first = it.next()
images, labels = first[0], first[1]

plot.imshow(images[0].squeeze())
model(images[0].squeeze().flatten())

最后一行报错:

ValueError                                Traceback (most recent call last)
ipython-input-87-57d521ba8778> in <module>()
----> 1 model(images[0].squeeze().flatten())
1 frames
/usr/local/lib/python3.7/dist-packages/keras/engine/input_spec.py in assert_input_compatibility(input_spec, inputs, layer_name)
    247         if value is not None and shape_as_list[int(axis)] not in {value, None}:
    248           raise ValueError(
--> 249               f'Input {input_index} of layer "{layer_name}" is '
    250               f'incompatible with the layer: expected axis {axis} '
    251               f'of input shape to have value {value}, '
ValueError: Exception encountered when calling layer "sequential_1" (type Sequential).
Input 0 of layer "dense_2" is incompatible with the layer: expected axis -1 of input shape to have value 784, but received input with shape (784, 1)
Call arguments received:
  • inputs=tf.Tensor(shape=(784,), dtype=float32)
  • training=False
  • mask=None

据我所知,模型 operator() 需要一个一维数组,但我为它提供了一个二维数组,其中第二维为 1(本质上是一个 1 维数组)。

我发现了这个问题:

但如果我执行 reshape(1, 784),则错误消息会切换到期望维度 (28,28)。如果我不展平数组,我会收到错误消息,指出 (28, 28) 已提供,但它需要 (784).

检查 images[0].squeeze().flatten() 的形状:

import numpy as np

print(np.shape(images[0].squeeze().flatten()))
(784,)

但是您的输入是 (None, 28, 28)。因此,您不需要展平(由输入处的 Flatten 处理)。此外,您还需要批量维度。所以你可以这样做:

model(np.expand_dims(images[0, :], axis=0))

请注意,如果您想一次输入更多图像,它可以正常工作:

model(images[0:10, :])

因为批次维度在那里。