tf.data:"mixing" 批量大小?
tf.data: "mixing" batch sizes?
我正在使用数据集 API 在 TF 1.4.1 中工作。我有两组输入数据,x
和 y
,每组都有相同数量的元素。对于 x
和 y
,我有大型上下文数组 context_x
和 context_y
,比如说大小为 10000×10。
每个输入批次的上下文都不同(尽管批次中的每个样本都相同),因此 link 在输入管道中将它们放在一起是有意义的。我无法将所有批次的所有上下文数组存储在图中,然后从那里读取,因为就所需的内存而言,将所有这些静态地存储在图中是令人望而却步的。我可以做的是为当前批次输入单个上下文数组,我想将其包含在我的输入管道中。
另请注意,在我的图表中,上下文数组经过一些卷积层,这有效地将其减小到可管理的大小,比原来的小得多,因此我 tile
它具有特定于批次中的样品并继续我的其余任务。因此,即使我最终需要复制到批量大小,我也可以在从上下文数组中提取的特征向量上执行此操作,该数组的大小要小得多。
我正在使用以下类型的代码来构建一个数据集,该数据集应将一批 x
和 y
样本连同它们的上下文一起提供给我的图表:
import tensorflow as tf
import numpy as np
# Small data input
x = np.arange(100)
y = np.arange(100)
# Large context array for both x and y
context_x = np.random.rand(1, 10000, 10)
context_y = np.random.rand(1, 10000, 10)
# Create datasets
dataset_x = tf.data.Dataset.from_tensor_slices(x)
dataset_y = tf.data.Dataset.from_tensor_slices(y)
# same context should be repeated for every data item
dataset_context_x = tf.data.Dataset.from_tensor_slices(context_x)
dataset_context_x = dataset_context_x.repeat()
dataset_context_y = tf.data.Dataset.from_tensor_slices(context_y)
dataset_context_y = dataset_context_y.repeat()
dataset = tf.data.Dataset.zip((dataset_x, dataset_context_x))
dataset = dataset.concatenate( tf.data.Dataset.zip((dataset_y, dataset_context_y)) )
dataset = dataset.batch(32)
iterator = dataset.make_initializable_iterator()
(x_iter, context_iter) = iterator.get_next()
with tf.Session() as sess:
sess.run(iterator.initializer)
while True:
try:
xi, ci = sess.run([x_iter, context_iter])
print(xi.shape, ci.shape)
except tf.errors.OutOfRangeError:
break
输出表明每个样本都复制了大型上下文数组 x[i]
和 y[i]
:
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((8,), (8, 10000, 10))
这会浪费大量内存,因为所有 32 个 10000
-by-10
切片都是相同的!我应该如何使用数据集 API 以避免不必要的上下文数组复制,并且我会为每个批次获得诸如 ((32,), (1, 10000, 10))
的输出?您可以将其视为混合批量大小,x
和 y
为 32,而上下文数组为 1。
好的,这是我的初步解决方案。请注意,我假设您的数据以某种方式排序,因此当您构建 x
的批次时,您阅读的下一个 context_x
始终与当前批次相关。
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1' # running on CPU
import tensorflow as tf
import numpy as np
# Small data input
x = np.arange(100)
y = np.arange(100)
# Large context array for both x and y
context_x = np.random.rand(1, 10000, 10)
context_y = np.random.rand(1, 10000, 10)
# Create datasets
dataset_x = tf.data.Dataset.from_tensor_slices(x).batch(32)
dataset_y = tf.data.Dataset.from_tensor_slices(y).batch(32)
# same context should be repeated for every data item
dataset_context_x = tf.data.Dataset.from_tensor_slices(context_x)
dataset_context_x = dataset_context_x.repeat() # here just for demonstration purposes. Ideally you'll have enough context data to match the batches
dataset_context_y = tf.data.Dataset.from_tensor_slices(context_y)
dataset_context_y = dataset_context_y.repeat() # here just for demonstration purposes. Ideally you'll have enough context data to match the batches
dataset = tf.data.Dataset.zip((dataset_x, dataset_context_x))
dataset = dataset.concatenate( tf.data.Dataset.zip((dataset_y, dataset_context_y)) ) # This stacks all 'x' samples on top of all 'y' samples. Is this really what you wanted?
iterator = dataset.make_initializable_iterator()
(x_iter, context_iter) = iterator.get_next()
with tf.Session() as sess:
sess.run(iterator.initializer)
while True:
try:
xi, ci = sess.run([x_iter, context_iter])
print(xi.shape, ci.shape)
except tf.errors.OutOfRangeError:
break
在您的实施中,删除 dataset_context_* = dataset_context_*.repeat()
行。
与您的管道的主要区别在于我在 x
之前 将其与上下文一起压缩,这样上下文就不会被复制。然而,这要求您在处理数据加载时要小心(因此我上面的假设)。
我正在使用数据集 API 在 TF 1.4.1 中工作。我有两组输入数据,x
和 y
,每组都有相同数量的元素。对于 x
和 y
,我有大型上下文数组 context_x
和 context_y
,比如说大小为 10000×10。
每个输入批次的上下文都不同(尽管批次中的每个样本都相同),因此 link 在输入管道中将它们放在一起是有意义的。我无法将所有批次的所有上下文数组存储在图中,然后从那里读取,因为就所需的内存而言,将所有这些静态地存储在图中是令人望而却步的。我可以做的是为当前批次输入单个上下文数组,我想将其包含在我的输入管道中。
另请注意,在我的图表中,上下文数组经过一些卷积层,这有效地将其减小到可管理的大小,比原来的小得多,因此我 tile
它具有特定于批次中的样品并继续我的其余任务。因此,即使我最终需要复制到批量大小,我也可以在从上下文数组中提取的特征向量上执行此操作,该数组的大小要小得多。
我正在使用以下类型的代码来构建一个数据集,该数据集应将一批 x
和 y
样本连同它们的上下文一起提供给我的图表:
import tensorflow as tf
import numpy as np
# Small data input
x = np.arange(100)
y = np.arange(100)
# Large context array for both x and y
context_x = np.random.rand(1, 10000, 10)
context_y = np.random.rand(1, 10000, 10)
# Create datasets
dataset_x = tf.data.Dataset.from_tensor_slices(x)
dataset_y = tf.data.Dataset.from_tensor_slices(y)
# same context should be repeated for every data item
dataset_context_x = tf.data.Dataset.from_tensor_slices(context_x)
dataset_context_x = dataset_context_x.repeat()
dataset_context_y = tf.data.Dataset.from_tensor_slices(context_y)
dataset_context_y = dataset_context_y.repeat()
dataset = tf.data.Dataset.zip((dataset_x, dataset_context_x))
dataset = dataset.concatenate( tf.data.Dataset.zip((dataset_y, dataset_context_y)) )
dataset = dataset.batch(32)
iterator = dataset.make_initializable_iterator()
(x_iter, context_iter) = iterator.get_next()
with tf.Session() as sess:
sess.run(iterator.initializer)
while True:
try:
xi, ci = sess.run([x_iter, context_iter])
print(xi.shape, ci.shape)
except tf.errors.OutOfRangeError:
break
输出表明每个样本都复制了大型上下文数组 x[i]
和 y[i]
:
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((32,), (32, 10000, 10))
((8,), (8, 10000, 10))
这会浪费大量内存,因为所有 32 个 10000
-by-10
切片都是相同的!我应该如何使用数据集 API 以避免不必要的上下文数组复制,并且我会为每个批次获得诸如 ((32,), (1, 10000, 10))
的输出?您可以将其视为混合批量大小,x
和 y
为 32,而上下文数组为 1。
好的,这是我的初步解决方案。请注意,我假设您的数据以某种方式排序,因此当您构建 x
的批次时,您阅读的下一个 context_x
始终与当前批次相关。
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1' # running on CPU
import tensorflow as tf
import numpy as np
# Small data input
x = np.arange(100)
y = np.arange(100)
# Large context array for both x and y
context_x = np.random.rand(1, 10000, 10)
context_y = np.random.rand(1, 10000, 10)
# Create datasets
dataset_x = tf.data.Dataset.from_tensor_slices(x).batch(32)
dataset_y = tf.data.Dataset.from_tensor_slices(y).batch(32)
# same context should be repeated for every data item
dataset_context_x = tf.data.Dataset.from_tensor_slices(context_x)
dataset_context_x = dataset_context_x.repeat() # here just for demonstration purposes. Ideally you'll have enough context data to match the batches
dataset_context_y = tf.data.Dataset.from_tensor_slices(context_y)
dataset_context_y = dataset_context_y.repeat() # here just for demonstration purposes. Ideally you'll have enough context data to match the batches
dataset = tf.data.Dataset.zip((dataset_x, dataset_context_x))
dataset = dataset.concatenate( tf.data.Dataset.zip((dataset_y, dataset_context_y)) ) # This stacks all 'x' samples on top of all 'y' samples. Is this really what you wanted?
iterator = dataset.make_initializable_iterator()
(x_iter, context_iter) = iterator.get_next()
with tf.Session() as sess:
sess.run(iterator.initializer)
while True:
try:
xi, ci = sess.run([x_iter, context_iter])
print(xi.shape, ci.shape)
except tf.errors.OutOfRangeError:
break
在您的实施中,删除 dataset_context_* = dataset_context_*.repeat()
行。
与您的管道的主要区别在于我在 x
之前 将其与上下文一起压缩,这样上下文就不会被复制。然而,这要求您在处理数据加载时要小心(因此我上面的假设)。