如何从TensorFlow数据集中提取数据/标签

53

有很多示例可以演示如何创建和使用TensorFlow数据集,例如:

dataset = tf.data.Dataset.from_tensor_slices((images, labels))

我的问题是如何将TF数据集中的数据/标签以numpy形式取回?换句话说,上面那行代码的反向操作是什么,即我有一个TF数据集,想要从中获取图像和标签。


https://dev59.com/0q_2oIgBc1ULPQZF7LGa#70584413 - AloneTogether
13个回答

83

如果您的tf.data.Dataset已经进行了批处理,则以下代码将检索所有的y标签:

y = np.concatenate([y for x, y in ds], axis=0)

简单解释:[y for x, y in ds]在Python中被称为“列表推导式”。如果数据集被分批处理,这个表达式将遍历每个批次并将每个批次的y(一个TF 1D张量)放入列表中,并返回它。然后,np.concatenate将获取这个由1-D张量组成的列表(隐式转换为numpy类型),并将它们沿着0轴堆叠成一个长向量。总之,它只是将一堆1-D小向量转换为一个长向量。

注意:如果您的y更复杂,则需要对此答案进行一些微小修改。


4
优雅简洁!Python风范!+1 - Tim Mironov
@TimMironov 谢谢。在那个一行代码中,我也可以使用 _ 代替 x。实际上,如果你想提取 x 和 y,我认为这有一个缺点。我还没有弄清楚是否可以用类似的一行代码来提取它们两个。 - kawingkelvin
作为一个初学者Python用户,这个答案对我来说非常晦涩。不是说这是一个坏答案,但我认为它需要更多的上下文或解释。 - Jacob Waters
对我来说这是黑魔法,但它运行得很好。 - Jacob Waters
1
有几个人想要解释。我已经更新了这个。关键是要知道什么是列表推导,并阅读numpy concatenate文档。与其他东西相比,它绝不是黑魔法。 - kawingkelvin

26

假设我们的tf.data.Dataset被称为train_dataset,并且启用了eager_execution(在TF 2.x中默认),则可以像这样检索图像和标签:

for images, labels in train_dataset.take(1):  # only take first element of dataset
    numpy_images = images.numpy()
    numpy_labels = labels.numpy()
  • 内联操作.numpy()将tf.Tensors转换为numpy数组
  • 如果您想检索更多数据集元素,请增加take方法中的数字。如果要获取所有元素,请插入-1

6
需要注意的是,有些情况下这种方法会返回count批图像,而不是单个图像。 - Mr. Duhart

11

如果您愿意将图像和标签保留为tf.Tensor,您可以执行以下操作:

images, labels = tuple(zip(*dataset))

将数据集的效果视为 zip(images, labels)。当我们想要获取图像和标签时,我们可以简单地 解压缩 它。

如果您需要numpy数组版本,请使用 np.array() 进行转换:

images = np.array(images)
labels = np.array(labels)

这导致我的程序在一个包含约20,000张图像和12GB RAM的数据集上崩溃。 - Jacob Waters
你需要一次性获取所有数据吗?如果不需要,分批加载数据可能是一个好主意。 - happymacaron
谢谢!连续使用 *zip 似乎可以解决这个错误:(images,), (labels,) = zip(*training_batches.take(1)) 对我来说它解决了这个错误: ValueError: not enough values to unpack (expected 2, got 1) - Shahrokh Bah

8
我认为我们可以在这里找到一个很好的例子: https://colab.research.google.com/github/tensorflow/datasets/blob/master/docs/overview.ipynb#scrollTo=BC4pEXtkp4K-
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds

# where mnsit train is a tf dataset
mnist_train = tfds.load(name="mnist", split=tfds.Split.TRAIN)
assert isinstance(mnist_train, tf.data.Dataset)

mnist_example, = mnist_train.take(1)
image, label = mnist_example["image"], mnist_example["label"]

plt.imshow(image.numpy()[:, :, 0].astype(np.float32), cmap=plt.get_cmap("gray"))
print("Label: %d" % label.numpy())

因此,数据集的每个组成部分都可以像字典一样访问。假设不同的数据集具有不同的字段名称(波士顿住房数据集可能没有图像和价值,但可能具有“特征”和“目标”或“价格”):

cnn = tfds.load(name="cnn_dailymail", split=tfds.Split.TRAIN)
assert isinstance(cnn, tf.data.Dataset)
cnn_ex, = cnn.take(1)
print(cnn_ex)

返回一个包含键 ['article', 'highlight'] 的字典(),其中包含numpy字符串。


6
您可以使用 TF Dataset 方法 unbatch() 来取消批处理数据集,然后您可以轻松地从中检索数据和标签:
ds_labels=[]
for images, labels in ds.unbatch():
    ds_labels.append(labels) # or labels.numpy().argmax() for int labels

或者一行代码:

ds_labels = [labels for _, labels in ds.unbatch()]

1
为什么需要取消批处理?我不能只迭代批次吗?如果这样做,我会得到一个“BatchDataset”对象,它根本不像张量。 - starbeamrainbowlabs

1
这对我起作用了。
features = np.array([list(x[0].numpy()) for x in list(ds_test)])
labels = np.array([x[1].numpy() for x in list(ds_test)])



# NOTE: ds_test was created
iris, iris_info = tfds.load('iris', with_info=True)
ds_orig = iris['train']
ds_orig = ds_orig.shuffle(150, reshuffle_each_iteration=False)
ds_train = ds_orig.take(100)
ds_test = ds_orig.skip(100)

1
这是我自己对这个问题的解决方案:
def dataset2numpy(dataset, steps=1):
    "Helper function to get data/labels back from TF dataset"
    iterator = dataset.make_one_shot_iterator()
    next_val = iterator.get_next()
    with tf.Session() as sess:
        for _ in range(steps):
           inputs, labels = sess.run(next_val)
           yield inputs, labels

请注意,此函数将生成数据集批次的输入/标签。步骤控制从数据集中取出多少批次。

0

0

https://www.tensorflow.org/tutorials/images/classification

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
  for i in range(9):
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(images[i].numpy().astype("uint8"))
  plt.title(class_names[labels[i]])
  plt.axis("off")

0
import numpy as np
import tensorflow as tf

batched_features = tf.constant([[[1, 3], [2, 3]],
                                [[2, 1], [1, 2]],
                                [[3, 3], [3, 2]]], shape=(3, 2, 2))
batched_labels = tf.constant([[0, 0],
                              [1, 1],
                              [0, 1]], shape=(3, 2, 1))
dataset = tf.data.Dataset.from_tensor_slices((batched_features, batched_labels))
classes = np.concatenate([y for x, y in dataset], axis=0)
unique = np.unique(classes, return_counts=True)
labels_dict = dict(zip(unique[0], unique[1]))
print(classes)
print(labels_dict)
# {0: 3, 1: 3}

2
虽然这可能回答了问题,但如果可能的话,您应该编辑您的答案,包括一个简短的解释说明如何这个代码块回答了问题。这有助于提供上下文,并使您的答案对未来的读者更加有用。 - Hoppeduppeanut

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