Hello,
I’ve built a GLM with Wald response in Bambi and I wanted to replicate that in PyMC3. The first version of the model is more or less what Bambi does under the hood, and the second version is my attempt to have it in a more concise manner in PyMC3 (which does not work)
EDIT: I’m tagging @agustinaarroyuelo here since she is the one who originally tried to fit the same model using both libraries and commented to me about the problem.
Setup
import numpy as np
import pandas as pd
import pymc3 as pm
import theano.tensor as tt
data = pd.read_csv("https://courses.ms.ut.ee/2020/glm/spring/uploads/Main/carclaims.csv")
data = data[data["claimcst0"] > 0]
# data.head()
# Get components of the model matrix
intercept = np.ones((len(data), 1))
age = pd.get_dummies(data["agecat"], drop_first = True).to_numpy()
area = pd.get_dummies(pd.Categorical(data.area), drop_first = True).to_numpy()
gender = pd.get_dummies(pd.Categorical(data.gender), drop_first = True).to_numpy()
Model 1:
with pm.Model() as model_1:
mu = 0.0
# Build predictors
β_0 = pm.Normal(
"β_0",
mu=np.array(7.6),
sigma=np.array(2.7),
)
mu += pm.math.dot(intercept, β_0)[:, None]
β_age = pm.Normal(
"β_age",
mu=np.array([0] * 5),
sigma=np.array([0.32, 6.94, 1.13, 5.44, 9.01]),
shape=5
)
mu += pm.math.dot(age, β_age)[:, None]
β_gender = pm.Normal(
"β_gender",
mu=np.array(0),
sigma=np.array(1.30),
)
mu += pm.math.dot(gender, β_gender)[:, None]
β_area = pm.Normal(
"β_area",
mu=np.array([0] * 5),
sigma=np.array([0.86, 0.25, 1.30, 0.76, 5.33]),
shape=5
)
mu += pm.math.dot(area, β_area)[:, None]
# Log link
mu = tt.exp(mu)
# Get response
response = np.array([data["claimcst0"]]).T
pm.Wald("claim", mu=mu, lam = pm.HalfCauchy("claim_lam", beta=1), observed=response)
idata_1 = pm.sample(return_inferencedata=True)
This model works, it takes around 30 seconds in my computer to finish and the results are the same than the ones I get with Bambi (as expected, since I replicated what happens within Bambi).
Model 2
Here I thought: “Ok, what if I concatenate the betas and do just one matrix multiplication?” And the code would be something like
with pm.Model() as model_2:
# Same as before
β_0 = pm.Normal(
"β_0",
mu=np.array(7.6),
sigma=np.array(2.7),
)
β_age = pm.Normal(
"β_age",
mu=np.array([0] * 5),
sigma=np.array([0.32, 6.94, 1.13, 5.44, 9.01]),
shape=5
)
β_gender = pm.Normal(
"β_gender",
mu=np.array(0),
sigma=np.array(1.30),
)
β_area = pm.Normal(
"β_area",
mu=np.array([0] * 5),
sigma=np.array([0.86, 0.25, 1.30, 0.76, 5.33]),
shape=5
)
# HERE somehow concatenate the betas to get a single column vector β
# ...
# mu = pm.math.dot(X, β)
# Log link
mu = tt.exp(mu)
# Get response
response = np.array([data["claimcst0"]]).T
pm.Wald("claim", mu=mu, lam = pm.HalfCauchy("claim_lam", beta=1), observed=response)
idata_1 = pm.sample(return_inferencedata=True)
What I tried:
-
tt.concatenate
and usingshape=(5, 1)
, as suggested here But it returned the following
TypeError: ('Non-unit value on shape on a broadcastable dimension.', (5, 5), (False, True))
-
Use
tt.inc_subtensor
as here, but my computer crashed. -
I also attempted with just removing the
[:, None]
inmodel_1
to see what happened and my computer also crashed.
So, I don’t really know where to go next with this problem. I would really appreciate any suggestion that anyone can give here.
%load_ext watermark
%watermark -n -u -v -iv -w
Last updated: Wed May 12 2021
Python implementation: CPython
Python version : 3.8.5
IPython version : 7.18.1
numpy : 1.20.1
pymc3 : 3.11.2
theano: 1.0.5
pandas: 1.2.2
json : 2.0.9
Watermark: 2.1.0