Tensorflow set di dati: consente di Ritagliare, Ridimensionare le immagini per lotto dopo il set di dati.batch()

0

Domanda

È possibile Ritagliare, Ridimensionare le immagini per lotto ?

Sto usando Tensorflow set di dati API, come di seguito:

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

Voglio, all'interno del batch tutte le immagini devono avere la stessa dimensione. Tuttavia in tutto il batch può avere diverse dimensioni.

Per esempio, 1 ° lotto dispone di tutte le immagini di forma (batch_size, 300, 300, 3). La prossima partita può avere immagini di forma (batch_size, 224, 224, 3). Un altro batch può avere immagini di forma (batch_size, 400, 400, 3).

Fondamentalmente voglio avere dymanically a forma di lotti, tuttavia, tutte le immagini in batch hanno statico forme.

Se facciamo come segue:

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

Il sopra .mappa() vale per ogni partita separatamente o sull'intero set di dati ?

Se in precedenza .mappa() non si applicano separatamente per ciascun lotto, come possiamo fare questo ? Possiamo definire qualsiasi iteratore dopo il set di dati.batch(), applicare tf.immagine.crop_and_resize() su ogni immagine per lotto e dopo l'uso del set di dati.concatena() per combinare tutti trasformati lotti ?

Sto creando il set di dati come qui di seguito:

# 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

Migliore risposta

1

In generale, si può provare qualcosa di simile a questo:

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]

Si potrebbe anche usare tf.image.resize_with_crop_or_pad se si desidera:

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))

Si noti che l'utilizzo repeat() crea un infinito set di dati.

Update 1

Se si desidera una dimensione casuale per ciascun lotto, provare qualcosa di simile a questo:

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]

Aggiorna 2

Molto flessibile, opzione che funziona per tutte le dimensioni del batch sarebbe simile a questa:

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

Si guarda bene. Tuttavia ancora non funziona per me. Quando cerco di treno modello, dà errore, come di seguito: INVALID_ARGUMENT: Cannot add tensor to the batch: number of elements does not match. Shapes are: [tensor]: [640,426,3], [batch]: [480,640,3] Anche se ho dato la DIMENSIONE = (300, 300) in tf.immagine.ridimensionare(immagini, DIMENSIONI), batch SIZE = (480, 640). E come l'immagine successiva è diversa DIMENSIONE = (640, 426), non è riuscita ad aggiungere al lotto. Ciò significa che, in qualche modo, non è in grado di applicare .mappa() funzione di ogni singolo lotto. Qualsiasi aiuto/idea ?
Avid Learner

Si potrebbe aggiungere il codice su come la creazione di set di dati per la tua domanda? Credo di avere un'idea di che cosa il problema potrebbe essere.
AloneTogether

Ho aggiornato la domanda di come mi sto creando il set di dati. In attesa di vostra risposta.
Avid Learner

Aggiornato risposta-
AloneTogether

batch_size=16. È gettare stesso errore con batch_size > 1.
Avid Learner

Il suo difficile capire esattamente cosa si sta facendo, senza alcun accesso ai set di dati che si sta utilizzando e le variabili definite da qualche altra parte. Il problema probabilmente è che ogni partita non sono le immagini tutte della stessa forma.
AloneTogether

Avid Learner

In altre lingue

Questa pagina è in altre lingue

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