python 中的数据库与平面文件(需要速度但无法放入内存)与生成器一起用于 NN 训练

Posted

技术标签:

【中文标题】python 中的数据库与平面文件(需要速度但无法放入内存)与生成器一起用于 NN 训练【英文标题】:Database vs flat files in python (need speed but can't fit in memory) to be used with generator for NN training 【发布时间】:2018-02-21 01:44:28 【问题描述】:

我正在处理一个相对较大的数据集 (>400 GB) 用于分析目的,但内存有限 (256 GB)。我正在使用python。到目前为止,我一直在数据的一个子集上使用 pandas,但很明显我需要一个允许我访问整个数据集的数据的解决方案。

关于数据的一点点。现在,数据被隔离在一组作为 pandas 数据帧的平面文件中。这些文件由具有 2 个键的列组成。主键,我们称之为“记录”,我希望能够使用它来访问数据,以及一个辅助键,它基本上是主键中的行号。就像我想访问记录“A”中的第 2 行一样。

该数据集用于训练 NN (keras/tf)。所以任务是通过记录将整个集合划分为train/dev/test,然后将数据传递给train/predict generators(我实现了keras.utils.Sequence(),我必须这样做,因为数据是可变长度的批量学习需要填充的序列)。

鉴于我希望尽快将示例传递给 NN,并且我无法将所有示例存储在内存中,我应该使用数据库(mongodb 或 sqlite 还是其他东西?)并根据需要查询示例,还是应该我继续将东西存储在平面文件中并加载/删除它们(并希望 python 垃圾收集器工作)?

另一个复杂因素是大约有 300 万条“记录”。现在,pandas 数据帧将它们存储在大约 10k 的批次中,但随机拆分训练/测试/验证对我有好处,这意味着我确实需要能够访问特定批次中的一些但不是全部记录。在熊猫中这似乎很难(据我所知,我需要读取整个平面文件然后访问特定记录,因为我不知道数据位于文件的哪个块中),另一方面我不要认为生成 300 万个单独的文件也不明智。

更复杂的是,该模型相对简单,由于各种瓶颈,我无法在训练期间使我的计算能力饱和,所以如果我可以将训练流式传输到有助于超参数搜索的几个不同模型,否则我我在浪费周期。

您认为处理我的数据需求的正确(快速、简单)后端是什么?

最好的,

伊利亚

【问题讨论】:

400 GB 中的 300 万条记录意味着每条记录的长度约为 130,000 字节。我严重怀疑您是否会通过神经网络获得任何有用的模型。 每条记录包含多行(150 到 500 之间)。我们对每一行进行预测,但由于一个记录中的行是相关的,我们不想在训练/测试之间混合来自同一记录的行。该模型已经运行良好(比我们基于规则的系统/其他替代方案更好),但我们希望通过提供更多数据来改进它/扩大规模。 另一方面,130kb 是 200x200 像素的 3 通道 int8 图像。这不是图像处理中的非典型尺寸。但是,是的,我们正在处理一个处理短字符序列的小模型。 【参考方案1】:

这是编写自定义生成器,然后使用 Keras 的 model.fit_generator 的一个很好的用例。这是我前几天和 Pandas 一起写的。

请注意,我首先将我的主要数据帧拆分为训练和验证拆分(合并的是我的原始数据帧),但您可能需要在磁盘上移动并在生成器中选择时指定它们

很多重塑和查找/加载都是我的问题的自定义,但你看到了模式。

msk = np.random.rand(len(merged)) < 0.8
train = merged[msk]
valid = merged[~msk]

def train_generator(batch_size):
    sample_rows = train[train['match_id'].isin(npf.id.values)].sample(n=batch_size)
    sample_file_ids = sample_rows.FILE_NAME.tolist()
    sample_data = [np.load('/Users/jeff/spectro/' + x.split(".")[0] + ".npy").T for x in sample_file_ids]
    sample_data = [x.reshape(x.shape[0], x.shape[1]) for x in sample_data]
    sample_data = np.asarray([x[np.random.choice(x.shape[0], 128, replace=False)] for x in sample_data])
    sample_labels = np.asarray([labels.get(x) for x in sample_file_ids])

    while True:
        yield (sample_data, sample_labels)

无论何时调用它,它本质上都会返回 batch_size 样本。 Keras 要求您的生成器返回一个长度为 2 的元组,其中第一个元素是您的预期形状的数据(无论您的神经网络输入形状是什么),并且标签也映射到预期的形状(N_classes 或其他)。

这是另一个关于生成器的相对有用的链接,它可以帮助您确定何时真正用尽了所有示例。我的生成器只是随机采样,但数据集足够大,我不在乎。

https://github.com/keras-team/keras/issues/7729#issuecomment-324627132

别忘了写一个validation_generator,它是从你随机放在其他地方的一些文件或数据帧中读取的,用于验证目的。

最后,这里调用了生成器:

model.fit_generator(train_generator(32), 
                    samples_per_epoch=10000, nb_epoch=20, 
                    validation_data=valid_generator(32), validation_steps=500)

根据 keras 版本,您可能会发现 arg 名称略有变化,但一些搜索应该可以让您快速修复。

【讨论】:

好的,谢谢。如前所述,我已经在使用生成器(建立在 keras.utils.Sequence() 之上)。实际上,我真的很喜欢将数据预分类到训练/有效/测试平面文件中,然后一次读取这些文件的想法。我想我会试试这个!谢谢。 很酷,我认为你不需要任何特殊的后端。

以上是关于python 中的数据库与平面文件(需要速度但无法放入内存)与生成器一起用于 NN 训练的主要内容,如果未能解决你的问题,请参考以下文章

SSIS需要具有2个列标题相同的平面文件输出

Python 中的 MySQL 查询速度较慢,但​​在其他地方速度较快

无法在本机反应中显示平面列表中的所有数据

提高 SceneKit Playground 速度

文本读写与二进制读写 速度对比 Python Matlab

文本读写与二进制读写 速度对比 Python Matlab