Skip to content

Instantly share code, notes, and snippets.

@chagag
Last active November 23, 2016 20:59
Show Gist options
  • Save chagag/2b165ab59f9336afc0d0b3f9f06b6f84 to your computer and use it in GitHub Desktop.
Save chagag/2b165ab59f9336afc0d0b3f9f06b6f84 to your computer and use it in GitHub Desktop.
var data = {self: 1, group : [5,5,6,7,8,9]}
var model = function(){
// uninformative prior over group beliefs
var groupMean = uniform(0,10) //prior
var groupSd = uniform(0, 10) //prior
// observe
// estimate groupmean and sd considering the group
mapData({data: data.group}, function(datum)
{observe(Gaussian({mu: groupMean, sigma: groupSd}), datum)})
// true emotion is generated from the group dist
var trueEmotion = Gaussian({mu: groupMean, sigma: groupSd})
observe (trueEmotion, data.self)
// return beliefs about both the group and the self, so we can compare
var response = sample(trueEmotion)
condition(response < 10 && response > 0)
return {group: groupMean, response: response}
}
var posterior = Infer({method:'MCMC', samples: 500, lag: 50, burn: 5},model)
viz(posterior)
viz.marginals(posterior)
//Estimating group mean based on a sample
//the prior is a uniform distribution participants assume that the mean and standard deviation were taken from a gaussian dist.
//They estimate the mean of that distribution.
var groupEmotions = [5,3,5,6,7]
var model = function(){
var gaussianMean = uniform(0,10) //prior
var guassianSd = uniform(0, 10) //prior
var obsFn = function(datum){ observe(Gaussian({mu: gaussianMean,
sigma: guassianSd}), datum) }
mapData({data: groupEmotions}, obsFn)
return gaussianMean
}
// an alternative option var obsFn = function(datum){ condition( sample(gaussian(..,..) == datum ) }
var estimateColEmotion = Infer({method:'MCMC', samples: 100, lag: 100, burn: 5},model)
print('Expected average is: ' + expectation(estimateColEmotion))
expectation(estimateColEmotion)
viz(estimateColEmotion)
// estimating the group emotion from the individual emotion
//By merely assuming a uniform distribution on the prior the system tends to assume that an extreme participant is biased.
var indivEmotion = [8]
var model = function(){
var gaussianMean = uniform(0,10) //prior
var gaussianSd = uniform(0, 10) //prior
var obsFn = function(datum){ observe(Gaussian({mu: gaussianMean,
sigma: gaussianSd}), datum) }
mapData({data: indivEmotion}, obsFn)
return gaussianMean
}
var estimateColEmotion = Infer({method:'MCMC', samples: 100, lag: 100, burn: 5},model)
print('Expected average is: ' + expectation(estimateColEmotion))
expectation(estimateColEmotion)
viz(estimateColEmotion)
@hawkrobe
Copy link

hawkrobe commented Nov 8, 2016

Awesome! I think the trick to get an individual emotion from the group is to build it all into a single model. Basically, instead of just returning beliefs about the group mean, you want to also return the individual's belief about themselves. This is where your theory about a person's bias goes (I called it "decisionRule" in the code below, and instantiate a naive function where you're one standard deviation toward the extreme from the inferred group mean)

var groupEmotions = [5,3,5,6,7,6,7]
var decisionRule = function(groupMean, groupSd) {
  return (groupMean > 5 ? groupMean + groupSd : groupMean - groupSd);
};

var model = function(){
  // uninformative prior over group beliefs
  var groupMu = uniform(0,10) //prior
  var groupSigma = uniform(0, 10) //prior

  // observe data about their ratings
  var obsFn = function(datum){observe(Gaussian({mu: groupMu, sigma: groupSigma}), datum)}
  mapData({data: groupEmotions}, obsFn)

  // determine your own response based on beliefs about the group
  var response = decisionRule(groupMean, groupSd)

  // force your response to be on the scale
  condition(response < 10 && response > 0)

  // return beliefs about both the group and the self, so we can compare
  return {group: groupMean, response: response}
}

var posterior = Infer({method:'MCMC', samples: 500, lag: 50, burn: 5},model)
viz(posterior)
viz.marginals(posterior)

@hawkrobe
Copy link

This is really close to what we talked about!

The main difference is that rather than just using the (inferred) group distribution as a prior for your own observation, you assume your data is a noisy observation of the true emotion. See below for the slightly refactored version of this model. I also added in uncertainty over whether you belong to the group or not, which I think might be needed to get that phenomenon of drift toward/away from the group.

var data = {self: 1, group : [5,5,6,7,8,9]}

var model = function(){
  // uninformative prior over group beliefs
  var groupMean = uniform(0,10) //prior
  var groupSd = uniform(0, 10) //prior
  
  // estimate groupmean and sd considering the group
  mapData({data: data.group}, function(datum){
    observe(Gaussian({mu: groupMean, sigma: groupSd}), datum)
  })

  // use group dist as true emotion prior if you belong; otherwise uninformative
  var belong = flip()
  var trueEmotionPrior = (belong ? 
                          Gaussian({mu: groupMean, sigma: groupSd}) : 
                          Uniform({a: 0, b: 10}))
  
  // data about self is noisy observation from true emotion prior
  var trueEmotion = sample(trueEmotionPrior);
  condition(trueEmotion < 10 && trueEmotion > 0)
  observe(Gaussian({mu: trueEmotion, sigma: 1}), data.self)
  
  // return beliefs about both the group and the self, so we can compare
  return {groupMean, trueEmotion, belong}
}

var posterior = Infer({method:'MCMC', samples: 1000, lag: 100, burn: 5},model)
viz.marginals(posterior)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment