2015-06-17 134 views
0

我有一个(非常大)的数据集。大小约为250,000个二进制向量,每个大小为800.
数据集驻留在(压缩表示形式)的(.txt ascii编码)文件中。意思是,该文件中的每一行代表一个矢量的外观,而不是800个字符的零和一个。
例如,假设第i个线在该文件中看起来像这样:Python:序列化/反序列化大量数据

12 14 16 33 93 123 456 133 

这意味着第i个向量是与它的12'th 14'th,16'th的载体, ......第133个指数值为1,其余为零。

该文件的大小略大于30MB。因为我使用这些数据来提供一个神经网络,所以这些数据需要进行一些预处理,以便将其转化为网络所期望的:列表大小为250,000,其中该列表中的每个元素都是20x40矩阵(其中,列表清单)零和一个。
例如,如果我们重新调整的问题4×2,这是最后的名单是什么样子:

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

(只,而不是4×2我有20X40矩阵)。

所以我写了两个函数:load_data() - 解析文件并返回800个二进制列表的列表,以及reshape() - 将列表重塑为20x40矩阵。
不用说,当load_data()reshape()正在运行时,我可怜的笔记本电脑真的很难工作。完成预处理需要大约7-9分钟,而在那段时间内,我可以在我的笔记本电脑上做大麦。即使最小化IDE窗口也是一项非常困难的任务。
由于我使用这些数据来调整神经网络,我发现自己经常会杀死正在运行的进程,重新调整网络并重新开始 - 每次重新启动都会导致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 wise),这将导致一个较小的文件,并将值得我同时?
或者,或者,如果任何人都可以提出更好的方法来加快速度(除了购买更快的计算机),那也会很棒。

p。当涉及到反序列化时,我不关心兼容性问题。我的电脑上唯一一个将这些数据反序列化的地方。

+1

你试过numpy.save吗?有些版本也包括压缩.. http://docs.scipy.org/doc/numpy/reference/generated/numpy.save.html – bsa

+0

虽然与您的问题没有关系......如果您有'800'尺寸特征向量和“唯一”250000个样本,那么在将数据提供给您的神经网络之前,不要忘记尝试对训练集进行维数降低! (如果你还没有这样做,当然);-) – Peque

+0

@Peque,谢谢你的提示。 –

回答

2

如果你要存储一个比特的数据中的每一个值,你会最终有一个25MB的文件;所以你的“压缩”方案实际上是让你的文件更大。你目前的方案的唯一好处是你可以用ascii存储你的数据。

计算:

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

因此,只要手动存储的位模式,阅读他们回来,和你的计算去。

编辑:看起来像阻力最小的路径是使用第三方模块packbits(即您需要下载它)。你必须首先将你的一长串矩阵平铺在一个平面列表中(作为一个迭代器),把它写成一系列位(注意:每32位int可以用32个值“打包” - 不仅仅是您在评论中建议的一个值),然后对输入进行反向转换。列表展平食谱是一打一毛钱(请参阅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×2矩阵的样本阵列,

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

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

+0

这是“阅读他们回来”,我很担心。如果我要将它们保存为位,这意味着数据将不得不转变为网络所期望的;每当从25MB文件加载数据时,整数列表(零和1)列表的列表。每一位都需要转换为四个字节的整数,代表零或一个整数。 –

+0

够公平的。让我仔细研究一下,看看编写一些代码来循环访问数据是多么容易。但是,为什么使用列表而不是numpy数组? – alexis

+0

因为它们更容易工作,至少对我而言。我在序列化之前将所有列表转换为数组,然后在numpy.asarray之前(在reshape()之前...列表没有reshape())。 –