Thanks for your latest reply - I tried something else in the meantime:
Here’s my attempt at a custom likelihood for the censored data, in sample_censored_correct()
. The rest is my toy problem for checking that naive modeling is biased.
"""Toy model for censored data"""
import numpy as np
import pymc3 as pm
true_rate = 0.25
N = 5_000
np.random.seed(45678)
customers = np.random.uniform(low=0, high=100, size=N)
complaints = np.random.poisson(lam=customers * true_rate)
def censor_data():
measured = (customers >= 10) & ((complaints == 0) | (complaints >= 10))
n = customers[measured]
e = complaints[measured]
return n, e
# noinspection PyTypeChecker, PyUnresolvedReferences
def do_sample_naive(n, e):
assert len(n) == len(e)
print(f"{len(n)} observations used")
print(n[:20])
print(e[:20])
with pm.Model():
r = pm.Exponential("r", 10)
pm.Poisson("events", mu=n * r, observed=e)
trace = pm.sample(2000, tune=1000)
print(pm.summary(trace))
def sample_censored_wrong():
n, e = censor_data()
do_sample_naive(n, e)
def sample_uncensored():
do_sample_naive(customers, complaints)
# noinspection PyTypeChecker,PyUnresolvedReferences
def sample_censored_correct():
ns, es = censor_data()
print(f"{len(ns)} observations used")
print(ns[:20])
print(es[:20])
with pm.Model():
r = pm.Exponential("r", 10)
def truncated_poisson_like(e_, n_):
lbda = n_ * r
log_like = pm.Poisson.dist(mu=lbda).logp(e_)
if e_ in [1, 2, 3]:
return -np.inf # log(0)
else:
# Normalization for the truncated values: subtract probabilities for 1, 2 and 3
prob_sum = pm.math.exp(-lbda) * (lbda + lbda**2 / 2 + lbda**3 / 6)
norm_constant = 1 - prob_sum
return log_like - pm.math.log(norm_constant)
pm.DensityDist(
"observed", logp=truncated_poisson_like, observed={"e_": es, "n_": ns}
)
trace = pm.sample(2000, tune=1000)
print(pm.summary(trace))
if __name__ == "__main__":
print("\n\n🟢 Uncensored:\n")
sample_uncensored()
print("\n\n🔴 Censored, wrong:\n")
sample_censored_wrong()
print("\n\n🟣 Censored, correct:\n")
sample_censored_correct()
The issue is that I get an error
Traceback (most recent call last):
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 603, in save
self.save_reduce(obj=obj, *rv)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 717, in save_reduce
save(state)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 560, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/site-packages/dill/_dill.py", line 990, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 971, in save_dict
self._batch_setitems(obj.items())
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 997, in _batch_setitems
save(v)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 603, in save
self.save_reduce(obj=obj, *rv)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 717, in save_reduce
save(state)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 560, in save
f(self, obj) # Call unbound method with explicit self
[... repeating ...]
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 560, in save
f(self, obj) # Call unbound method with explicit self
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/site-packages/dill/_dill.py", line 990, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 970, in save_dict
self.memoize(obj)
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 510, in memoize
self.write(self.put(idx))
File "/Users/ehansis/anaconda/envs/pymc3/lib/python3.9/pickle.py", line 515, in put
if self.proto >= 4:
RecursionError: maximum recursion depth exceeded in comparison
Any ideas on the error (or suggestions on my custom likelihood)? If not, I’ll look into your suggestion.
EDIT: I should mention that I’m on a quite old version of pymc3 (3.11.4), so maybe upgrading that would be a first step…