# Problem with sampling - pickling

**URL:** <https://discourse.pymc.io/t/problem-with-sampling-pickling/7010>\
**Category:** Questions\
**Created:** [March 16, 2021, 9:54pm UTC](https://discourse.pymc.io/t/problem-with-sampling-pickling/7010 "2021-03-16T21:54:42Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![RichardJM](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/richardjm/32/3274_2.png) [@RichardJM](https://discourse.pymc.io/u/RichardJM)\
**Post date:** [March 16, 2021, 9:54pm UTC](https://discourse.pymc.io/t/problem-with-sampling-pickling/7010/1 "2021-03-16T21:54:42Z")

</div>

Hi,

I have been revisiting a model that worked a couple of months ago, but since updating to PyMC v3.11 I am getting a Recursion Error when trying to sample.

The model looks like this:

```python
def pow_law_mod(x,p1,p2,p3):
    return p1*tt.pow(x,-p2)+p3

def likelihood(model, theta1, theta2, theta3, nu):
    '''
    model: - function
                functional form of curve
    theta1-3: - float
                parameters
    nu: - int 
                constant
    '''
    def logp_(value):
        mod_ = model(value[0],theta1,theta2, theta3) 
        return (-nu*((value[1]/mod_)+tt.log(mod_)+(2/nu-1)*tt.log(value[1]))).sum()
    return logp_

with pm.Model() as model:
    
    #prior
    slope = pm.Normal('slope', 1, 1 )
    amp = pm.HalfNormal('amp', 1 )
    const = pm.Normal('const', 1e3, 100)
    
    #likelihood
    like = pm.DensityDist('like', likelihood(pow_law_mod, amp, slope, const,2), observed=[x,test_data])

```

and I get a very long error message that looks like the following (I have truncated):

```python
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-7-af36fa849c26> in <module>
      2 
      3     
----> 4 trace = pm.sample(1000, tune = 2500, target_accept=0.85)
      5 
      6     

~/opt/anaconda3/lib/python3.8/site-packages/pymc3/sampling.py in sample(draws, step, init, n_init, start, trace, chain_idx, chains, cores, tune, progressbar, model, random_seed, discard_tuned_samples, compute_convergence_checks, callback, jitter_max_retries, return_inferencedata, idata_kwargs, mp_ctx, pickle_backend, **kwargs)
    556 _print_step_hierarchy(step)
    557 try:
--> 558 trace = _mp_sample( **sample_args,** parallel_args)
    559 except pickle.PickleError:
    560 _log.warning("Could not pickle model, sampling singlethreaded.")

~/opt/anaconda3/lib/python3.8/site-packages/pymc3/sampling.py in _mp_sample(draws, tune, step, chains, cores, chain, random_seed, start, progressbar, trace, model, callback, discard_tuned_samples, mp_ctx, pickle_backend, **kwargs)
   1458 traces.append(strace)
   1459 
-> 1460 sampler = ps.ParallelSampler(
   1461 draws,
   1462 tune,

~/opt/anaconda3/lib/python3.8/site-packages/pymc3/parallel_sampling.py in __init__ (self, draws, tune, chains, cores, seeds, start_points, step_method, start_chain_num, progressbar, mp_ctx, pickle_backend)
    421 if mp_ctx.get_start_method() != "fork":
    422 if pickle_backend == "pickle":
--> 423 step_method_pickled = pickle.dumps(step_method, protocol=-1)
    424 elif pickle_backend == "dill":
    425 try:

~/opt/anaconda3/lib/python3.8/site-packages/pymc3/distributions/distribution.py in __getstate__ (self)
    559 ) from err
    560 else:
--> 561 raise err
    562 vals = self. __dict__.copy()
    563 vals["logp"] = logp

~/opt/anaconda3/lib/python3.8/site-packages/pymc3/distributions/distribution.py in __getstate__ (self)
    552 # Fix https://github.com/pymc-devs/pymc3/issues/3844
    553 try:
--> 554 logp = dill.dumps(self.logp)
    555 except RecursionError as err:
    556 if type(self.logp) == types.MethodType:

~/opt/anaconda3/lib/python3.8/site-packages/dill/_dill.py in dumps(obj, protocol, byref, fmode, recurse, **kwds)
    271 """pickle an object to a string"""
    272 file = StringIO()
--> 273 dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
    274 return file.getvalue()
    275 

~/opt/anaconda3/lib/python3.8/site-packages/dill/_dill.py in dump(obj, file, protocol, byref, fmode, recurse, **kwds)
    265 _kwds = kwds.copy()
    266 _kwds.update(dict(byref=byref, fmode=fmode, recurse=recurse))
--> 267 Pickler(file, protocol, **_kwds).dump(obj)
    268 return
    269 

~/opt/anaconda3/lib/python3.8/site-packages/dill/_dill.py in dump(self, obj)
    452 raise PicklingError(msg)
    453 else:
--> 454 StockPickler.dump(self, obj)
    455 stack.clear() # clear record of 'recursion-sensitive' pickled objects
    456 return

~/opt/anaconda3/lib/python3.8/pickle.py in dump(self, obj)
    485 if self.proto >= 4:
    486 self.framer.start_framing()
--> 487 self.save(obj)
    488 self.write(STOP)
    489 self.framer.end_framing()

~/opt/anaconda3/lib/python3.8/pickle.py in save(self, obj, save_persistent_id)
    558 f = self.dispatch.get(t)
    559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
    561 return
    562 

~/opt/anaconda3/lib/python3.8/site-packages/dill/_dill.py in save_function(pickler, obj)
   1442 if _memo: pickler._recurse = False
   1443 fkwdefaults = getattr(obj, ' __kwdefaults__', None)
-> 1444 pickler.save_reduce(_create_function, (obj. __code__ ,
   1445 globs, obj. __name__ ,
   1446 obj. __defaults__ , obj. __closure__ ,

~/opt/anaconda3/lib/python3.8/pickle.py in save_reduce(self, func, args, state, listitems, dictitems, state_setter, obj)
    690 else:
    691 save(func)
--> 692 save(args)
    693 write(REDUCE)
    694 

~/opt/anaconda3/lib/python3.8/pickle.py in save(self, obj, save_persistent_id)
    558 f = self.dispatch.get(t)
    559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
    561 return
    562 

~/opt/anaconda3/lib/python3.8/pickle.py in save_tuple(self, obj)
    899 write(MARK)
    900 for element in obj:
--> 901 save(element)
    902 
    903 if id(obj) in memo:

~/opt/anaconda3/lib/python3.8/pickle.py in save(self, obj, save_persistent_id)
    558 f = self.dispatch.get(t)
    559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
    561 return
    562 

~/opt/anaconda3/lib/python3.8/pickle.py in save_tuple(self, obj)
    899 write(MARK)
    900 for element in obj:
--> 901 save(element)
    902 
    903 if id(obj) in memo:

~/opt/anaconda3/lib/python3.8/pickle.py in save(self, obj, save_persistent_id)
    558 f = self.dispatch.get(t)
    559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
    561 return
    562 

~/opt/anaconda3/lib/python3.8/site-packages/dill/_dill.py in save_cell(pickler, obj)
   1176 log.info("Ce: %s" % obj)
   1177 f = obj.cell_contents
-> 1178 pickler.save_reduce(_create_cell, (f,), obj=obj)
   1179 log.info("# Ce")
   1180 return
+
+ 
+
+

... last 132 frames repeated, from the frame below ...

~/opt/anaconda3/lib/python3.8/pickle.py in _batch_setitems(self, items)
    995 for k, v in tmp:
    996 save(k)
--> 997 save(v)
    998 write(SETITEMS)
    999 elif n:

RecursionError: maximum recursion depth exceeded while calling a Python object

```

Anybody have any ideas what might have happened? It may not be a PyMC thing but any help would be appreciated.

Thanks in advance.
