Python:序列化/反序列化大量数据

时间:2015-06-17 13:29:28

标签: python serialization

我有一个(非常大的)数据集。大约为200,000个二进制向量的大小为800.
数据集位于“压缩表示”中的(.txt ascii编码)文件中。意思是,该文件中的每一行代表一个矢量的外观,而不是800个字符的零和一个 例如,假设该文件中的第i行如下所示:

12 14 16 33 93 123 456 133

这意味着第i个向量是一个向量,其第12'第14',第16,......第133'索引保持值1,其余为零。

文件的大小略大于30MB。

现在,由于我使用这些数据来提供神经网络,这个数据需要一些预处理,以便将其转换为网络所需的内容:大小为250,000的列表,其中该列表中的每个元素都是20x40矩阵(列表列表)零和一 例如,如果我们将问题重新缩放到4x2,这就是最终列表的样子:

[[[1,0],[1,1],[0,0],[1,0]], [[0,0],[0,1],[1,0],[1,0]], ..., [[1,1],[0,1],[0,0],[1,1]]]

(仅代替4x2我有20x40矩阵)。

所以我写了两个函数:load_data() - 解析文件并返回800个二进制列表的列表,reshape() - 将列表重新整形为20x40矩阵。
毋庸置疑,当load_data()reshape()正在运行时,我糟糕的笔记本电脑非常难用。完成预处理大约需要7到9分钟,而在那段时间我可以在我的笔记本电脑上做任何其他事情。即使最小化IDE窗口也是一项非常困难的任务 由于我使用这些数据来调整神经网络,我发现自己经常杀死正在运行的进程,重新调整网络,然后重新开始 - 每次重启都会导致调用load_data()后跟{{1} }。
所以,我决定快速完成这个加载数据的痛苦过程 - >转换为二元向量 - >重塑它。
我想从文件中加载数据,转换为二进制向量,重新整形并将其序列化为文件reshape()
现在,每当我需要提供网络时,我都可以从my_input反序列化数据,并为我节省大量时间。
我就这样做了:

my_input

问题在于:
结果文件很大;尺寸为1.7GB,看起来游戏不值得用蜡烛(我希望我使用它正确),因为加载它需要太多时间(没有测量多少,我只是试图加载它,并且9-10分钟后,我放弃并杀死了这个过程)。

为什么生成的文件比原始文件大得多(我希望它更大,但不是那么多)?
有没有另一种方法来编码数据(顺序化/反序列化),这将导致一个较小的文件,并值得我的时间?
或者,或者,如果任何人都可以提出一个更好的方法来加快速度(除了购买更快的计算机),这也会很棒。

p.s在进行反序列化时,我不关心兼容性问题。这个数据将被反序列化的唯一地方是在我的计算机上。

1 个答案:

答案 0 :(得分:2)

如果您要为数据中的每个值存储一点,那么最终会得到一个25MB的文件;所以你的“压缩”方案实际上使你的文件更大。您当前方案的唯一优势是您可以将数据存储在ascii中。

计算:

250.000 * 800 bits = 250.000 * 100 bytes = 25.000.000 bytes = 25 MB

因此,只需手动存储位模式,将其重新读入并继续计算。

修改:看起来阻力最小的路径是使用第三方模块packbits(即您需要下载它)。您必须首先将您的长矩阵列表平移到一个平面列表中(作为迭代器),将其写为一系列位(注意:每个32位int可以“打包”32个值 - 而不仅仅是您在评论中建议的一个值),然后对输入进行反向转换。 List-flattening食谱只有十几个(参见here选项),但这里有一个补充的unflattening代码。

from itertools import zip_longest    
def chunks(iterable, size):
    "chunks(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g', 0, 0)"
    return zip_longest(*[iter(iterable)]*size, fillvalue=0)

def flatten(data):
    """Convert a list of N x M matrices into a flat iterator"""
    return ( v for matrix in data for row in matrix for v in row )

def unflatten(data, n, m):
    """Convert a flat sequence (of ints) into a list of `n` by `m` matrices"""
    msize = n * m
    for chunk in chunks(data, msize):
        yield [ chunk[i:i+m] for i in range(0, msize, m) ]

如果sampledata是4 x 2矩阵的样本数组,

rt = list(unflatten(flatten(sampledata), 4, 2)) 

是一个具有相同结构和值的列表(但是元组而不是行数组)。你可以填写其余的吗?