Tensorflow ensembles de données: Recadrer/Redimensionner les images par lot, après l'ensemble des données.lot()

0

La question

Est-il possible de Recadrer/Redimensionner les images par lot ?

Je suis en utilisant Tensorflow dataset API comme ci-dessous:

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

Je veux, dans le lot de toutes les images doivent avoir la même taille. Cependant à travers les lots, il peut avoir des tailles différentes.

Par exemple, le 1er lot a toutes les images de la forme (batch_size, 300, 300, 3). Prochain lot peut avoir des images de la forme (batch_size, 224, 224, 3). Un lot peut avoir des images de la forme (batch_size, 400, 400, 3).

Fondamentalement, je veux avoir dymanically en forme de lots, cependant toutes les images dans le lot statique des formes.

Si nous ne faisons que suivre:

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

Le ci-dessus .map() s'applique à chaque lot séparément ou plus de l'ensemble du jeu de données ?

Si ci-dessus .map() ne s'applique pas à chaque lot séparément, comment pouvons-nous faire cela ? Pouvons-nous définir le tout itérateur après dataset.lot () s'appliquent de la tf.image.crop_and_resize() sur chaque image par lot, et ensuite utiliser un jeu de données.concatener() pour combiner tous transformés lots ?

Je suis de la création du jeu de données comme ci-dessous:

# 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

La meilleure réponse

1

Généralement, vous pouvez essayer quelque chose comme ceci:

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]

Vous pouvez également utiliser tf.image.resize_with_crop_or_pad si vous le souhaitez:

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

Notez que l'utilisation de repeat() va créer un infini jeu de données.

Mise à jour 1

Si vous souhaitez une taille aléatoire pour chaque lot, essayez quelque chose comme ceci:

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]

Mise à jour 2

Un très souples option qui fonctionne pour n'importe quel taille de lot ressemblerait à ceci:

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

Il a l'air bon. Cependant cela ne fonctionne toujours pas pour moi. Lorsque j'essaie de former le modèle, il donne une erreur comme ci-dessous: INVALID_ARGUMENT: Cannot add tensor to the batch: number of elements does not match. Shapes are: [tensor]: [640,426,3], [batch]: [480,640,3] Même si j'ai donné la TAILLE de l' = (300, 300) en tf.image.redimensionner des images, TAILLE), des lots de TAILLE a = (480, 640). Et comme l'image suivante a différente TAILLE = (640, 426), il n'a pas l'ajouter au lot. Cela signifie que d'une certaine manière, il n'est pas en mesure d'appliquer .map() la fonction de chaque lot. Toute aide/idée ?
Avid Learner

Pourriez-vous ajouter le code sur la façon dont vous créez vos jeux de données à votre question? Je pense avoir une idée de ce que peut être le problème.
AloneTogether

J'ai mis à jour la question de la façon dont je suis la création du jeu de données. En attente de votre réponse.
Avid Learner

Mise à jour de la réponse-
AloneTogether

batch_size=16. C'est jeter même erreur avec batch_size > 1.
Avid Learner

Il est difficile de comprendre exactement ce que vous faites sans aucun accès à l'ensemble de données que vous utilisez et les variables que vous avez défini quelque part d'autre. Le problème est probablement que chaque lot n'a pas les images toutes de la même forme.
AloneTogether

Avid Learner

Dans d'autres langues

Cette page est dans d'autres langues

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