Python 如何在tf.data.Dataset中输入不同大小的列表列表
我有一个很长的整数列表(表示句子,每个句子的大小不同),我想使用tf.data库提供这些整数。每个列表(列表的列表)有不同的长度,我得到一个错误,我可以在这里重现:Python 如何在tf.data.Dataset中输入不同大小的列表列表,python,tensorflow,tensorflow-datasets,Python,Tensorflow,Tensorflow Datasets,我有一个很长的整数列表(表示句子,每个句子的大小不同),我想使用tf.data库提供这些整数。每个列表(列表的列表)有不同的长度,我得到一个错误,我可以在这里重现: t = [[4,2], [3,4,5]] dataset = tf.data.Dataset.from_tensor_slices(t) 我得到的错误是: ValueError: Argument must be a dense tensor: [[4, 2], [3, 4, 5]] - got shape [2], but wa
t = [[4,2], [3,4,5]]
dataset = tf.data.Dataset.from_tensor_slices(t)
我得到的错误是:
ValueError: Argument must be a dense tensor: [[4, 2], [3, 4, 5]] - got shape [2], but wanted [2, 2].
有办法做到这一点吗
编辑1:为了清楚起见,我不想填充列表的输入列表(这是一个包含超过一百万个元素的句子列表,长度不同),我想使用tf.data库以适当的方式输入,具有不同长度的列表列表。我认为tensorflow不支持在给定维度上具有不同数量元素的张量 但是,一个简单的解决方案是用尾随零填充嵌套列表(如有必要): 产出:
[[4, 2, 0], [3, 4, 5]]
<TensorSliceDataset shapes: (3,), types: tf.int32>
[[4,2,0],[3,4,5]]
对于模型来说,零不应该是一个大问题:从语义上讲,它们只是每个实际句子列表末尾大小为零的额外句子。您可以使用它将任何iterable Python对象(如列表列表)转换为数据集
t = [[4, 2], [3, 4, 5]]
dataset = tf.data.Dataset.from_generator(lambda: t, tf.int32, output_shapes=[None])
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
print(sess.run(next_element)) # ==> '[4, 2]'
print(sess.run(next_element)) # ==> '[3, 4, 5]'
除了@mrry的答案外,如果要创建(图像、标签)对,还可以使用以下代码:
对于那些使用TensorFlow 2并寻找答案的人
我发现以下内容可以直接用于不规则张量。
只要整个数据集都放在内存中,它应该比生成器快得多
t = [[[4,2]],
[[3,4,5]]]
rt=tf.ragged.constant(t)
dataset = tf.data.Dataset.from_tensor_slices(rt)
for x in dataset:
print(x)
产生
出于某种原因,在单个数组上至少有两个维度是非常特别的。嗨,谢谢你的回答,因为我不能填充整个列表,因为它太大了。我将为每个批次进行填充,但不是为由数百万个句子组成的整个数据集进行填充。如果您将句子列表(字符串列表)传递到tf.data.dataset.from_tensor_slices
,它应该可以工作,然后您应该能够使用dataset.map(您的函数)
将每个句子转换为整数列表。然后,您可以使用dataset.padded\u batch
自动添加填充。这个示例非常有用:Hi@OlivierMoindrot,我已经看到了这个示例。我关心的是:在训练时运行图形时(即每次向模型提供新数据时),还是在训练前在整个数据集上执行,然后提供结果时,会执行映射函数?在我看来,与第二个相比,第一个训练要慢得多,这就是我想要避免的。这就是tf.data
的全部要点,它在后台使用队列,只在需要时处理数据。您可以“预取”数据,以确保您的GPU从不等待数据,并以100%的速度工作。由于数据在一端消耗(用于培训),因此之前的队列将被数据填满。您甚至可以使用num\u parallel\u调用
.dataset拥有多个worker。prefetch@mrry,我的想法是一样的,来自生成器的数据集可以成批处理,我的意思是使其成为一个小批量?+1但供参考,tf 2.1不再需要额外的括号
import itertools
data = tf.data.Dataset.from_generator(lambda: itertools.izip_longest(images, labels),
output_types=(tf.float32, tf.float32),
output_shapes=(tf.TensorShape([None, None, 3]),
tf.TensorShape([None])))
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
image, label = sess.run(next_element) # ==> shape: [320, 420, 3], [20]
image, label = sess.run(next_element) # ==> shape: [1280, 720, 3], [40]
t = [[[4,2]],
[[3,4,5]]]
rt=tf.ragged.constant(t)
dataset = tf.data.Dataset.from_tensor_slices(rt)
for x in dataset:
print(x)
<tf.RaggedTensor [[4, 2]]>
<tf.RaggedTensor [[3, 4, 5]]>