How to model problem where we see a yes/no output?

Hi, I want to model a problem where I only see a yes/no answer (w), and I ask questions (z) in a given context (x). I want to learn something that influences the answer w.

  • a and b are two random variables, and I want to learn about them
  • x is known
  • I can make a “question” z

Now suppose:

y ~ a + b + x

But I only get to see whether z > y, let’s call it w:

w = z > y

So I observe x, propose z, and observe w = 1 iff z > y.

By proposing different z’s for different x’s I should be able to learn about a and b.

I was trying to express that problem in PyMC3 going along the following lines:

import pymc3 as pm

a_guess = 4
b_guess = 5

x = np.random.uniform(100, 200, 100)
z = a_guess + b_guess * x

with pm.Model() as model:
    
    a = pm.Uniform('a', lower=-10, upper=10)
    b = pm.Uniform('b', lower=-10, upper=10)
    
    y = a + b * x
    w = z > y

But I found no way to provide what w values I actually observe, in order to be able to sample from a posterior distribution of a and b.

I think I might be missing something fundamental here… Can some one help me?

In general, these kind of question is formulated as a GLM with Bernoulli likelihood:

with pm.Model() as m:
    ...
    obs = pm.Bernoulli('observed', p, observed=w)

Now the trick is to come up with the formulation of p. Rearrange your initial formulation a bit, we get:

                                   p = z > y 
=>                             z - y > 0
=> (a_guess - a) + (b_guess - b) * x > 0

A direct translation would be:

with pm.Model() as model:
    
    a = pm.Uniform('a', lower=-10, upper=10)
    b = pm.Uniform('b', lower=-10, upper=10)
    p = (a_guess - a) + (b_guess - b) * x > 0
    obs = pm.Bernoulli('observed', p, observed=w)

of course, a binary p will likely makes inference pretty difficult, instead, we usually use a Sigmoid:

with pm.Model() as model:
    a = pm.Uniform('a', lower=-10, upper=10)
    b = pm.Uniform('b', lower=-10, upper=10)
    latent_p = (a_guess - a) + (b_guess - b) * x
    obs = pm.Bernoulli('observed', pm.math.sigmoid(latent_p), observed=w)
3 Likes