// total number of marbles drawn from urn every time
var nMarbles = 8;
var threshold = .6;
// example data point for self
var selfData = 4;
// example data point for others
var otherData = [{prediction: 'red', confidence: 'high'},
{prediction: 'red', confidence: 'high'},
{prediction: 'blue', confidence: 'low'},
{prediction: 'blue', confidence: 'low'}];
// (discretized) uniform distribution over actual proportion of red in urn
var rednessPrior = Categorical({vs: [0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1]});
/*
Generative model of other agents
Assumes they are *also* doing inference about actual proportion
based on their data and responding according to their best guess...
*/
var otherOutput = cache(function(kRed, threshold) {
return Infer({method: 'enumerate', model: function() {
var pRed = sample(rednessPrior);
var prediction = flip(pRed) ? 'red' : 'blue';
var highConf = prediction === 'red' ? pRed >= threshold : pRed <= 1 - threshold;
observe(Binomial({p: pRed, n: nMarbles}), kRed);
return {prediction: prediction, confidence: highConf ? 'high' : 'low'}
}});
})
/*
Model of participant's inference on a given trial
*/
var trialModel = function() {
// participant is trying to infer latent distribution in urn
var pRed = sample(rednessPrior);
// first, take into account own data (i.e. a draw of balls from urn)
observe(Binomial({p: pRed, n: nMarbles}), selfData);
// next, take into account social information
// assume their sample was drawn from sample population but not sure of exact data
mapData({data: otherData}, function(datum) {
var kSeenPrior = Binomial({p: pRed, n : nMarbles});
var likelihood = expectation(kSeenPrior, function(k) {
return otherOutput(k, threshold).score(datum)
})
factor(likelihood);
})
// ugly js convert to string for pretty plots
return pRed + "";
}
viz.hist(Infer({method: 'enumerate', model: trialModel}))