Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default score function treats objects as ordered #108

Open
hawkrobe opened this issue May 28, 2015 · 3 comments
Open

default score function treats objects as ordered #108

hawkrobe opened this issue May 28, 2015 · 3 comments

Comments

@hawkrobe
Copy link
Contributor

Suppose you use Enumerate to create an erp with objects in its support:

var uniformDraw = function (xs) {
  return xs[randomInteger(xs.length)];
};

var myERP = Enumerate(function(){
  return uniformDraw([{'a' : 1, 'b' : 2}, {'a' : 2, 'b' : 1}])
})

When you try to look up the score of {'b' : 1, 'a' : 2}, which is equivalent to {'a' : 2, 'b' : 1}, the score function treats the object as ordered. Thus, the following returns null when it should return -0.69

console.log(myERP.score([], {'b' : 1, 'a' : 2}))

This happens because we use json.stringify() to look up the value in makeMarginalERP() instead of something that will properly match objects.

@iffsid
Copy link
Contributor

iffsid commented May 28, 2015

This is something that bit me as well. The way I got around this is to use the object-hash package from npm which computes a sha1 (or md5) hash of the object and keys the map with that hash. The reason I haven't pushed that change into dev is because that hash computation is slow.

One thing that we could do is look at the type, as well as the size where necessary, of the support elements to decide if paying that computation cost will be worth it. Clearly there are cases where this is unavoidable; the only issue is minimizing the impact where it isn't necessary.

Actually, the object-hash way is a little overkill for this particular case, but it has the added bonus of even handling circular references correctly.

@stuhlmueller
Copy link
Member

Here's a workaround that can be used in some cases until we have a more general solution:

var toPairs = function(obj){
  return _.sortBy(_.pairs(obj));
}

var toObject = function(pairs){
  return _.object(pairs);
}

var makeObjectScorer = function(erp) {
  var newERP = Enumerate(function(){
    return toPairs(erp.sample());
  });
  return function(value) {
    return newERP.score([], toPairs(value));
  }
}


// Example:

var myERP = Enumerate(function(){
  return uniformDraw(
    [{'a' : 1, 'b' : 2}, 
     {'b' : 2, 'a' : 1}]
  );
});

var myScoreObject = makeObjectScorer(myERP);

print(Math.exp(myERP.score([], {'a' : 1, 'b' : 2})));  // .5 - wrong
print(Math.exp(myScoreObject({'a' : 1, 'b' : 2})));  // 1 - right

@mhtess
Copy link
Contributor

mhtess commented Mar 14, 2019

Just wanted to bump this as an issue. Here is my minimal example:

var myDist = Infer({model: function(){
  return {a: flip(), b: flip()}
}})

myDist.score({b: true, a: true})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants