python - Why am I allowed pickle instancemethods that are Theano functions, but not normal instancemethods? -
in process of using joblib parallelize model-fitting code involving theano functions, i've stumbled across behavior seems odd me.
consider simplified example:
from joblib import parallel, delayed import theano theano import tensor te import numpy np class theanomodel(object): def __init__(self): x = te.dvector('x') y = (x ** te.log(x ** 2)).sum() self.theano_get_y = theano.function([x], y) def get_y(self, x): return self.theano_get_y(x) def run(niter=100): x = np.random.randn(1000) model = theanomodel() pool = parallel(n_jobs=-1, verbose=1, pre_dispatch='all') # fails `typeerror: can't pickle instancemethod objects`... results = pool(delayed(model.get_y)(x) _ in xrange(niter)) # # ... works! why? # results = pool(delayed(model.theano_get_y)(x) _ in xrange(niter)) if __name__ == '__main__': run()
i understand why first case fails, since .get_y()
instancemethod of theanomodel
. don't understand why second case works, since x
, y
andtheano_get_y()
declared within __init__()
method of theanomodel
. theano_get_y()
can't evaluated until theanomodel
instance has been created. surely, then, should considered instancemethod, , should therefore unpickleable? in fact, still works if explicitly declare x
, y
attributes of theanomodel
instance.
can explain what's going on here?
update
just illustrate why think behaviour particularly weird, here few examples of other callable member objects don't take self
first argument:
from joblib import parallel, delayed import theano theano import tensor te import numpy np class theanomodel(object): def __init__(self): x = te.dvector('x') y = (x ** te.log(x ** 2)).sum() self.theano_get_y = theano.function([x], y) def square(x): return x ** 2 self.member_function = square self.static_method = staticmethod(square) self.lambda_function = lambda x: x ** 2 def run(niter=100): x = np.random.randn(1000) model = theanomodel() pool = parallel(n_jobs=-1, verbose=1, pre_dispatch='all') # # not allowed: `typeerror: can't pickle function objects` # results = pool(delayed(model.member_function)(x) _ in xrange(niter)) # # not allowed: `typeerror: can't pickle function objects` # results = pool(delayed(model.lambda_function)(x) _ in xrange(niter)) # # not allowed: `typeerror: can't pickle staticmethod objects` # results = pool(delayed(model.static_method)(x) _ in xrange(niter)) # totally fine!? results = pool(delayed(model.theano_get_y)(x) _ in xrange(niter)) if __name__ == '__main__': run()
none of them pickleable exception of theano.function
!
theano functions aren't python functions. instead python objects override __call__
. means can call them function internally objects of custom class. in consequence, can pickle them.
Comments
Post a Comment