Tensorflow conjuntos de datos: Recortar/cambiar el tamaño de imágenes por lotes después de la del conjunto de datos.lote()

0

Pregunta

Es posible Recortar/cambiar el tamaño de imágenes por lotes ?

Estoy usando Tensorflow conjunto de datos de la API de la siguiente manera:

dataset = dataset.shuffle().repeat().batch(batch_size, drop_remainder=True)

Quiero, en el lote de todas las imágenes deben tener el mismo tamaño. Sin embargo a través de los lotes puede tener diferentes tamaños.

Por ejemplo, lote 1 tiene todas las imágenes de la forma (batch_size, 300, 300, 3). Siguiente lote puede tener imágenes de forma (batch_size, 224, 224, 3). Otro lote puede tener imágenes de forma (batch_size, 400, 400, 3).

Básicamente quiero tener dymanically en forma de lotes, sin embargo todas las imágenes dentro del lote estática formas.

Si hacemos como sigue:

dataset = dataset.shuffle().repeat().batch(batch_size, drop_remainder=True).map(lambda x, y: map_fn(x, y))

Significa lo anterior .mapa() se aplica a cada lote por separado o de todo el conjunto de datos ?

Si anteriormente .mapa() no aplica para cada lote por separado, ¿cómo podemos hacer esto ? Podemos definir cualquier iterador después de conjunto de datos.lote(), se aplican tf.imagen.crop_and_resize() sobre cada imagen por lote y el uso posterior del conjunto de datos.concatenar() para combinar todos transformados de los lotes ?

Estoy creando el conjunto de datos de la siguiente manera:

# Dataset creation (read image data from files of COCO dataset)
dataset = tf.data.Dataset.list_files(self._file_pattern, shuffle=False)
dataset = dataset.shard(dataset_num_shards, dataset_shard_index)
dataset = dataset.shuffle(tf.cast(256 / dataset_num_shards, tf.int64))
dataset = dataset.interleave(map_func=tf.data.TFRecordDataset(filename).prefetch(1), cycle_length=32, block_length=1, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset = dataset.map(tf_example_decoder.TfExampleDecoder().decode, num_parallel_calls=64)
dataset = dataset.shuffle(64).repeat()
# Parse each image for preprocessing
dataset = dataset.map(lambda data, _: _parse_example(data), num_parallel_calls=64)
dataset = dataset.batch(batch_size=batch_size, drop_remainder=True)

# Below code suggested by you to resize images to fixed shape in each batch
def resize_data(images, labels):
    tf.print('Original shape -->', tf.shape(images))
    SIZE = (300, 300)
    return tf.image.resize(images, SIZE), labels
dataset = dataset.map(resize_data)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)

tf.estimator.Estimator(...).train(
        input_fn=dataset,
        steps=steps,
        hooks=train_hooks)
python tensorflow tensorflow-datasets
2021-11-24 05:50:45
1

Mejor respuesta

1

Por lo general, usted puede intentar algo como esto:

import tensorflow as tf
import numpy as np

dataset1 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 300, 300, 3)))
dataset2 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 224, 224, 3)))
dataset3 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 400, 400, 3)))
dataset = dataset1.concatenate(dataset2.concatenate(dataset3))
dataset = dataset.shuffle(1).repeat().batch(32, drop_remainder=True)

def resize_data(images):
  tf.print('Original shape -->', tf.shape(images))
  SIZE = (180, 180)

  return tf.image.resize(images, SIZE)

dataset = dataset.map(resize_data)

for images in dataset.take(3):
  tf.print('New shape -->', tf.shape(images))
Original shape --> [32 300 300 3]
New shape --> [32 180 180 3]
Original shape --> [32 224 224 3]
New shape --> [32 180 180 3]
Original shape --> [32 400 400 3]
New shape --> [32 180 180 3]

Usted también podría usar tf.image.resize_with_crop_or_pad si usted desea:

def resize_data(images):
  tf.print('Original shape -->', tf.shape(images))
  SIZE = (180, 180)
  return tf.image.resize_with_crop_or_pad(images, SIZE[0], SIZE[1])

dataset = dataset.map(resize_data)

for images in dataset.take(3):
  tf.print('New shape -->', tf.shape(images))

Tenga en cuenta que el uso de repeat() va a crear un infinito conjunto de datos.

Actualización 1

Si desea un tamaño al azar de cada lote, intentar algo como esto:

import tensorflow as tf
import numpy as np

dataset1 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 300, 300, 3)))
dataset2 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 224, 224, 3)))
dataset3 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 400, 400, 3)))
dataset = dataset1.concatenate(dataset2.concatenate(dataset3))
dataset = dataset.batch(32, drop_remainder=True).shuffle(96)


def resize_data(images):
  batch_size = tf.shape(images)[0]
  images_resized = tf.TensorArray(dtype=tf.float32, size = 0, dynamic_size=True)
  SIZE = tf.random.uniform((2,), minval=300, maxval=500, dtype=tf.int32)
  for i in range(batch_size):
    images_resized = images_resized.write(images_resized.size(), tf.image.resize(images[i], SIZE))
  return images_resized.stack()

dataset = dataset.map(resize_data)

for images in dataset:
  tf.print('New shape -->', tf.shape(images))
New shape --> [32 392 385 3]
New shape --> [32 468 459 3]
New shape --> [32 466 461 3]

Actualización 2

Una muy opción flexible que funciona para cualquier tamaño de lote tendría este aspecto:

import tensorflow as tf
import numpy as np

dataset1 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 300, 300, 3)))
dataset2 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 224, 224, 3)))
dataset3 = tf.data.Dataset.from_tensor_slices(np.random.random((32, 400, 400, 3)))
dataset = dataset1.concatenate(dataset2.concatenate(dataset3))

def resize_and_batch(dataset, batch_size):
  final_dataset = None
  duration = len(dataset)//batch_size
  random_sizes = [tf.random.uniform((2,), minval=300, maxval=500, dtype=tf.int32) for _ in range(duration)]

  for i, size in zip(range(duration), random_sizes):
    idx = i * batch_size
    if i == 0:
      final_dataset = tf.data.Dataset.from_tensor_slices([tf.image.resize(x, size) for x in dataset.take(batch_size)])
    else:
      final_dataset = final_dataset.concatenate(tf.data.Dataset.from_tensor_slices([tf.image.resize(x, size) for x in dataset.skip(idx).take(batch_size)]))
  return final_dataset

batch_size = 10
ds = resize_and_batch(dataset, batch_size)
ds = ds.batch(batch_size).shuffle(len(ds))
for images in ds:
 tf.print('New shape -->', images.shape)
New shape --> TensorShape([10, 399, 348, 3])
New shape --> TensorShape([10, 356, 329, 3])
New shape --> TensorShape([10, 473, 373, 3])
New shape --> TensorShape([10, 489, 489, 3])
New shape --> TensorShape([10, 421, 335, 3])
New shape --> TensorShape([10, 447, 455, 3])
New shape --> TensorShape([10, 355, 382, 3])
New shape --> TensorShape([10, 310, 396, 3])
New shape --> TensorShape([10, 345, 356, 3])
2021-12-01 14:51:04

Es que se ve bien. Sin embargo aún no funciona para mí. Cuando trato de entrenar el modelo, da error como el siguiente: INVALID_ARGUMENT: Cannot add tensor to the batch: number of elements does not match. Shapes are: [tensor]: [640,426,3], [batch]: [480,640,3] Aunque me dio SIZE = (300, 300) en tf.imagen.cambiar el tamaño(imágenes, TAMAÑO), el lote tiene un TAMAÑO = (480, 640). Y como en la siguiente imagen se tiene de diferente TAMAÑO = (640, 426), no de añadir al lote. Eso significa que de alguna manera no es capaz de aplicar .mapa() de la función en cada uno de los lotes. Cualquier ayuda/idea ?
Avid Learner

Puede agregar el código de la creación de sus bases de datos a su pregunta? Creo que tengo una idea de lo que podría ser el problema.
AloneTogether

He actualizado a la pregunta de cómo estoy creando el conjunto de datos. Esperando su respuesta.
Avid Learner

Respuesta actualizada-
AloneTogether

batch_size=16. Es tirar el mismo error con batch_size > 1.
Avid Learner

Es difícil entender qué es exactamente lo que usted está haciendo sin ningún tipo de acceso al conjunto de datos y de las variables que se han definido en algún otro lugar. Probablemente el problema sea que cada lote no tenemos las imágenes todas de la misma forma.
AloneTogether

Avid Learner

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................