Python pkl 文件的内存错误
我正在使用一个Python库来进行深度学习和神经网络的开发。我的电脑有16GB的内存,频率是1866 MHz。最开始我的输入数据文件太大了,所以我把它分成了几个小文件:
-rw-rw-r-- 1 jt jt 1.8G Mar 20 18:09 covarFile.pkl
这导致了以下错误:
Traceback (most recent call last):
File "PYJT2/pp_dbn.py", line 69, in <module>
go()
File "PYJT2/pp_dbn.py", line 32, in go
model = cPickle.load(open(CONTROL_DBN.INPUT, "rb"))
MemoryError
因为这个文件只是一个包含多个numpy数组的numpy数组,所以我可以把它分成多个文件,然后在程序中动态地加载这些小的pickle文件,重新组合成一个大文件。
total 5.2G
drwxrwxr-x 2 jt jt 4.0K Mar 20 18:15 ./
drwxrwxr-x 4 jt jt 4.0K Mar 20 18:15 ../
-rw-rw-r-- 1 jt jt 351M Mar 20 18:09 outfile-0.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:11 outfile-10.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:11 outfile-11.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:12 outfile-12.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:12 outfile-13.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:12 outfile-14.pkl
-rw-rw-r-- 1 jt jt 2.3M Mar 20 18:12 outfile-15.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:09 outfile-1.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:09 outfile-2.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:10 outfile-3.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:10 outfile-4.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:10 outfile-5.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:10 outfile-6.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:11 outfile-7.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:11 outfile-8.pkl
-rw-rw-r-- 1 jt jt 351M Mar 20 18:11 outfile-9.pkl
这个方法效果很好。但我现在的问题是,我有一个非常大的文件,导致了MemoryError
,我不知道该如何进一步拆分。这个文件是一个theano张量变量,表示一个30,000x30,000的浮点数矩阵。我的问题有:
- 有没有办法将数据保存到多个pkl文件中,即使你不确定如何划分底层的数据结构?
- 在我们实验室的服务器上(48GB内存)运行这个会更好吗?还是这个内存错误和架构无关?
- 我现在这个太大的pkl文件是没用的吗?我希望不是,因为它花了我大约8个小时进行神经网络训练。
- 除了使用数据库,还有其他解决方案吗?如果可能的话,我非常希望不使用数据库,因为我已经不得不把软件转移到多个服务器上,其中很多我没有管理员权限,安装其他东西非常麻烦。
1 个回答
首先,pkl格式并不适合保存二进制数据,而且在内存使用上也不太友好。因为在写入磁盘之前,它需要先把所有数据复制到内存中,这样就会导致内存使用量翻倍!你可以使用numpy.save和numpy.load来存储ndarray,这样就不会出现内存翻倍的问题。
关于Theano变量,我猜你在使用Theano的共享变量。默认情况下,当你通过get_value()
获取它时,会复制数据。你可以使用get_value(borrow=True)
来避免复制。
这两种方法结合起来,可以将内存使用量降低三倍。如果这还不够,或者你不想自己处理多个文件,我建议你使用pytables:http://www.pytables.org/。它可以让你在一个文件中存储一个比可用内存更大的ndarray,但它会提供一个类似于ndarray的对象,你可以像操作ndarray一样操作它。