pymc-devs / pymc-examples

Examples of PyMC models, including a library of Jupyter notebooks.
https://www.pymc.io/projects/examples/en/latest/
MIT License
287 stars 245 forks source link

unhashable type: 'dict' in Bayesian regression with truncated or censored data #399

Closed computbiolgeek closed 2 years ago

computbiolgeek commented 2 years ago

Bayesian regression with truncated or censored data: Notebook url:

Issue description

Running the following chunk of code in the corresponding notebook

fig, ax = plt.subplots(figsize=(10, 3))

with pm.Model() as m:
    pm.Normal("y", 0, 2)

with pm.Model() as m_censored:
    pm.Censored("y", pm.Normal.dist(0, 2), lower=-1.0, upper=None)

logp_fn = m.logp
logp_censored_fn = m_censored.logp

xi = np.hstack((np.linspace(-6, -1.01), [-1.0], np.linspace(-0.99, 6)))

ax.plot(xi, [np.exp(logp_fn({"y": x})) for x in xi], label="uncensored")
ax.plot(xi, [np.exp(logp_censored_fn({"y": x})) for x in xi], label="censored", lw=8, alpha=0.6)
ax.axvline(-1, c="k", ls="--")
ax.legend()
ax.set(xlabel="$y$", ylabel="probability density", ylim=(-0.02, 0.4));

gave a TypeError

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [60], in <cell line: 14>()
     10 logp_censored_fn = m_censored.logp
     12 xi = np.hstack((np.linspace(-6, -1.01), [-1.0], np.linspace(-0.99, 6)))
---> 14 ax.plot(xi, [np.exp(logp_fn({"y": x})) for x in xi], label="uncensored")
     15 ax.plot(xi, [np.exp(logp_censored_fn({"y": x})) for x in xi], label="censored", lw=8, alpha=0.6)
     16 ax.axvline(-1, c="k", ls="--")

Input In [60], in <listcomp>(.0)
     10 logp_censored_fn = m_censored.logp
     12 xi = np.hstack((np.linspace(-6, -1.01), [-1.0], np.linspace(-0.99, 6)))
---> 14 ax.plot(xi, [np.exp(logp_fn({"y": x})) for x in xi], label="uncensored")
     15 ax.plot(xi, [np.exp(logp_censored_fn({"y": x})) for x in xi], label="censored", lw=8, alpha=0.6)
     16 ax.axvline(-1, c="k", ls="--")

File /opt/homebrew/lib/python3.9/site-packages/pymc/model.py:742, in Model.logp(self, vars, jacobian, sum)
    740 rv_order, potential_order = [], []
    741 for i, var in enumerate(varlist):
--> 742     value_var = self.rvs_to_values.get(var)
    743     if value_var is not None:
    744         rv_values[var] = value_var

TypeError: unhashable type: 'dict'

Expected output

The figure below the above chunk of code, as shown in the notebook.

Proposed solution

No solution yet. Looked the signature of m.logp, which suggests that a list should be passed as an argument, but had no idea how to achieve that.

OriolAbril commented 2 years ago

Thanks for reporting. What versions of pymc and aesara are you using?

computbiolgeek commented 2 years ago

Thanks for the reply. My PyMC and aesara version are

pymc                          4.1.3
aesara                        2.7.7
ricardoV94 commented 2 years ago

Instead of m_censored.logp you should call m_censored.compile_logp()

OriolAbril commented 2 years ago

Do you want to send a PR to update and rerun the notebook @computbiolgeek?

computbiolgeek commented 2 years ago

Changing

logp_fn = m.logp
logp_censored_fn = m_censored.logp

to

logp_fn = m.compile_logp()
logp_censored_fn = m_censored.compile_logp()

did resolve the error. Thank you so much!

I typed up everything from scratch and did not clone the notebook. Let me know if a PR is still needed. Thanks!

ricardoV94 commented 2 years ago

I confirm the code in the notebook still needs to be updated