Ошибка при проверке ввода: ожидалось, что flatten_input имеет 3 измерения, но получил массив с формой (None, 100, 100, 1) - PullRequest
0 голосов
/ 21 сентября 2018

Используя TensorFlow / Keras, я хочу разделить изображения на два класса: селфи и не селфи.

Я собрал сэмплы в две папки файловой системы, по одной для каждой категории.

Iреализовал обучение, приведенное ниже, следуя официальному руководству по моде MNIST (которое также является проблемой классификации изображений), после использования загрузки изображений из файловой системы, как показано на 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.

Как я могу адаптировать Keras к моему вводу или преобразовать мой ввод так, чтобы Keras принял его?

1 Ответ

0 голосов
/ 21 сентября 2018

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) Если у вас есть два класса, то почему последний слой имеет 10 единиц?Это проблема двоичной классификации, поэтому у последнего слоя должен быть один блок с активацией sigmoid.Наконец, измените убыток на binary_crossentropy:

       # ... 
       keras.layers.Dense(1, activation=tf.nn.sigmoid)
])

model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='binary_crossentropy',
              metrics=['accuracy'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...