如何在 tf.data.Dataset 中输入不同大小的列表列表
How to input a list of lists with different sizes in tf.data.Dataset
我有一长串整数列表(代表句子,每个句子的大小不同),我想使用 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 wanted [2, 2].
有办法吗?
编辑 1:明确地说,我不想填充列表的输入列表(这是一个包含超过一百万个元素的句子列表,具有不同的长度)我想使用 tf.data 库以适当的方式提供不同长度的列表列表。
我认为 tensorflow 不支持沿给定维度具有不同数量元素的张量。
但是,一个简单的解决方案是用尾随零填充嵌套列表(必要时):
t = [[4,2], [3,4,5]]
max_length = max(len(lst) for lst in t)
t_pad = [lst + [0] * (max_length - len(lst)) for lst in t]
print(t_pad)
dataset = tf.data.Dataset.from_tensor_slices(t_pad)
print(dataset)
输出:
[[4, 2, 0], [3, 4, 5]]
<TensorSliceDataset shapes: (3,), types: tf.int32>
零对于模型来说应该不是什么大问题:从语义上讲,它们只是每个实际句子列表末尾的零大小的额外句子。
您可以使用 tf.data.Dataset.from_generator()
将任何可迭代的 Python 对象(如列表的列表)转换为 Dataset
:
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 的回答之外,如果您想创建(图像,标签)对,也可以使用以下代码:
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]
对于那些使用 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.RaggedTensor [[4, 2]]>
<tf.RaggedTensor [[3, 4, 5]]>
出于某种原因,在单个数组上至少有 2 个维度是非常特别的。
我有一长串整数列表(代表句子,每个句子的大小不同),我想使用 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 wanted [2, 2].
有办法吗?
编辑 1:明确地说,我不想填充列表的输入列表(这是一个包含超过一百万个元素的句子列表,具有不同的长度)我想使用 tf.data 库以适当的方式提供不同长度的列表列表。
我认为 tensorflow 不支持沿给定维度具有不同数量元素的张量。
但是,一个简单的解决方案是用尾随零填充嵌套列表(必要时):
t = [[4,2], [3,4,5]]
max_length = max(len(lst) for lst in t)
t_pad = [lst + [0] * (max_length - len(lst)) for lst in t]
print(t_pad)
dataset = tf.data.Dataset.from_tensor_slices(t_pad)
print(dataset)
输出:
[[4, 2, 0], [3, 4, 5]]
<TensorSliceDataset shapes: (3,), types: tf.int32>
零对于模型来说应该不是什么大问题:从语义上讲,它们只是每个实际句子列表末尾的零大小的额外句子。
您可以使用 tf.data.Dataset.from_generator()
将任何可迭代的 Python 对象(如列表的列表)转换为 Dataset
:
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 的回答之外,如果您想创建(图像,标签)对,也可以使用以下代码:
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]
对于那些使用 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.RaggedTensor [[4, 2]]> <tf.RaggedTensor [[3, 4, 5]]>
出于某种原因,在单个数组上至少有 2 个维度是非常特别的。