Ste*_* W. 6 tensorflow tensorflow-datasets tensorflow-estimator
我最近改变了我的建模框架以使用自定义Tensorflow Estimators和Datasets,并且对这个工作流程非常满意.
但是,我刚刚注意到我的dataset_input_fn如何从tfrecords加载数据的问题.我的输入函数是在Tensorflow文档中的示例之后建模的.当我有更多的例子而不是我可以适应RAM时,会出现问题.如果我有1e6个示例,并将我的shuffle buffer_size设置为1e5,则选择1e5示例的子集一次,随机,然后迭代.这意味着我的模型仅在我的整个数据集的10%上进行训练.设置此行为的代码完全来自Tensorflow文档示例代码:
dataset = dataset.map(parser)
dataset = dataset.shuffle(buffer_size=10000)
dataset = dataset.batch(32)
dataset = dataset.repeat(num_epochs)
iterator = dataset.make_one_shot_iterator()
Run Code Online (Sandbox Code Playgroud)
我的问题:当我训练时,是否有可能在最初的1e5之外用新的例子填充shuffle缓冲区?one_shot_iterator是否支持此类功能?我需要使用可初始化的迭代器吗?
谢谢!
我发现目前看来是可行的解决方法。通过一些实验,我了解到在实例化TFRecordDataset时,
filenames = ["file1.tfrecord", ..., "filen.tfrecord"]
dataset = tf.data.TFRecordDataset(filenames)
Run Code Online (Sandbox Code Playgroud)
并设置随机播放缓冲区:
dataset = dataset.shuffle(buffer_size=10000)
Run Code Online (Sandbox Code Playgroud)
缓冲区仅填充有需要的许多tf记录中的前10000个示例。例如,就我而言,我有〜300个tfrecord文件,每个文件包含4096个示例。经检查,我的混洗缓冲区似乎仅由文件名列表中前3个tf记录中的示例组成。由于我的文件名列表是静态的,因此这意味着仅对我的前3个tfrecords进行模型训练!
我目前的解决方法非常简单。在我的训练循环中,我已经在Estimator.train和Estimator.evaluate之间交替,并且我注意到,每次调用Estimator.train时,都会重新填充随机缓冲。然后,我的解决方案是每次调用input_fn时都对文件名进行混洗。这不是一个非常优雅的解决方案,但是确实达到了允许我遍历所有tfrecords的预期效果。
#My Crappy Fix: shuffle file names in input_fn
np.random.shuffle(filenames)
dataset = tf.data.TFRecordDataset(filenames)
Run Code Online (Sandbox Code Playgroud)
这个解决方案的烦人之处(除了它的模糊性)是我的迷你批处理不是“全局随机的”。相反,它们是从tf记录的一小部分中选择的,并且每个训练/评估周期仅使用该子集。减轻这种情况的一种方法是增加随机播放缓冲区的大小或减小tfrecord的大小,我可能会同时做这两项。最后,我认为值得注意的是
shuffle_buffer_size < (tf_record_size + minibatch_size)
Run Code Online (Sandbox Code Playgroud)
然后,据我所知,我的TFRecordDataset将从一个tfrecord文件中提取!
最后,我认为相关的张量流文档不能很好地传达这些复杂性。该文档暗示了能够对不适合内存但没有提供太多细节的大型数据集进行训练的能力。TF编写者在编写此代码时似乎不太可能想到我的hacky策略,因此我仍然很想知道是否有更好的方法。
| 归档时间: |
|
| 查看次数: |
759 次 |
| 最近记录: |