pymc
pymc copied to clipboard
DOC: Provide a working example of inheriting from pymc.Model
Issue with current documentation:
The documentation for pymc.Model
seems to give some conceptual gist of how it works, but the example given in the documentation does not work.
There are no imports, and I am not sure where pt
is coming from in pt.constant(1)
. I have thought maybe pt
was for "PyTensor" but there is no constant
in the namespace of pt
resulting from import pytensor as pt
. There is a pymc.math.constant
, but I am unsure if that is the same thing.
But it is also unclear if the imports are the only issue. Here is some code where I have attempted to address the above namespace issues.
from pymc import *
class CustomModel(Model):
# 1) override init
def __init__(self, mean=0, sigma=1, name=''):
# 2) call super's init first, passing model and name
# to it name will be prefix for all variables here if
# no name specified for model there will be no prefix
super().__init__(name, model)
# now you are in the context of instance,
# `modelcontext` will return self you can define
# variables in several ways note, that all variables
# will get model's name prefix
# 3) you can create variables with the register_rv method
self.register_rv(Normal.dist(mu=mean, sigma=sigma), 'v1', initval=1)
# this will create variable named like '{name::}v1'
# and assign attribute 'v1' to instance created
# variable can be accessed with self.v1 or self['v1']
# 4) this syntax will also work as we are in the
# context of instance itself, names are given as usual
Normal('v2', mu=mean, sigma=sigma)
# something more complex is allowed, too
half_cauchy = HalfCauchy('sigma', beta=10, initval=1.)
Normal('v3', mu=mean, sigma=half_cauchy)
# Deterministic variables can be used in usual way
Deterministic('v3_sq', self.v3 ** 2)
# Potentials too
Potential('p1', pt.constant(1))
# After defining a class CustomModel you can use it in several
# ways
# I:
# state the model within a context
with Model() as model:
CustomModel()
# arbitrary actions
# II:
# use new class as entering point in context
with CustomModel() as model:
Normal('new_normal_var', mu=1, sigma=0)
# III:
# just get model instance with all that was defined in it
model = CustomModel()
# IV:
# use many custom models within one context
with Model() as model:
CustomModel(mean=1, name='first')
CustomModel(mean=2, name='second')
# variables inside both scopes will be named like `first::*`, `second::*`
Running the above I get an AttributeError
that I don't think is related because it occurs at super().__init__(name, model)
.
Traceback (most recent call last):
File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
exec(code, self.locals)
File "/home/galen/pymc_inheritance_question.py", line 42, in <module>
CustomModel()
File "/home/galen/.local/lib/python3.10/site-packages/pymc/model.py", line 264, in __call__
instance.__init__(*args, **kwargs)
File "/home/galen/pymc_inheritance_question.py", line 10, in __init__
super().__init__(name, model)
File "/home/galen/.local/lib/python3.10/site-packages/pymc/model.py", line 588, in __init__
self.add_coords(coords)
File "/home/galen/.local/lib/python3.10/site-packages/pymc/model.py", line 1080, in add_coords
for name, values in coords.items():
AttributeError: 'Model' object has no attribute 'items'
Idea or request for content:
Please provide a minimum working example.
:tada: Welcome to PyMC! :tada: We're really excited to have your input into the project! :sparkling_heart:
If you haven't done so already, please make sure you check out our Contributing Guidelines and Code of Conduct.
@galenseilis Thanks for reporting, that definitely should be fixed (pt
is import pytensor.tensor as pt
). But I'd also like to know if what you're trying to do really requires this?
@twiecki Thank you for the clarification on pt
.
Goals
Sure, let us start with clarifying what I am trying to do. I have three goals. They're sequentially-dependent in the sense that achieving goal 3 depends on achieving goal 2 which depends on achieving goal 1. However, it would still count for something if I achieved goal 1 alone, or only goal 1 and goal 2.
Goal 1
The first is just to understand how it works, unconditioned on "trying to do something else". Is a working example required to understand how pymc.Model
works? Maybe not, but I recommend it.
Goal 2
The second goal is to understand where I might use it. What is the use case for making a PyMC model this way? Often a tool is created for a desired set of use cases, and I would like to understand what was the desired use case for being able to build models this way. Is a working example required to understand the use cases of inheriting from pymc.Model
? Maybe not, but I recommend it.
Goal 3
The third goal is assess whether it is suitable for a project I am at the product design stage of. The concept is a Python package for random graphs, random hypergraphs, and random simplicial complexes among other things. PyMC is one of the tools I am considering for providing the Monte Carlo methods. If I go with PyMC, I want to make a decision about my model classes inheriting from pymc.Model
exor using the usual context wrapper within my classes' __init__
to store the PyMC model as an attribute. Whether I subclass or use the context wrapper will depend on what I learn from goals 1 and 2. Is a working example required to understand what subclassing from pymc.Model
would look like in my project? Maybe not, but I recommend it.
Maybe https://github.com/pymc-devs/pymc-experimental/blob/main/pymc_experimental/model_builder.py#L30 could help you?
Maybe https://github.com/pymc-devs/pymc-experimental/blob/main/pymc_experimental/model_builder.py#L30 could help you?
That looks potentially useful for developing NetMC. Certainly something to weigh against in goal 3. If there are alternatives to pymc.Model
I should consider them.
model_builder.py
is interesting, but has that stalled?
It would be nice to know some conventions for instantiating complex models, but when I look to the doc, I always come back to the same broken example.
If there are no desire to fix it, could we/I at least remove the example?
Didn't know it was broken?