Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attribute error when observed has multiple dimensions: MultiObservedRV #384

Closed
sidravi1 opened this issue Oct 31, 2018 · 6 comments · Fixed by #1098
Closed

Attribute error when observed has multiple dimensions: MultiObservedRV #384

sidravi1 opened this issue Oct 31, 2018 · 6 comments · Fixed by #1098

Comments

@sidravi1
Copy link

sidravi1 commented Oct 31, 2018

Here's a Weibull survival model in pymc3:

def weibull_lccdf(alpha, beta, x):
    return -(x / beta)**alpha

class Weibull_like(pm.Continuous):
    def __init__(self, alpha, lambd, *args, **kwargs):
       
        self.alpha = tt.as_tensor_variable(alpha)
        self.lambd = tt.as_tensor_variable(lambd)
        
        super().__init__(*args, **kwargs)

    def logp(self, failure, value):
        
        alpha = self.alpha
        beta = 1/tt.exp(self.lambd)

        no_censoring = failure.astype('bool')
        beta_nocens = beta[no_censoring]
        beta_censor = beta[~no_censoring]
        
        uncensored = pm.Weibull.dist(alpha, beta_nocens).logp(value[no_censoring]).sum()
        censored = weibull_lccdf(alpha, beta_censor, value[~no_censoring]).sum()
        
        return uncensored + censored

and the setting up the model

with pm.Model() as weibull:
    beta0 = pm.Normal('β_0', 0, 100)
    beta1 = pm.Normal('β_1', 0, 100)
    alpha = pm.Gamma('α', 1.0, 1/0.001)
    
    lam_ = pm.Deterministic('λ', beta0 + beta1*(treatment - treatment.mean()))
    
    like = Weibull_like('survival', alpha=alpha, lambd=lam_, observed={'failure':failure, 'value':t})
    
    trace_weibull = pm.sample(tune=1000, draws=3000, chains=2)

Running any of plots gives an Attribute error:

av.plot_trace(trace_EVM)
/anaconda3/lib/python3.6/site-packages/arviz/data/io_pymc3.py in <dictcomp>(.0)
    107         model = self.trace._straces[0].model  # pylint: disable=protected-access
    108 
--> 109         observations = {obs.name: obs.observations for obs in model.observed_RVs}
    110         if self.dims is None:
    111             dims = {}

AttributeError: 'MultiObservedRV' object has no attribute 'observations'

Poking around a bit, it looks like MultiObservedRV, doesn't create an observations parameter but instead saves in self.data:

https://github.com/pymc-devs/pymc3/blob/master/pymc3/model.py#L1369

Suggestion on how to fix this? Is it as simple as just patching the PyMC3Converter class where it build the observations dict?

https://github.com/arviz-devs/arviz/blob/master/arviz/data/io_pymc3.py#L110

I'm assuming just doing this will break some of the plots?

@sidravi1 sidravi1 changed the title Attribute error when observed that multiple dimension: MultiObservedRV Attribute error when observed has multiple dimensions: MultiObservedRV Oct 31, 2018
@ahartikainen
Copy link
Contributor

Will it create correct InferenceData object?

@ColCarroll
Copy link
Member

Darn, I'd never even seen MultiObservedRV.

I think patching there will work, and will probably break a few plots that assume there is only 1 observed variable. Tests will continue to pass, since nothing checks for this.

Maybe a solution is to add a survival model (like this, but with your likelihood) to the model zoo, and include plot(s) from it in the documentation. Is the model you're working with public, or could it be?

@sidravi1
Copy link
Author

sidravi1 commented Oct 31, 2018 via email

@canyon289 canyon289 added the Bug label Nov 19, 2018
@FlorianWilhelm
Copy link

I just ran into the same problem.

@mfansler
Copy link

mfansler commented Apr 1, 2019

Hit the same issue when using pymc3.DensityDist for making a weighted model. FWIW, here is the reproducible example I made for this.

import numpy as np
import pymc3 as pm
import arviz as az

# fake regression data, with weights (W)
np.random.seed(2019)
N = 100
X = np.random.uniform(size=N)
W = 1 + np.random.poisson(size=N)
a, b = 5, 17
Y = a + np.random.normal(b*X)

with pm.Model():
    a = pm.Normal('a', 0, 10)
    b = pm.Normal('b', 0, 10)
    
    mu = a + b*X
    sigma = pm.HalfNormal('sigma', 1)
    
    def weighted_normal(y, w):
        return w*pm.Normal.dist(mu=mu, sd=sigma).logp(y)
    
    y_logp = pm.DensityDist('y_logp', weighted_normal, observed={'y': Y, 'w': W})
    
    trace = pm.sample(2000, tune=2000, random_seed=2019)

traz = az.from_pymc3(trace)

which gives the error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-50-3aba64ad8aca> in <module>
----> 1 traz = az.from_pymc3(trace)

~/miniconda3/envs/pymc36/lib/python3.7/site-packages/arviz/data/io_pymc3.py in from_pymc3(trace, prior, posterior_predictive, coords, dims)
    150         posterior_predictive=posterior_predictive,
    151         coords=coords,
--> 152         dims=dims,
    153     ).to_inference_data()

~/miniconda3/envs/pymc36/lib/python3.7/site-packages/arviz/data/io_pymc3.py in to_inference_data(self)
    138                 "posterior_predictive": self.posterior_predictive_to_xarray(),
    139                 "prior": self.prior_to_xarray(),
--> 140                 "observed_data": self.observed_data_to_xarray(),
    141             }
    142         )

~/miniconda3/envs/pymc36/lib/python3.7/site-packages/arviz/data/base.py in wrapped(cls, *args, **kwargs)
     23                 if getattr(cls, prop) is None:
     24                     return None
---> 25             return func(cls, *args, **kwargs)
     26 
     27         return wrapped

~/miniconda3/envs/pymc36/lib/python3.7/site-packages/arviz/data/io_pymc3.py in observed_data_to_xarray(self)
    108         model = self.trace._straces[0].model  # pylint: disable=protected-access
    109 
--> 110         observations = {obs.name: obs.observations for obs in model.observed_RVs}
    111         if self.dims is None:
    112             dims = {}

~/miniconda3/envs/pymc36/lib/python3.7/site-packages/arviz/data/io_pymc3.py in <dictcomp>(.0)
    108         model = self.trace._straces[0].model  # pylint: disable=protected-access
    109 
--> 110         observations = {obs.name: obs.observations for obs in model.observed_RVs}
    111         if self.dims is None:
    112             dims = {}

AttributeError: 'MultiObservedRV' object has no attribute 'observations'

Environment Info

PyMC3 3.6
ArviZ 0.3.3

@OriolAbril
Copy link
Member

@sidravi1 @mfansler @ColCarroll I was checking the state of this issue, and found out that latest release does not raise an error as it used to happen. There is no observed data though. I tried to modify io_pymc3 to retrieve this kind of data but I am not sure this is the right approach, I am not eve sure it would be helpful to have this kind of data stored. It would be great if somebody could try the code or review the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants