我为相当大的数据集创建径向基函数插值模型。主要调用`scipy.interpolate.Rbf(,)需要大约一分钟和14 GB的RAM。 由于并非每台应该运行的机器都能够执行此操作,并且由于程序将经常在同一数据集上运行,因此我想将结果挑选到文件中。这是一个简化的例子:
import scipy.interpolate as inter
import numpy as np
import cPickle
x = np.array([[1,2,3],[3,4,5],[7,8,9],[1,5,9]])
y = np.array([1,2,3,4])
rbfi = inter.Rbf(x[:,0], x[:,1], x[:,2], y)
RBFfile = open('picklefile','wb')
RBFpickler = cPickle.Pickler(RBFfile,protocol=2)
RBFpickler.dump(rbfi)
RBFfile.close()
RBFpickler.dump()
电话会导致can't pickle <type 'instancemethod'>
错误。
据我所知,这意味着那里有一个方法(好吧,rbfi()
可以调用),而且由于某种原因我不能理解它。
是否有人知道以其他方式腌制此方法或以其他方式保存inter.Rbf()
来电的结果?
有一些形状(nd,n)和(n,n)的数组(rbfi.A
,rbfi.xi
,rbfi.di
...),我假设存储所有有趣的信息。我想我可以腌制那些阵列,但是我不知道怎么能把对象再次放在一起......
修改 附加约束:我不允许在系统上安装其他库。我可以包含它们的唯一方法是,如果它们是纯Python,我可以将它们包含在脚本中而无需编译任何内容。
答案 0 :(得分:2)
我使用dill
来序列化结果......或者如果你想要一个缓存函数,你可以使用klepto
来缓存函数调用,这样你就可以最小化函数的重新评估。 / p>
Python 2.7.6 (default, Nov 12 2013, 13:26:39)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import scipy.interpolate as inter
>>> import numpy as np
>>> import dill
>>> import klepto
>>>
>>> x = np.array([[1,2,3],[3,4,5],[7,8,9],[1,5,9]])
>>> y = np.array([1,2,3,4])
>>>
>>> # build an on-disk archive for numpy arrays,
>>> # with a dictionary-style interface
>>> p = klepto.archives.dir_archive(serialized=True, fast=True)
>>> # add a caching algorithm, so when threshold is hit,
>>> # memory is dumped to disk
>>> c = klepto.safe.lru_cache(cache=p)
>>> # decorate the target function with the cache
>>> c(inter.Rbf)
<function Rbf at 0x104248668>
>>> rbf = _
>>>
>>> # 'rbf' is now cached, so all repeat calls are looked up
>>> # from disk or memory
>>> d = rbf(x[:,0], x[:,1], x[:,2], y)
>>> d
<scipy.interpolate.rbf.Rbf object at 0x1042454d0>
>>> d.A
array([[ 1. , 1.22905719, 2.36542472, 1.70724365],
[ 1.22905719, 1. , 1.74422655, 1.37605151],
[ 2.36542472, 1.74422655, 1. , 1.70724365],
[ 1.70724365, 1.37605151, 1.70724365, 1. ]])
>>>
...继续
>>> # the cache is serializing the result object behind the scenes
>>> # it also works if we directly pickle and unpickle it
>>> _d = dill.loads(dill.dumps(d))
>>> _d
<scipy.interpolate.rbf.Rbf object at 0x104245510>
>>> _d.A
array([[ 1. , 1.22905719, 2.36542472, 1.70724365],
[ 1.22905719, 1. , 1.74422655, 1.37605151],
[ 2.36542472, 1.74422655, 1. , 1.70724365],
[ 1.70724365, 1.37605151, 1.70724365, 1. ]])
>>>
在此处获取klepto
和dill
:https://github.com/uqfoundation
答案 1 :(得分:0)
好吧,Mike的解决方案似乎很好,但我在此期间找到了另一个:
Rbf对象只有两个部分无法直接进行腌制,并且很容易从头开始重新创建。因此,我的代码现在只保存数据部分:
import scipy.interpolate as inter
import numpy as np
import cPickle
x = np.array([[1,2,3],[3,4,5],[7,8,9],[1,5,9]])
y = np.array([1,2,3,4])
rbfi = inter.Rbf(x[:,0], x[:,1], x[:,2], y)
RBFfile = open('picklefile','wb')
RBFpickler = cPickle.Pickler(RBFfile,protocol=2)
# RBF can't be pickled directly, so save everything required for reconstruction
RBFdict = {}
for key in rbfi.__dict__.keys():
if key != '_function' and key!= 'norm':
RBFdict[key] = rbfi.__getattribute__(key)
RBFpickler.dump(RBFdict)
RBFfile.close()
这给了我一个包含对象中存储的所有信息的文件。 rbfi._function()
和rbfi.norm
未保存。幸运的是,只需初始化任意(任意简单的)Rbf对象,就可以从头开始重新创建它们:
## create a bare-bones RBF object ##
rbfi = inter.Rbf(np.array([1,2,3]), np.array([10,20,30]), \
np.array([1,2,3]), function = RBFdict['function'] )
然后用保存的数据替换该对象的数据部分:
RBFfile = open('picklefile','rb')
RBFunpickler = cPickle.Unpickler(RBFfile)
RBFdict = RBFunpickler.load()
RBFfile.close()
## replace rbfi's contents with what was saved ##
for key,value in RBFdict.iteritems():
rbfi.__setattr__(key, value)
>>> rbfi(2,3,4)
array(1.4600661386382146)
显然甚至不需要为新Rbf对象提供与原始对象相同数量的维度,因为所有这些都将被覆盖。
也就是说,迈克的解决方案可能是更普遍适用的解决方案,而这个解决方案更加平台无关。我在平台之间移动酸洗Kriging模型时遇到了问题,但这种RBF模型的方法看起来更加强大 - 我还没有对它进行过多次测试,所以没有保证。