Latent Dirichlet allocation applies here to sequences of agent actions, treating each agent as a mixture over hidden groups and each group as its own distribution over actions. Given five agents’ observed action histories, inference recovers agent1’s posterior distribution over which groups its behavior draws from.
// Parameters
var actions = ['a', 'b', 'c', 'd'];
var groups = {
'group1': null,
'group2': null
};
var agents = {
'agent1': 'a b a b a d a b a b a c'.split(' '),
'agent2': 'c a c d c d c d c b c d'.split(' '),
'agent3': 'a b a b a b a b a b a b'.split(' '),
'agent4': 'c d c d c d c d c d c d'.split(' '),
'agent5': 'a b a b a b a b a b a c'.split(' ')
};
// Constants and helper functions
var ones = function(n) {
return repeat(n, function() {return 1.0;});
}
// Model
var makeActionDist = function() {
return dirichlet(ones(actions.length));
};
var makeGroupDist = function() {
return dirichlet(ones(_.size(groups)));
};
var discreteFactor = function(vs, ps, v) {
var i = indexOf(v, vs);
factor(Math.log(ps[i]));
}
var model = function() {
var actionDistForGroup = mapObject(makeActionDist, groups);
var groupDistForAgent = mapObject(makeGroupDist, agents);
var makeGroupForAction = function(agentName, word) {
var i = discrete(groupDistForAgent[agentName]);
return _.keys(groups)[i];
};
var makeActionGroups = function(agentName, actions) {
return map(function(action) {return makeGroupForAction(agentName, action);},
actions);
};
var groupsForAgent = mapObject(makeActionGroups, agents);
mapObject(
function(agentName, agentActions) {
map2(
function(group, action) {
discreteFactor(actions, actionDistForGroup[group], action);
},
groupsForAgent[agentName],
agentActions);
},
agents);
// console.log(actionDistForGroup);
return groupDistForAgent.agent1
};
vizPrint(MH(model, 10000))