Google colab не загружает файлы изображений при использовании пакетного набора данных tenorflow 2.0 - PullRequest
6 голосов
/ 27 марта 2020

Немного фона, я загружаю около 60 000 изображений в colab для обучения GAN. Я уже загрузил их на диск, и структура каталогов содержит папки для разных классов (около 7-8) внутри root. Я загружаю их в colab следующим образом:

root = "drive/My Drive/data/images"
root = pathlib.Path(root)

list_ds = tf.data.Dataset.list_files(str(root/'*/*'))

for f in list_ds.take(3):
  print(f.numpy())

, который дает вывод:

b'drive/My Drive/data/images/folder_1/2994.jpg'
b'drive/My Drive/data/images/folder_1/6628.jpg'
b'drive/My Drive/data/images/folder_2/37872.jpg'

Я продолжаю обрабатывать их следующим образом:

def process_path(file_path):
  label = tf.strings.split(file_path, '/')[-2]
  image = tf.io.read_file(file_path)
  image = tf.image.decode_jpeg(image)
  image = tf.image.convert_image_dtype(image, tf.float32)
  return image#, label

ds = list_ds.map(process_path)

BUFFER_SIZE = 60000
BATCH_SIZE = 128

train_dataset = ds.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)

Каждый изображение имеет размер 128x128. Теперь перейдем к проблеме, когда я пытаюсь просмотреть пакет в colab, выполнение продолжается вечно и никогда не останавливается, например, с таким кодом:

for batch in train_dataset.take(4):
  print([arr.numpy() for arr in batch])

Ранее я думал, что batch_size может быть проблемой, поэтому попытался меняя его, но все же проблема. Может ли это быть проблемой из-за колаба, когда я загружаю большое количество файлов?

Или из-за размера изображений, который работал при использовании MNIST (28x28)? Если да, каковы возможные решения?

Заранее спасибо.

РЕДАКТИРОВАТЬ: после удаления оператора shuffle последняя строка выполняется в течение нескольких секунд. Поэтому я подумал, что это может быть проблемой из-за случайного перемешивания BUFFER_SIZE, но даже с уменьшенным значением BUFFER_SIZE выполнение снова занимает очень много времени. Есть обходной путь?

1 Ответ

3 голосов
/ 30 марта 2020

Вот как я загружаю набор изображений FLICKR в сжатом виде объемом 1,12 ГБ из моего личного диска Google. Сначала я разархивирую набор данных в среде colab. Некоторые функции, которые могут ускорить производительность: prefetch и autotune. Кроме того, я использую локальный кеш colab для хранения обработанных изображений. Это займет ~ 20 секунд, чтобы выполнить в первый раз (при условии, что вы разархивировали набор данных). Затем кэш позволяет загружать последующие вызовы очень быстро.

Предполагая, что вы авторизовали API Google Drive, я начинаю с разархивирования папки (ей)

!unzip /content/drive/My\ Drive/Flickr8k
!unzip Flickr8k_Dataset
!ls

Затем я использовал ваш код с добавление prefetch(), autotune и cache file.

import pathlib
import tensorflow as tf

def prepare_for_training(ds, cache, BUFFER_SIZE, BATCH_SIZE):
  if cache:
    if isinstance(cache, str):
      ds = ds.cache(cache)
    else:
      ds = ds.cache()
  ds = ds.shuffle(buffer_size=BUFFER_SIZE)
  ds = ds.batch(BATCH_SIZE)
  ds = ds.prefetch(buffer_size=AUTOTUNE)
  return ds

AUTOTUNE = tf.data.experimental.AUTOTUNE

root = "Flicker8k_Dataset"
root = pathlib.Path(root)

list_ds = tf.data.Dataset.list_files(str(root/'**'))

for f in list_ds.take(3):
  print(f.numpy())

def process_path(file_path):
  label = tf.strings.split(file_path, '/')[-2]
  img = tf.io.read_file(file_path)
  img = tf.image.decode_jpeg(img)
  img = tf.image.convert_image_dtype(img, tf.float32)
  # resize the image to the desired size.
  img =  tf.image.resize(img, [128, 128])
  return img#, label

ds = list_ds.map(process_path, num_parallel_calls=AUTOTUNE)
train_dataset = prepare_for_training(ds, cache="./custom_ds.tfcache", BUFFER_SIZE=600000, BATCH_SIZE=128)
for batch in train_dataset.take(4):
  print([arr.numpy() for arr in batch])

Вот способ сделать это с помощью keras flow_from_directory(). Преимущество этого подхода состоит в том, что вы избегаете тензор потока shuffle(), который в зависимости от размера буфера может потребовать обработки всего набора данных. Keras предоставляет вам итератор, который вы можете вызвать для извлечения пакета данных, и имеет встроенную случайную перемешивание.

import pathlib
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

root = "Flicker8k_Dataset"
BATCH_SIZE=128

train_datagen = ImageDataGenerator(
    rescale=1./255 )

train_generator = train_datagen.flow_from_directory(
        directory = root,  # This is the source directory for training images
        target_size=(128, 128),  # All images will be resized
        batch_size=BATCH_SIZE,
        shuffle=True,
        seed=42, #for the shuffle
        classes=[''])

i = 4
for batch in range(i):
  [print(x[0]) for x in next(train_generator)]
...