【问题标题】:Consistent extraction of data from tensorflow dataset从 tensorflow 数据集中一致地提取数据
【发布时间】:2022-01-04 19:10:28
【问题描述】:

我想将 tensorflow 数据集中的数据一致地提取到 numpy 数组/张量中。我正在加载图片和

data = keras.preprocessing.image_dataset_from_directory(
  './data', 
  labels='inferred', 
  label_mode='binary', 
  validation_split=0.2, 
  subset="training", 
  image_size=(img_height, img_width), 
  batch_size=sz_batch, 
  crop_to_aspect_ratio=True
)

我已经得到了使用以下行的提示:

xdata = np.concatenate([x for x, y in data], axis=0)
ydata = np.concatenate([y for x, y in data], axis=0)

然而,问题是xdata 和ydata 中提取的数据不一致,因此ydata 中的标签不适合xdata 中的样本(我通过简单地检查了这一点循环提取的数据)。

我的第二个想法是在标准 for 循环中提取数据:

xdata = np.empty([sz1, sz2, 3])[np.newaxis,...]
ydata = np.array([0])
for images, labels in val_ds:
    xdata = np.concatenate((xdata, images), axis=0)
    ydata = np.concatenate((ydata, labels), axis=0)

xdata = xval[1:]
ydata = yval[1:]

尽管数据似乎与这种方法一致,但我认为这种方法相当繁琐,而且写得也不好(而且可能效率也不高)——尤其是最后两行让我很困扰。但是我无法想出一种更简单的方法来提取数据并将提取的数据堆叠在 numpy 数组/张量中。

如果能在 python 中正确解决这个问题,我会非常感激。

无论如何,我想知道为什么处理 tensorflow 数据集至少在我看来真的很麻烦。首先,我需要解决上述问题,以便在其他例程中使用数据,而不是在 tensorflow 中。其次,即使我在 tensorflow 训练以外的任何地方使用数据,我的选择也不是很简单。例如。如果我想将来自 NN 的预测标签与来自数据集的真实标签进行比较,我无法轻松提取该数据集的一致标签。我必须在 for 循环中分别预测每个样本。

注意:我不会/不能使用tfds

【问题讨论】:

  • 如果数据集被洗牌,您需要对其进行迭代。您可以使用列表而不是数组进行追加。

标签: python numpy tensorflow tensorflow-datasets


【解决方案1】:

关于将数据集转换为 numpy 数组时的顺序,如果您想看到相同的结果,请确保将 shuffle=False 设置为 image_dataset_from_directory:

import tensorflow as tf
import matplotlib.pyplot as plt
import pathlib

dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)

batch_size = 32

train_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(180, 180),
  batch_size=batch_size,
  shuffle=False)

normalization_layer = tf.keras.layers.Rescaling(1./255)
train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
images, labels = next(iter(train_ds.take(1)))
image = images[0]
plt.title('label :: ' + str(labels[0]))
plt.imshow(image.numpy())

之后,您可以尝试几种方法将数据集转换为列表或类似数组的结构:

选项 1:

train_ds = train_ds.unbatch()
data = list(train_ds.map(lambda x, y: (x, y)))
data = list(map(list, zip(*data)))
images, labels = data[0], data[1]

image = images[0]
plt.title('label :: ' + str(labels[0]))
plt.imshow(image.numpy())

选项 2:

import numpy as np

train_ds = train_ds.unbatch()
images = np.asarray(list(train_ds.map(lambda x, y: x)))
labels = np.asarray(list(train_ds.map(lambda x, y: y)))
image = images[0]
plt.title('label :: ' + str(labels[0]))
plt.imshow(image)

选项 3:

import numpy as np

# no unbatching
images = np.concatenate(list(train_ds.map(lambda x, y: x)))
labels = np.concatenate(list(train_ds.map(lambda x, y: y)))

image = images[0]
plt.title('label :: ' + str(labels[0]))
plt.imshow(image)

所有选项都将保持数据的顺序:

更新 1: 您也可以尝试使用tf.TensorArray 并设置shuffle=True:

images = tf.TensorArray(dtype=tf.float32, size=0, dynamic_size=True)
labels = tf.TensorArray(dtype=tf.int32, size=0, dynamic_size=True)

for x, y in train_ds.unbatch():
  images = images.write(images.size(), x)
  labels = labels.write(labels.size(), y)

images = tf.stack(images.stack(), axis=0)
labels = tf.stack(labels.stack(), axis=0)

【讨论】:

  • 设置shuffle=False 并不是我真正想要的方式,因为我必须在提取后手动打乱数据集(目录中的数据是有序的),因此,我必须打乱它两次。如果我禁用改组,我在第二个代码块中的解决方案也可以工作。
  • 你试过使用 TensorArrays 吗?检查我更新的答案。
  • 这似乎工作正常。非常感谢!
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 2020-11-10
  • 2019-08-09
  • 1970-01-01
  • 2011-04-18
  • 2017-10-08
  • 2020-06-21
  • 1970-01-01
相关资源
最近更新 更多