0

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 bounds late_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.

user224348
  • 200
  • 1
  • 7
  • What happens when you use `low` and `high` for measurements? I get that the model is misspecified. What is happening is that there is no reason `early_low < early_high`, which leads you to regions with 0 probability. Even after you fix that, `measurements` being uniform means you must be sure that the generative model never allows values outside the observed ones (as it stands, you *do* allow that). – colcarroll Apr 05 '18 at 12:07
  • You really should avoid `tt.switch` - it breaks down the nice geometry of your model and makes using NUTS to sample very difficult. You should try to rewrite your model into a continuous one, more details here: https://stackoverflow.com/questions/49144144 – Junpeng Lao Apr 07 '18 at 14:30

0 Answers0