[英]pickle cython class
我必须保存并加载一个cython类实例。 我的cython类是以及几种方法:
import numpy as np
cimport numpy as np
cimport cython
cdef class Perceptron_avg_my:
cdef int wlen,freePos
cdef np.ndarray w,wtot,wac,wtotc #np.ndarray[np.int32_t]
cdef np.ndarray wmean #np.ndarray[np.float32_t]
cdef public dict fpos
def __cinit__(self,np.int64_t wlen=4*10**7):
self.fpos= dict()
self.freePos=1
self.wlen=wlen
self.w=np.zeros(wlen,np.int32)
self.wtot=np.zeros(wlen,np.int32)
self.wac=np.zeros(wlen,np.int32)
self.wtotc=np.zeros(wlen,np.int32)
self.wmean=np.zeros(wlen,np.float32)
cpdef evaluate_noavg(self,list f):
cdef np.ndarray[np.int32_t] w = self.w
cdef dict fpos = self.fpos
cdef bytes ff
cdef int i
cdef long int score=0
for ff in f:
i=fpos.get(ff,0)
if i != 0:
score += w[i]
return score
我在考虑使用cPickle模块。 我明白我必须实现一个__reduce __(自我)方法但是我有一些问题需要找到一个例子并且很好地理解文档
我试图将这样的东西添加到Perceptron_avg_my但不起作用:
def rebuild(self,l):
self.fpos=l[0]
self.freePos=l[1]
def __reduce__(self):
#print 'reduce call'
return (Perceptron_avg_my.rebuild,(self.fpos,self.freePos))
有什么建议? 非常感谢!!!
我不知道你是否找到它,但官方的Python文档有一个关于pickle扩展类型的部分 (遗憾的是,似乎没有这个文档的Python 3版本,但它在Python 3中的工作方式相同)。
我想你在这里有三个问题。 首先, __reduce__
返回的函数应该从头开始创建一个新对象并返回它,而你的rebuild
函数只设置一些属性。 其次, __reduce__
返回的元组本身必须是__reduce__
,并且作为一种方法, Perceptron_avg_my.rebuild
不可选(我认为这可以在python 3.3或3.4中修复)。 相反,您可以将其转换为模块级功能。 最后,参数(self.fpos,self.freePos)
被单独传递给rebuild
- 你不必自己解包元组。
以下似乎对我有用(尽管您可能也希望存储其他属性的值,否则它们将只有__init__
设置的初始值):
#inside the class definition
def __reduce__(self):
return (rebuild, (self.wlen, self.fpos, self.freePos))
#standalone function
def rebuild(wlen, fpos, freePos):
p = Perceptron_avg_my(wlen)
p.fpos = fpos
p.freePos = freePos
return p
从Cython 0。26(2017年7月发布)开始,不再需要实施pickle协议。 所有不包含指针或联合的cdef类都可以自动进行pickle。 对于包含结构的类,由于(以及其他原因)高代码开销,默认情况下禁用自动pickle。 通过使用@cython.auto_pickle(True)
装饰器,可以为具有结构的类启用自动酸洗。
更多信息可以在变更日志和Stefan Behnel的网站上找到。
我使用这种解决方法,但我不确定它是最好的解决方案。
我创建了一个新的支持文件来声明reduce调用的函数(如果我把它放在cython模块中它不起作用):
#perceptron_supp.py
from perceptron import Perceptron
def rebuild_perceptron(wlen,freePos,fpos,w,nw_avg,wtot_avg,wsup_avg,wmean_avg,wtot_my,wac_my,wtotc_my,wmean_my):
return Perceptron(wlen,True,freePos,fpos,w,nw_avg,wtot_avg,wsup_avg,wmean_avg,wtot_my,wac_my,wtotc_my,wmean_my)
然后我在cython模块中导入这个函数:
#perceptron.pyx
import numpy as np
cimport numpy as np
cimport cython
#added
from perceptron_supp import rebuild_perceptron
cdef class Perceptron:
cdef int wlen,freePos
cdef dict fpos
cdef np.ndarray w #np.ndarray[np.int32_t]
cdef int nw_avg
cdef np.ndarray wtot_avg,wsup_avg #np.ndarray[np.int32_t]
cdef np.ndarray wmean_avg #np.ndarray[np.float64_t]
cdef np.ndarray wtot_my,wac_my,wtotc_my #np.ndarray[np.int32_t]
cdef np.ndarray wmean_my #np.ndarray[np.float64_t]
def __cinit__(self,int wlen=4*10**7,setValues=False,freePos=0,fpos=0,w=0,nw_avg=0,wtot_avg=0,wsup_avg=0,wmean_avg=0,wtot_my=0,wac_my=0,wtotc_my=0,wmean_my=0):
if not setValues:
self.wlen=wlen
self.freePos=1
self.fpos= dict()
self.w=np.zeros(wlen,np.int32)
self.nw_avg=1
self.wtot_avg=np.zeros(wlen,np.int32)
self.wsup_avg=np.zeros(wlen,np.int32)
self.wmean_avg=np.zeros(wlen,np.float64)
self.wtot_my=np.zeros(wlen,np.int32)
self.wac_my=np.zeros(wlen,np.int32)
self.wtotc_my=np.zeros(wlen,np.int32)
self.wmean_my=np.zeros(wlen,np.float64)
else:
self.wlen=wlen
self.freePos=freePos
self.fpos=fpos
self.w=w
self.nw_avg=nw_avg
self.wtot_avg=wtot_avg
self.wsup_avg=wsup_avg
self.wmean_avg=wmean_avg
self.wtot_my=wtot_my
self.wac_my=wac_my
self.wtotc_my=wtotc_my
self.wmean_my=wmean_my
def __reduce__(self):
return (rebuild_perceptron,(self.wlen,self.freePos,self.fpos,self.w,self.nw_avg,self.wtot_avg,self.wsup_avg,self.wmean_avg,self.wtot_my,self.wac_my,self.wtotc_my,self.wmean_my))
当我使用我的感知器模块时,我只需做:从感知器导入Perceptron,现在我可以在需要时执行cPyckle.dump或cPickle.load。
如果有人有更好的解决方案,非常感谢!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.