Closed yarden closed 8 years ago
Sorry to bug, but does anyone have hints on this? I'm pretty sure I'm missing something very simple about how PyMC objects can be mutated/copied, and have not been able to get around it. Thanks again!
There really isn't any functionality built into PyMC to do this, though it ought to be easy to wrap something along the lines that you have into a function. All we have are facilities for serializing model states. We would happily accept a pull request to this effect.
Thank you Chris. I'd love to implement this; just let me know if there are any subtle 'gotchas' with copying a node from a model without breaking inference. It seems like the pythonic solution is just to implement a __copy__
method for a Stochastic node (and for a Model
) that will copy the relevant attributes, like the parents and children, etc.
I'm revisiting this and still puzzled as to how to correctly copy Model objects. deepcopy
on any variable instance fails with this:
import pymc
import copy
rain = pymc.Bernoulli("rain", 0.5)
model = pymc.Model([rain])
# Get a variable from a model and try to copy it
var = next(iter(model.variables))
# Deep copy of variable
new_node = copy.deepcopy(var)
# This fails
print "new node: "
print new_node
The error is below.
I don't really follow what is happening with ParentDict and how distribution objects are made, and that seems to be the barrier to making a copy a Model
object.
Can someone give a hint as to how to copy these objects? All I'm trying to do is copy a Model
object correctly. (Happy to serialize model and read back in if that's the best way to do this but I don't see the serialization methods @fonnesbeck mentioned?).
This is the error from above code snippet:
Traceback (most recent call last):
File "pymc_test.py", line 78, in <module>
new_node = copy.deepcopy(var)
File "/Users/yarden/anaconda/lib/python2.7/copy.py", line 190, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "/Users/yarden/anaconda/lib/python2.7/copy.py", line 334, in _reconstruct
state = deepcopy(state, memo)
File "/Users/yarden/anaconda/lib/python2.7/copy.py", line 163, in deepcopy
y = copier(x, memo)
File "/Users/yarden/anaconda/lib/python2.7/copy.py", line 257, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "/Users/yarden/anaconda/lib/python2.7/copy.py", line 190, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "/Users/yarden/anaconda/lib/python2.7/copy.py", line 358, in _reconstruct
y[key] = value
File "/Users/yarden/Software/pymc/pymc/PyMCObjects.py", line 151, in __setitem__
old_parent = self[key]
KeyError: 'p'
I'm not sure if this helps, but in kabuki I managed to make an object pickable (but it essentially got recreated): https://github.com/hddm-devs/kabuki/blob/master/kabuki/hierarchical.py#L361
It's not a PyMC object though that gets copied in __getstate__
(in the Hierarchical
class) as far as I can tell? Or did you mean that I should try to pickle a PyMC object, serialize it out, and then read it back in as a way to generate a copy?
Any attempt to make deepcopy
of a PyMC node gives an error, e.g.:
rain_pymc = pymc.Bernoulli("rain", 0.5)
from copy import deepcopy
deepcopy(rain_pymc)
gives:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-145-7ca6ed433e2e> in <module>()
----> 1 deepcopy(rain_pymc)
/Users/yarden/anaconda/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
188 raise Error(
189 "un(deep)copyable object of type %s" % cls)
--> 190 y = _reconstruct(x, rv, 1, memo)
191
192 memo[d] = y
/Users/yarden/anaconda/lib/python2.7/copy.pyc in _reconstruct(x, info, deep, memo)
332 if state:
333 if deep:
--> 334 state = deepcopy(state, memo)
335 if hasattr(y, '__setstate__'):
336 y.__setstate__(state)
/Users/yarden/anaconda/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
161 copier = _deepcopy_dispatch.get(cls)
162 if copier:
--> 163 y = copier(x, memo)
164 else:
165 try:
/Users/yarden/anaconda/lib/python2.7/copy.pyc in _deepcopy_dict(x, memo)
255 memo[id(x)] = y
256 for key, value in x.iteritems():
--> 257 y[deepcopy(key, memo)] = deepcopy(value, memo)
258 return y
259 d[dict] = _deepcopy_dict
/Users/yarden/anaconda/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
188 raise Error(
189 "un(deep)copyable object of type %s" % cls)
--> 190 y = _reconstruct(x, rv, 1, memo)
191
192 memo[d] = y
/Users/yarden/anaconda/lib/python2.7/copy.pyc in _reconstruct(x, info, deep, memo)
356 key = deepcopy(key, memo)
357 value = deepcopy(value, memo)
--> 358 y[key] = value
359 return y
360
/Users/yarden/Software/pymc/pymc/PyMCObjects.py in __setitem__(self, key, new_parent)
149
150 def __setitem__(self, key, new_parent):
--> 151 old_parent = self[key]
152
153 # Possibly remove owner from old parent's children set.
KeyError: 'p'
Hi,
I'm writing a small extension to pymc for inference in DBNs that unrolls a DBN into a static graphical model, so that it can be solved with pymc. To do this, it's helpful to copy
Model
instances and change their variables, but I'm not sure how to correctly copy models and how to modify their contents? For example, I'd like to copy aModel
instance and change the names of its variables in place, and which nodes are parents, keeping all else in tact. E.g.:What is the best way to copy
Model
instances and alter them? Sorry if this is obvious, I couldn't find an example in the documentation and looking atObjectContainer
and related classes didn't reveal the answer. Thanks very much.