34

我有一个程序,我基本上根据已知情况调整某些事情发生的概率。我的数据文件已保存为pickleDictionary 对象Dictionary.txt

问题是每次我运行程序时,它都会拉入Dictionary.txt,将其转换为字典对象,对其进行编辑和覆盖Dictionary.txt。这是相当大的内存密集型,因为它Dictionary.txt是 123 MB。当我转储时,我得到了MemoryError,当我把它拉进去时,一切似乎都很好。

  • 是否有更好(更有效)的编辑方式?(也许不必每次都覆盖整个文件)

  • 有没有办法可以调用垃圾收集(通过gc模块)?(我已经通过 自动启用它gc.enable()

  • 我知道除了readlines()你可以逐行阅读。当我在程序中已经有一个完全完成的字典对象文件时,有没有办法逐行递增地编辑字典。

  • 还有其他解决方案吗?

感谢您的时间。

4

9 回答 9

21

我遇到了同样的问题。我使用 joblib 并且工作已经完成。如果有人想知道其他可能性。

将模型保存到磁盘

from sklearn.externals import joblib
filename = 'finalized_model.sav'
joblib.dump(model, filename)  

一段时间后...从磁盘加载模型

loaded_model = joblib.load(filename)
result = loaded_model.score(X_test, Y_test) 

print(result)
于 2017-04-26T07:39:19.483 回答
17

我是一个名为的包的作者klepto(也是 的作者dill)。 klepto旨在以非常简单的方式存储和检索对象,并为数据库、内存缓存和磁盘存储提供简单的字典接口。下面,我展示了将大型对象存储在“目录存档”中,这是一个文件系统目录,每个条目一个文件。我选择序列化对象(速度较慢,但​​使用dill,因此您几乎可以存储任何对象),并且我选择了缓存。使用内存缓存使我能够快速访问目录存档,而无需将整个存档保存在内存中。与数据库或文件交互可能会很慢,但与内存交互会很快……您可以根据需要从存档中填充内存缓存。

>>> import klepto
>>> d = klepto.archives.dir_archive('stuff', cached=True, serialized=True)
>>> d
dir_archive('stuff', {}, cached=True)
>>> import numpy
>>> # add three entries to the memory cache
>>> d['big1'] = numpy.arange(1000)
>>> d['big2'] = numpy.arange(1000)
>>> d['big3'] = numpy.arange(1000)
>>> # dump from memory cache to the on-disk archive
>>> d.dump()
>>> # clear the memory cache
>>> d.clear()
>>> d
dir_archive('stuff', {}, cached=True)
>>> # only load one entry to the cache from the archive
>>> d.load('big1')
>>> d['big1'][-3:]
array([997, 998, 999])
>>> 

klepto提供对大量存储的快速灵活的访问,如果存档允许并行访问(例如某些数据库),那么您可以并行读取结果。在不同的并行进程或不同的机器上共享结果也很容易。在这里,我创建了第二个归档实例,指向同一个目录归档。在两个对象之间传递密钥很容易,并且与不同的进程没有什么不同。

>>> f = klepto.archives.dir_archive('stuff', cached=True, serialized=True)
>>> f
dir_archive('stuff', {}, cached=True)
>>> # add some small objects to the first cache  
>>> d['small1'] = lambda x:x**2
>>> d['small2'] = (1,2,3)
>>> # dump the objects to the archive
>>> d.dump()
>>> # load one of the small objects to the second cache
>>> f.load('small2')
>>> f       
dir_archive('stuff', {'small2': (1, 2, 3)}, cached=True)

您还可以选择不同级别的文件压缩,以及是否要对文件进行内存映射。对于文件后端和数据库后端,有很多不同的选项。但是,界面是相同的。

关于您关于垃圾收集和字典部分编辑的其他问题,两者都可以使用klepto,因为您可以从内存缓存中单独加载和删除对象,转储,加载,并与存档后端同步,或任何其他字典方法。

在此处查看更长的教程:https ://github.com/mmckerns/tlkklp

klepto到这里:https : //github.com/uqfoundation

于 2015-07-25T14:27:22.680 回答
5

以上答案都不适合我。我最终使用了 Hickle,它是基于 HDF5 的 pickle 的替代品。不是将其保存到泡菜中,而是将数据保存到 HDF5 文件中。API 对于大多数用例是相同的,并且它具有一些非常酷的功能,例如压缩。

pip install hickle

例子:

# Create a numpy array of data
array_obj = np.ones(32768, dtype='float32')

# Dump to file
hkl.dump(array_obj, 'test.hkl', mode='w')

# Load data
array_hkl = hkl.load('test.hkl')
于 2017-03-13T22:38:06.347 回答
4

我有内存错误并通过使用协议 = 2 解决它:

cPickle.dump(obj, file, protocol=2)

于 2015-05-06T18:28:47.313 回答
2

这个怎么样?

import cPickle as pickle
p = pickle.Pickler(open("temp.p","wb")) 
p.fast = True 
p.dump(d) # d could be your dictionary or any file
于 2013-12-11T14:16:29.130 回答
2

如果您的键和值是字符串,则可以使用 Python 标准库中提供的嵌入式持久键值存储引擎之一。anydbm来自模块文档的示例:

import anydbm

# Open database, creating it if necessary.
db = anydbm.open('cache', 'c')

# Record some values
db['www.python.org'] = 'Python Website'
db['www.cnn.com'] = 'Cable News Network'

# Loop through contents.  Other dictionary methods
# such as .keys(), .values() also work.
for k, v in db.iteritems():
    print k, '\t', v

# Storing a non-string key or value will raise an exception (most
# likely a TypeError).
db['www.yahoo.com'] = 4

# Close when done.
db.close()
于 2013-07-07T19:12:15.007 回答
2

您是否尝试过使用流式泡菜:https ://code.google.com/p/streaming-pickle/

我刚刚通过切换到流式泡菜解决了类似的内存错误。

于 2013-07-11T15:16:55.913 回答
1

我最近遇到了这个问题。在尝试使用 ASCII 和二进制协议 2 的 cpickle 后,我发现我的 sci-kit learn 中的 SVM 训练了 20+ gb 的数据,但由于内存错误而没有进行酸洗。然而,莳萝包似乎解决了这个问题。Dill 不会为字典带来很多改进,但可能有助于流式传输。它旨在通过网络传输腌制字节。

import dill

with open(path,'wb') as fp:
    dill.dump(outpath,fp)
    dill.load(fp)

如果效率是一个问题,请尝试加载/保存到数据库。在这种情况下,您的存储解决方案可能是个问题。123 mb 的 Pandas 应该没问题。但是,如果机器的内存有限,SQL 会提供快速、优化的数据包操作,通常支持多线程。我的 poly kernel svm 保存了。

于 2015-07-24T18:58:53.907 回答
1

这可能看起来微不足道,但如果不是,请尝试使用 64 位 Python。

于 2017-07-16T05:13:08.193 回答