I'm trying to model following problem:
- Before some switching point in time (chosen from DiscreteUniform distribution), values are chosen from Uniform distribution with bounds
early_low
,early_high
. After this switch in time, values are chosen from Uniform distribution with boundslate_low
,late_high
. Given list of samples, estimate switching point and four bounds.
I would like to do something like this:
import pymc3 as pm
with pm.Model() as value_model:
early_low = pm.Uniform("early_low", lower=value.min(), upper=value.max())
late_low = pm.Uniform("late_low", lower=value.min(), upper=value.max())
early_high = pm.Uniform("early_high", lower=value.min(), upper=value.max())
late_high = pm.Uniform("late_high", lower=value.min(), upper=value.max())
switch_date = pm.DiscreteUniform('switch_date', lower=date.min(), upper=date.max())
low = pm.math.switch(date >= switch_date, late_low, early_low)
high = pm.math.switch(date >= switch_date, late_high, early_high)
measurements = pm.Uniform("measurements", low, high, observed=value)
Problem is, that I can't use low
and high
as parameters of Uniform
distribution (see measurements =
...). It is possible to use such arguments with Poisson distribution (of course there is only one argument). (See code in Coal mining disasters.) I don't know why.
According to this post, you can use arrays consisting of constants as parameters of distributions. I would like to use low
and high
in similar way.
This question shows creating deterministic function, but I'm not sure if this is somehow applicable to arrays.
Lastly, I thought about using mixture, something like this:
with pm.Model() as value_model:
early_low = pm.Uniform("early_low", lower=value.min(), upper=value.max())
late_low = pm.Uniform("late_low", lower=value.min(), upper=value.max())
early_high = pm.Uniform("early_high", lower=value.min(), upper=value.max())
late_high = pm.Uniform("late_high", lower=value.min(), upper=value.max())
switch_date = pm.DiscreteUniform('switch_date', lower=date.min(), upper=date.max())
early = pm.Uniform("early", early_low, early_high, observed=value)
late = pm.Uniform("late", late_low, late_high, observed=value)
measurements = pm.Mixture("measurements", [date >= switch_date, date < switch_date], [late, early])
However this doesn't seem like way to go.
This is how I sample this model:
with value_model:
trace = pm.sample(10000)
In ideal case, I'm looking for way to do something like switch
, but instead of taking fixed values, it should decide between two distributions.