probmods / webchurch

A Church to Javascript compiler (DEPRECATED)
Other
140 stars 15 forks source link

Stick breaking within mh-query #71

Closed null-a closed 9 years ago

null-a commented 9 years ago

I noticed that the following code produces different results under webchurch and bher.

(define (pick-a-stick sticks J)
  (if (flip (sticks J))
      J
      (pick-a-stick sticks (+ J 1))))

(define (make-sticks alpha)
  (let ((sticks (mem (lambda (x) (beta 1.0 alpha)))))
    (lambda () (pick-a-stick sticks 1))))

(define my-sticks (make-sticks 1))

(define samples (mh-query
 1000 1
 (my-sticks)
 #t))

(hist samples)

Under webchurch each execution looks like several draws from a DP. Under bher the result is (approximately) a geometric distribution which is what I expected. I'm not sure whether I'm missing something or whether this perhaps points to a bug.

I ran the code under bher via this page. The beta procedure returns a list under bher so following the example on the linked page I used the following version of make-sticks.

(define (make-sticks alpha)
  (let ((sticks (mem (lambda (x) (first (beta 1.0 alpha))))))
    (lambda () (pick-a-stick sticks 1))))
longouyang commented 9 years ago

It looks like webchurch gives the same result as bher when you move the defines into the query, i.e.,

(define samples
  (mh-query
   1000 1

   (define (pick-a-stick sticks J)
     (if (flip (sticks J))
         J
         (pick-a-stick sticks (+ J 1))))

   (define (make-sticks alpha)
     (let ((sticks (mem (lambda (x) (beta 1.0 alpha)))))
       (lambda () (pick-a-stick sticks 1))))

   (define my-sticks (make-sticks 1))             

   (my-sticks)
   #t))

(hist samples)

I suspect that webchurch's implementation of mem is causing the issue. mem in this setting should be localized to the environment of a specific mh step, but this might be getting screwed up (in webchurch) when the mem'd function is defined outside the mh call.

I'll investigate and report back in a day or two.

Thanks for catching this!

null-a commented 9 years ago

Makes sense, thanks!

longouyang commented 9 years ago

Okay, it looks like my guess was right -- it's that mem behaves differently inside a query versus out.

Andreas (@stuhlmueller) thinks that this behavior is actually more sensible: that if you want to use mem inside inference, you need to express this in the scoping of your code.

stuhlmueller commented 9 years ago

Yup. If you call make-sticks outside of the query scope, and thus create memoized functions there, those functions will store mem state across mh iterations. This is generally not what you want, so they need to created within query scope.