检查输入时发生错误:期望flatten_input具有3个维度,但得到的数组形状为(None, 100, 100, 1)

我想使用TensorFlow/Keras将图片分类为自拍和非自拍两类。

我已经将样本收集到了两个文件系统文件夹中,每个类别一个文件夹。

我按照MNIST时尚(这也是一个图片分类问题)的官方教程实现了下面的训练,并使用从文件系统加载图片的方法,如https://stackoverflow.com/a/52417770/226958所示。

不幸的是,我遇到了一个错误:

1.10.1Tensor("IteratorGetNext:0", shape=(?, 100, 100, 1), dtype=float32)Tensor("IteratorGetNext:1", shape=(?,), dtype=int32)Traceback (most recent call last):  File "run.py", line 50, in <module>    model.fit(images, labels, epochs=1, steps_per_epoch=60000)  File "/home/nico/.local/lib/python2.7/site-packages/tensorflow/python/keras/engine/training.py", line 1278, in fit    validation_split=validation_split)  File "/home/nico/.local/lib/python2.7/site-packages/tensorflow/python/keras/engine/training.py", line 878, in _standardize_user_data    exception_prefix='input')  File "/home/nico/.local/lib/python2.7/site-packages/tensorflow/python/keras/engine/training_utils.py", line 182, in standardize_input_data    'with shape ' + str(data_shape))ValueError: Error when checking input: expected flatten_input to have 3 dimensions, but got array with shape (None, 100, 100, 1)

这是源代码:

import tensorflow as tfprint(tf.__version__)out_shape = tf.convert_to_tensor([100, 100])batch_size = 2image_paths, labels = ["selfies-data/1", "selfies-data/2"], [1, 2]epoch_size = len(image_paths)image_paths = tf.convert_to_tensor(image_paths, dtype=tf.string)labels = tf.convert_to_tensor(labels)# 图片加载部分来自 https://stackoverflow.com/a/52417770/226958dataset = tf.data.Dataset.from_tensor_slices((image_paths, labels))dataset = dataset.repeat().shuffle(epoch_size)def map_fn(path, label):    # path/label代表单个示例的值    image = tf.image.decode_jpeg(tf.read_file(path))    # 调整到固定大小 - 注意不要扭曲纵横比    image = tf.image.resize_images(image, out_shape)    image = tf.image.rgb_to_grayscale(image)    # 颜色归一化 - 仅为示例    image = tf.to_float(image) * (2. / 255) - 1    return image, label# num_parallel_calls > 1 会导致批次内洗牌dataset = dataset.map(map_fn, num_parallel_calls=8)dataset = dataset.batch(batch_size)dataset = dataset.prefetch(1)images, labels = dataset.make_one_shot_iterator().get_next()# 以下所有内容来自 https://www.tensorflow.org/tutorials/keras/basic_classificationfrom tensorflow import kerasmodel = keras.Sequential([    keras.layers.Flatten(input_shape=(100, 100)),    keras.layers.Dense(128, activation=tf.nn.relu),    keras.layers.Dense(10, activation=tf.nn.softmax)])model.compile(optimizer=tf.train.AdamOptimizer(),              loss='sparse_categorical_crossentropy',              metrics=['accuracy'])print(images)print(labels)model.fit(images, labels, epochs=epoch_size, steps_per_epoch=60000)

虽然我读过一些类似的提问,但我没有看到任何关于None的问题。

我如何调整Keras以适应我的输入,或者如何转换我的输入使Keras能够接受它?


回答:

1) 图片只有一个通道,因此必须在输入形状参数中反映出来:

keras.layers.Flatten(input_shape=(100, 100, 1))

2) 要使用tf.data API加载文件,您需要先获取图像文件名及其相应的标签:

image_paths, lbls = ["selfies-data/1", "selfies-data/2"], [0., 1.]labels = []file_names = []for d, l in zip(image_paths, lbls):    # 获取所有图像文件名的列表    name = [os.path.join(d,f) for f in os.listdir(d)]    file_names.extend(name)    labels.extend([l] * len(name))file_names = tf.convert_to_tensor(file_names, dtype=tf.string)labels = tf.convert_to_tensor(labels)dataset = tf.data.Dataset.from_tensor_slices((file_names, labels))# 其余部分相同 

您可能还需要扩展labels的维度,使其形状为(?, 1)(而不是(?,))。为此,您可以在map_fn函数中添加以下一行:

labels = tf.expand_dims(labels, axis=-1)

3) 如果您有两个类别,那么为什么最后一层有10个单元?这是一个二元分类问题,因此使最后一层有一个单元,并使用sigmoid激活函数。最后,将损失函数改为binary_crossentropy

       # ...        keras.layers.Dense(1, activation=tf.nn.sigmoid)])model.compile(optimizer=tf.train.AdamOptimizer(),              loss='binary_crossentropy',              metrics=['accuracy'])

Related Posts

如何使用Google Protobuf解析、编辑和生成object_detection/pipeline.config文件

我在一个常见的集成学习范式中训练多个模型,目前我在处理…

我的GridSearchCV不起作用,我不知道为什么

大家好,我在使用GridSearchCV时遇到了问题,…

Keras: 两个同时进行的层,其中一个对前一层的输出进行卷积

我想实现这样的模型连接: 输入图像1 -> 卷积层1 …

如何将行数据转换为列数据而不使用独热编码

我有一个如下所示的数据集。 MonthDate Day…

使用 ML Kit 与 NNAPI

我正在尝试在运行 Android 9 的设备上使用新的…

Vowpal Wabbit 可能的哈希冲突

我在VW中生成了一个模型,并且在相同的数据上生成了两个…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注