代码之家  ›  专栏  ›  技术社区  ›  Nicolas Raoul

检查输入时出错:期望flatten\u输入有3个维度,但得到了具有形状的数组(None,100,100,1)

  •  0
  • Nicolas Raoul  · 技术社区  · 7 年前

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

    我已将示例收集到两个文件系统文件夹中,每个文件夹对应一个类别。

    https://stackoverflow.com/a/52417770/226958 .

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

    1.10.1
    Tensor("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 tf
    print(tf.__version__)
    
    out_shape = tf.convert_to_tensor([100, 100])
    batch_size = 2
    
    image_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)
    
    # The images loading part is from https://stackoverflow.com/a/52417770/226958
    dataset = tf.data.Dataset.from_tensor_slices((image_paths, labels))
    dataset = dataset.repeat().shuffle(epoch_size)
    
    def map_fn(path, label):
        # path/label represent values for a single example
        image = tf.image.decode_jpeg(tf.read_file(path))
    
        # some mapping to constant size - be careful with distorting aspec ratios
        image = tf.image.resize_images(image, out_shape)
        image = tf.image.rgb_to_grayscale(image)
        # color normalization - just an example
        image = tf.to_float(image) * (2. / 255) - 1
        return image, label
    
    # num_parallel_calls > 1 induces intra-batch shuffling
    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()
    
    # All of the following is from https://www.tensorflow.org/tutorials/keras/basic_classification
    from tensorflow import keras
    
    model = 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 .

    1 回复  |  直到 7 年前
        1
  •  3
  •   today    7 年前

    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):
        # get the list all the images file names
        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))
    
    # the rest is the same 
    

    labels 使其具有 (?, 1) (代替 (?,) map_fn 功能:

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

    3) sigmoid 激活。最后,将损失改为 binary_crossentropy :

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