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

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

javascript - Highcharts multi-color line -

javascript - Enter key does not work in search box -