【问题标题】:Shuffle batches fit_generator Keras line-by-line processingShuffle batches fit_generator Keras 逐行处理
【发布时间】:2019-01-05 09:53:51
【问题描述】:

我正在使用 Python Keras 的 fit_generator() 在 30M 行文件(每行是一个样本)上训练深度学习模型,该模型实现了批量训练。由于样本的大小非常不同,出于效率原因,我使用分桶,以避免批次稀疏。

为此,我通过增加行大小对文件进行排序,并编写了一个生成器,它遍历行并在每次处理 n_batch 行时产生一个批处理:

def generate_batches_from_file():
while True:        
    doc_list = []
    with open(path_to_file) as docs: 
        for my_counter,doc in enumerate(docs):
            doc_list.append(doc)            
            if my_counter % batch_size == 0:
                doc_array = truncation_padding_other_stuff(doc_list)
                yield(doc_array)

这样,每批中的样本具有相等或非常相似的大小,并且产生的张量是密集的。

但在深度学习中,最佳实践要求批次不是在每个 epoch 都以相同的顺序传递给模型(出于正则化目的)。

如何在我的设置中打乱批次,因为我是动态生成的,而且我必须逐行处理大型排序输入文件以进行分桶? p>

请注意,我不想在每个批次中打乱样本,我希望 批次 在每个时期以不同的顺序传递。

编辑:我最终将每个批次写入磁盘并拥有一个生成器,它在迭代路径列表之前对其进行洗牌。 GitHub 上的最终代码:https://github.com/Tixierae/deep_learning_NLP/blob/master/HAN/preprocessing.py

【问题讨论】:

  • 为什么不将大型训练文件分成每个存储桶 1 个文件,然后将这些文件中的行打乱?
  • 有趣的问题。您可以将数据拆分为单独的文件,并在每个 epoch 开始时重新排列文件。 tensorflow 数据集 api 还提供了对保存在缓冲区中的数据进行洗牌的可能性:tensorflow.org/api_docs/python/tf/data/Dataset#shuffle
  • 是的,我想我会将每个批次写入磁盘,并有一个生成器在遍历路径列表之前对其进行洗牌。

标签: python keras deep-learning bigdata generator


【解决方案1】:

为简单起见,假设您有 1000 个训练样本(用 n_samples 表示)并且批次大小设置为 10。您已对行进行了排序,因此批次为:(docs[0],...,docs[9]), (docs[10],...,docs[19]),...,(docs[990],...,docs[999])。因此,要以不同的顺序生成批次,您可以轻松地存储每个批次的起始索引,然后在每个 epoch 开始时将它们打乱:

import numpy as np

def generate_batches_from_file():
    indices = np.arange(0, n_samples, batch_size) 
    while True:
        # shuffle the indices each time to generate batches in different order
        np.random.shuffle(indices)
        with open(path_to_file) as docs:
            for idx in indices:
                doc_array = truncation_padding_other_stuff(docs[idx:idx+batch_size])
                yield(doc_array)

【讨论】:

  • 您的解决方案假定输入文件可以加载到 RAM 中,我认为我已经明确说明在我的情况下是不可能的(30M 行,逐行处理)。代替 idxs,我可以将字节偏移位置与 tell 和 seek 一起使用,但这对我不起作用,因为我实际上正在共同处理两个文件:文档和标签。所以有逐行对应,但显然不是逐字节的。我认为对我来说最好的解决方案是将每个批次写入磁盘,并在每个时代开始时以不同的顺序读取文件,正如 cmets 中所建议的那样。
  • @Antoine 只需将您的数据存储在 h5py 文件中,然后调整上述解决方案即可。我认为将它们存储为批次毫无意义且效率极低(假设您想更改批次大小等)。
  • @Antoine 我收回我的话,将批次存储在磁盘上效率极低。我应该与另一种解决方案进行比较来说明这一点。我不知道您的数据的细节(即一行中的最大和最小元素数、批次的预处理等)以便能够将其与基于 h5py 的解决方案进行比较。
猜你喜欢
  • 2021-01-29
  • 2019-09-17
  • 2019-10-07
  • 1970-01-01
  • 2019-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
相关资源
最近更新 更多