代码之家  ›  专栏  ›  技术社区  ›  Karnivaurus

TensorFlow网络在使用“dataset.map()之后接收到错误的张量形状`

  •  1
  • Karnivaurus  · 技术社区  · 6 年前

    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) 为什么我的网络接收到形状的输入 [None, None, 3] ,如我们所见,迭代器读取的数据是 [64, 64, 3]

    2) 为什么输入的形状不是 [1, 64, 64, 3] ,即4维?我认为第一个维度应该是1,因为这是批大小(我不是在批处理数据,所以实际上这是一个1的批大小)。

    谢谢!

    1 回复  |  直到 6 年前
        1
  •  1
  •   xdurch0    6 年前
    1. 形状是 None 因为原则上你可以加载任何大小的图像。不能保证它们是64x64,所以Tensorflow使用 允许任何大小输入的形状。因为您知道图像的大小总是相同的,所以可以使用 Tensor set_shape 方法来提供此信息。就写一行 image_float.set_shape((64, 64, 3)) here .

    2. 您不在批处理数据,所以根本不添加批处理轴。数据集的元素只是形状(64、64、3)的图像,迭代器逐个返回这些元素。如果你想要1号的批,你应该使用 dataset = dataset.batch(1) tf.expand_dims .