从多个文件读取 TensorFlow 数据集时结合 flat_map 和 zip:Are files being being second time from disk?
Combining flat_map and zip when reading TensorFlow Dataset from multiple files: Are files being read from disk a second time?
跟进 ,我正在使用 tf.data.Dataset.zip(dataset, dataset.skip(1))
生成连续项目的数据集。我这样做是因为我希望我的 model_fn 一次被馈送两个连续的帧,从中计算差异。
当从磁盘上的多个 tfrecords
文件中读取时,我遇到了 运行 问题,即在我当前的实现中有时无法维护数据集中记录的正确顺序。简化的问题可以重现为:
file1.txt(file2.txt 看起来与 f2_i01,1
等相同)
f1_i01,1
f1_i02,2
f1_i03,3
f1_i04,4
f1_i05,5
我的代码
import tensorflow as tf
COLUMNS = ['image', 'label']
FIELD_DEFAULTS = [['empty'], [0]]
def _line_parser(line):
fields = tf.decode_csv(line, FIELD_DEFAULTS)
data = dict(zip(COLUMNS, fields))
label = data.pop('label')
return data, label
filenames = ['file1.txt', 'file2.txt']
files = tf.data.Dataset.list_files(filenames)
dataset = files.flat_map(
lambda filename:
tf.data.TextLineDataset(filename)
.map(_line_parser))
dataset = tf.data.Dataset.zip((dataset, dataset.skip(1)))
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()
init_op = iterator.initializer
with tf.Session() as sess:
sess.run(init_op)
for i in range(5):
print(sess.run(next_element))
如果我执行这段代码,我会得到以下结果之一,似乎是随机的:
选项 1.1:维持秩序(file1.txt 先读)
(({'image': b'f1_i01'}, 1), ({'image': b'f1_i02'}, 2))
(({'image': b'f1_i02'}, 2), ({'image': b'f1_i03'}, 3))
(({'image': b'f1_i03'}, 3), ({'image': b'f1_i04'}, 4))
(({'image': b'f1_i04'}, 4), ({'image': b'f1_i05'}, 5))
(({'image': b'f1_i05'}, 5), ({'image': b'f2_i01'}, 1))
选项 1.2:维持秩序(file2.txt 先读)
(({'image': b'f2_i01'}, 1), ({'image': b'f2_i02'}, 2))
(({'image': b'f2_i02'}, 2), ({'image': b'f2_i03'}, 3))
(({'image': b'f2_i03'}, 3), ({'image': b'f2_i04'}, 4))
(({'image': b'f2_i04'}, 4), ({'image': b'f2_i05'}, 5))
(({'image': b'f2_i05'}, 5), ({'image': b'f1_i01'}, 1))
选项 2.1:未维护订单(file1.txt 先阅读)
(({'image': b'f1_i01'}, 1), ({'image': b'f2_i02'}, 2))
(({'image': b'f1_i02'}, 2), ({'image': b'f2_i03'}, 3))
(({'image': b'f1_i03'}, 3), ({'image': b'f2_i04'}, 4))
(({'image': b'f1_i04'}, 4), ({'image': b'f2_i05'}, 5))
(({'image': b'f1_i05'}, 5), ({'image': b'f1_i01'}, 1))
选项 2.2:未维护订单(file2.txt 先阅读)
(({'image': b'f2_i01'}, 1), ({'image': b'f1_i02'}, 2))
(({'image': b'f2_i02'}, 2), ({'image': b'f1_i03'}, 3))
(({'image': b'f2_i03'}, 3), ({'image': b'f1_i04'}, 4))
(({'image': b'f2_i04'}, 4), ({'image': b'f1_i05'}, 5))
(({'image': b'f2_i05'}, 5), ({'image': b'f2_i01'}, 1))
在我看来,zip 函数会导致数据集从磁盘中独立读取第二次。有什么方法可以让我始终如一地实现选项 1?
我仍然认为这令人困惑,因为我不希望 zip 导致文件被第二次读取。
然而,就我而言,事实证明我需要做的就是将 shuffle=False
参数添加到 tf.data.Dataset.list_files
以始终如一地实现选项 1。
跟进 tf.data.Dataset.zip(dataset, dataset.skip(1))
生成连续项目的数据集。我这样做是因为我希望我的 model_fn 一次被馈送两个连续的帧,从中计算差异。
当从磁盘上的多个 tfrecords
文件中读取时,我遇到了 运行 问题,即在我当前的实现中有时无法维护数据集中记录的正确顺序。简化的问题可以重现为:
file1.txt(file2.txt 看起来与 f2_i01,1
等相同)
f1_i01,1
f1_i02,2
f1_i03,3
f1_i04,4
f1_i05,5
我的代码
import tensorflow as tf
COLUMNS = ['image', 'label']
FIELD_DEFAULTS = [['empty'], [0]]
def _line_parser(line):
fields = tf.decode_csv(line, FIELD_DEFAULTS)
data = dict(zip(COLUMNS, fields))
label = data.pop('label')
return data, label
filenames = ['file1.txt', 'file2.txt']
files = tf.data.Dataset.list_files(filenames)
dataset = files.flat_map(
lambda filename:
tf.data.TextLineDataset(filename)
.map(_line_parser))
dataset = tf.data.Dataset.zip((dataset, dataset.skip(1)))
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()
init_op = iterator.initializer
with tf.Session() as sess:
sess.run(init_op)
for i in range(5):
print(sess.run(next_element))
如果我执行这段代码,我会得到以下结果之一,似乎是随机的:
选项 1.1:维持秩序(file1.txt 先读)
(({'image': b'f1_i01'}, 1), ({'image': b'f1_i02'}, 2))
(({'image': b'f1_i02'}, 2), ({'image': b'f1_i03'}, 3))
(({'image': b'f1_i03'}, 3), ({'image': b'f1_i04'}, 4))
(({'image': b'f1_i04'}, 4), ({'image': b'f1_i05'}, 5))
(({'image': b'f1_i05'}, 5), ({'image': b'f2_i01'}, 1))
选项 1.2:维持秩序(file2.txt 先读)
(({'image': b'f2_i01'}, 1), ({'image': b'f2_i02'}, 2))
(({'image': b'f2_i02'}, 2), ({'image': b'f2_i03'}, 3))
(({'image': b'f2_i03'}, 3), ({'image': b'f2_i04'}, 4))
(({'image': b'f2_i04'}, 4), ({'image': b'f2_i05'}, 5))
(({'image': b'f2_i05'}, 5), ({'image': b'f1_i01'}, 1))
选项 2.1:未维护订单(file1.txt 先阅读)
(({'image': b'f1_i01'}, 1), ({'image': b'f2_i02'}, 2))
(({'image': b'f1_i02'}, 2), ({'image': b'f2_i03'}, 3))
(({'image': b'f1_i03'}, 3), ({'image': b'f2_i04'}, 4))
(({'image': b'f1_i04'}, 4), ({'image': b'f2_i05'}, 5))
(({'image': b'f1_i05'}, 5), ({'image': b'f1_i01'}, 1))
选项 2.2:未维护订单(file2.txt 先阅读)
(({'image': b'f2_i01'}, 1), ({'image': b'f1_i02'}, 2))
(({'image': b'f2_i02'}, 2), ({'image': b'f1_i03'}, 3))
(({'image': b'f2_i03'}, 3), ({'image': b'f1_i04'}, 4))
(({'image': b'f2_i04'}, 4), ({'image': b'f1_i05'}, 5))
(({'image': b'f2_i05'}, 5), ({'image': b'f2_i01'}, 1))
在我看来,zip 函数会导致数据集从磁盘中独立读取第二次。有什么方法可以让我始终如一地实现选项 1?
我仍然认为这令人困惑,因为我不希望 zip 导致文件被第二次读取。
然而,就我而言,事实证明我需要做的就是将 shuffle=False
参数添加到 tf.data.Dataset.list_files
以始终如一地实现选项 1。