tensorflow - TensorFlow 网络在使用“dataset.map()”后接收到错误的张量形状
问题描述
按照https://www.tensorflow.org/guide/datasets#preprocessing_data_with_datasetmap上的示例,我想创建一个tf.Dataset
接收图像路径的方法,并将它们映射到图像张量。
我的第一次尝试如下,与上面链接中的示例非常相似:
def input_parser(image_path):
image_data_string = tf.read_file(image_path)
image_decoded = tf.image.decode_png(image_data_string, channels=3)
image_float = tf.image.convert_image_dtype(image_decoded, dtype=tf.float32)
return image_float
def train_model():
image_paths = ['test_image1.png', .test_image2.png', 'test_image3.png']
dataset = tf.data.Dataset.from_tensor_slices(image_paths)
dataset = dataset.map(map_func=input_parser)
iterator = dataset.make_initializable_iterator()
input_images = iterator.get_next()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(iterator.initializer)
for i in range(3):
x = sess.run(input_images)
print(x.shape)
这似乎工作正常,并打印出:
(64, 64, 3)
(64, 64, 3)
(64, 64, 3)
这确实是我的图像的尺寸。
因此,我尝试将这些数据实际输入到网络中进行训练,并相应地修改了代码:
def input_parser(image_path):
image_data_string = tf.read_file(image_path)
image_decoded = tf.image.decode_png(image_data_string, channels=3)
image_float = tf.image.convert_image_dtype(image_decoded, dtype=tf.float32)
return image_float
def train_model():
image_paths = ['test_image1.png', .test_image2.png', 'test_image3.png']
dataset = tf.data.Dataset.from_tensor_slices(image_paths)
dataset = dataset.map(map_func=input_parser)
iterator = dataset.make_initializable_iterator()
input_images = iterator.get_next()
x = tf.layers.conv2d(inputs=input_images, filters=50, kernel_size=[5, 5], name='layer1')
x = tf.layers.flatten(x, name='layer2')
prediction = tf.layers.dense(inputs=x, units=4, name='layer3')
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(iterator.initializer)
for i in range(3):
p = sess.run(prediction)
print(p)
然后这给了我以下错误消息:
ValueError: Input 0 of layer layer1 is incompatible with the layer: expected ndim=4, found ndim=3. Full shape received: [None, None, 3]
我对此有两个问题:
1)为什么我的网络接收到 shape 的输入[None, None, 3]
,正如我们所见,迭代器读取的数据是 shape [64, 64, 3]
。
2) 为什么输入的形状实际上不是[1, 64, 64, 3]
4 维?我认为第一个维度是 1,因为这是批量大小(我没有批量处理数据,所以实际上这是批量大小为 1)。
谢谢!
解决方案
形状是
None
空间维度的,因为原则上您可以加载任何尺寸的图像。无法保证它们将是 64x64,因此 Tensorflow 使用None
形状来允许任何大小的输入。由于您知道图像将始终具有相同的大小,因此您可以使用 aTensor
的set_shape
方法来提供此信息。image_float.set_shape((64, 64, 3))
只需在解析函数中包含一行。请注意,这似乎修改了张量。这里甚至还有一个使用图像的例子。您没有对数据进行批处理,因此根本没有添加批处理轴。数据集的元素只是形状 (64, 64, 3) 的图像,这些元素由迭代器一一返回。如果你想要大小为 1 的批次,你应该使用
dataset = dataset.batch(1)
. 现在数据集的元素是形状(1、64、64、3)的图像“批次”。当然你也可以使用任何其他方法在前面添加一个轴,例如tf.expand_dims
.
推荐阅读
- php - 在 Woocommerce 感谢页面上添加产品缩略图
- google-bigquery - BigQuery 在重复字段上连接表
- pdf - 如何使用 Ghostscript 对 pdf 文档进行每页更改?
- office365 - 如何在 SharePoint 中使用 Jquery 获取 Web 对象?
- c# - 如果应用程序由于未处理的异常或其他原因崩溃,FileStream 会发生什么?
- python - 将列表对象缩短为仅数字并在 Python 中创建新列表
- hibernate - Hibernate 提取错误数据类型的值
- python - 如何在 Python 中从非多部分电子邮件创建多部分电子邮件?
- selenium - 无法通过 winium.desktop.driver 在窗格内找到窗格。无法识别窗格内的元素
- android - 正在进行的通知未取消