Python: Serializing/de-serializing 海量数据

Python: Serializing/de-serializing huge amount of data

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

12 14 16 33 93 123 456 133

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

文件大小略大于 30MB。

现在,由于我使用这些数据来为神经网络提供数据,因此需要对这些数据进行一些预处理,以便将其转换为网络所期望的:大小为 250,000 的列表,其中该列表中的每个元素都是一个 20x40 矩阵(列表列表)0 和 1。
例如,如果我们将问题重新缩放为 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]]]

(我只有 20x40 矩阵而不是 4x2)。

所以我写了两个函数:load_data() - 解析文件和 returns 800 个二进制列表的列表,以及 reshape() - 将列表重塑为 20x40 矩阵。
不用说,当 load_data()reshape() 为 运行 时,我可怜的笔记本电脑工作起来真的很辛苦。完成预处理大约需要 7-9 分钟,而在这段时间里,我可以用大麦在我的笔记本电脑上做任何其他事情。即使最小化 IDE window 也是一项极其困难的任务。
由于我使用这些数据来调整神经网络,我发现自己经常终止 运行 进程,重新调整网络,然后重新开始——每次重新启动都会调用 load_data(),然后调用 load_data() reshape().
因此,我决定绕过加载数据这一痛苦的过程 --> 转换为二进制向量 --> 重塑它。
我想从文件中加载数据,转换为二进制向量,对其进行整形并将其序列化为文件 my_input.
现在,每当我需要为网络提供数据时,我只需反序列化来自 my_input 的数据,就可以节省很多时间。
我是这样做的:

input_file=open('my_input', 'wb')

print 'loading data from file...'
input_data=load_data()  # this will load the data from file and will re-encode it to binary vectors

print 'reshaping...'
reshaped_input=reshape(input_data)

print 'writing to file...'
cPickle.dump(reshaped_input, input_file, HIGHEST_PROTOCOL)
input_file.close()

问题是这样的:
生成的文件很大; 1.7GB大小,感觉游戏不值一提(希望我用对了),因为加载它太费时间了(没测多少,我只是试着加载了,而且9-10 分钟后,我放弃并终止了进程)。

为什么生成的文件比原始文件大这么多(我希望它更大,但没有那么大)?
是否有另一种编码数据的方法(serialize/de-serialize 明智),这将导致文件更小,并且值得我花时间?
或者,如果有人可以建议一种更好的方法来加快速度(除了购买更快的计算机之外),那也很棒。

p.s 我不关心反序列化的兼容性问题。此数据将被反序列化的唯一位置是在我的计算机上。

如果您要为数据中的每个值存储一点,您最终会得到一个 25MB 的文件;所以你的 "compression" 方案实际上让你的文件变大了。当前方案的唯一优点是您可以将数据存储在 ascii 中。

计算:

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

所以只需手动存储位模式,读回它们并继续计算。

编辑: 看起来阻力最小的路径是使用第三方模块 packbits (i.e. you need to download it). You must first flatten your long list of matrices into a flat list on the fly (as an iterator), write it out as a sequence of bits (note: every 32-bit int can be "packed" with 32 values-- not just one value as you suggest in the comments), then do the reverse conversion on input. List-flattening recipes are a dime a dozen (see here 进行选择),但这里有一个带有补充的展开代码。

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)) 

是具有相同结构和值的列表(但元组而不是行数组)。剩下的可以填吗?