谷歌协作平台在使用TensorFlow 2.0批次数据集时无法加载图像文件

8

一些背景信息,我正在加载大约60,000张图片到colab来训练GAN。我已经将它们上传到Drive,并且目录结构包含不同类别(大约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可能是个问题,所以尝试更改它,但问题仍然存在。这可能是由于在Colab中加载大量文件引起的问题吗?

或者由于图像大小的原因,当使用MNIST(28x28)时可以正常工作?如果是这样,有哪些可能的解决方案?

提前感谢。

编辑: 删除shuffle语句后,最后一行代码几秒钟内就能执行完。因此我认为这可能是由于shuffle的BUFFER_SIZE问题,但即使将BUFFER_SIZE减小,它仍需要很长时间才能执行。有没有什么解决方法?


你尝试检查是否有可用的GPU了吗? - MPA
是的,我尝试过使用CPU和GPU。 - bkshi
1个回答

3
这是我如何从我的个人Google Drive中加载一个1.12GB的FLICKR图像数据集的步骤。首先,在colab环境中解压数据集。一些可以加速性能的特性是“prefetch”和“autotune”。此外,我使用本地的colab缓存来存储处理后的图像。第一次执行需要约20秒钟(假设您已解压数据集)。然后,缓存允许后续调用非常快速。
假设您已经授权了Google Drive API,我开始解压文件夹。
!unzip /content/drive/My\ Drive/Flickr8k
!unzip Flickr8k_Dataset
!ls

我随后使用了你的代码,并添加了prefetch()autotunecache 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() 方法的方式。这种方法的好处是您可以避免使用TensorFlow的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)]

你的计算机中,执行print([arr.numpy() for arr in batch])代码所需时间是多少? - bkshi
你使用的数据集大小是多少? - bkshi
1.12 GB 的压缩文件,无论我是全部取还是在循环中取其中的4个,都需要20秒钟。 - pastaleg
@bkshi 你试过 Tensorflow 的数据吗? - pastaleg
我在谈论我的答案中的第二个代码片段。我已经更新它,从tensorflow的服务器加载MNIST,而不是从Google Drive文件夹加载。 - pastaleg
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接