Probabilistic programming in clojure

516 views
Skip to first unread message

Nils Bertschinger

unread,
Nov 17, 2011, 12:57:01 PM11/17/11
to Clojure
Hi everyone,

inspired by the bher compiler for the probabilistic scheme dialect MIT
Church, I have implemented a version of the probability monad which
uses Metropolis Hastings to draw samples from runs of monadic
programs. You can find the code on github: https://github.com/bertschi/ProbClojureNice.

The monadic version is more a proof of principle and not very fast. It
might nevertheless be useful, e.g. for educational purposes. Have a
look and decide for yourself ...
For the future, I'm working on a different approach to embed
probabilistic operations into clojure which scales better and allows
to run somewhat larger models.

Any comments and feedback are welcome. Best,

Nils

Konrad Hinsen

unread,
Nov 17, 2011, 3:58:57 PM11/17/11
to clo...@googlegroups.com
On 17 nov. 2011, at 18:57, Nils Bertschinger wrote:

> inspired by the bher compiler for the probabilistic scheme dialect MIT
> Church, I have implemented a version of the probability monad which
> uses Metropolis Hastings to draw samples from runs of monadic
> programs. You can find the code on github: https://github.com/bertschi/ProbClojureNice.

There's also this one in clojure-contrib (old, not yet moved to the new contrib collection):

https://github.com/richhickey/clojure-contrib/tree/master/src/main/clojure/clojure/contrib/probabilities

Konrad.

Nils Bertschinger

unread,
Nov 17, 2011, 6:09:11 PM11/17/11
to Clojure
Hi Konrad,

thanks for the link. I know your very nice library and actually use
clojure.contrib.monads to implement my probability monad.
The two approaches are somewhat complementary to each other. Your
monad does exact inference on discrete distributions by running
through all possibilities. Mine is sampling based and does approximate
inference using MCMC. This makes it feasible to simulate larger
discrete models and also continuous distributions can easily be
incorporated. In the demos section you can find a Gaussian mixture
model demonstrating these features.

Nils

On Nov 17, 9:58 pm, Konrad Hinsen <googlegro...@khinsen.fastmail.net>
wrote:
> There's also this one in clojure-contrib (old, not yet moved to the new contrib collection):
>
>        https://github.com/richhickey/clojure-contrib/tree/master/src/main/cl...
>
> Konrad.

Konrad Hinsen

unread,
Nov 18, 2011, 2:05:28 AM11/18/11
to clo...@googlegroups.com
--On 17 novembre 2011 15:09:11 -0800 Nils Bertschinger
<nils.ber...@googlemail.com> wrote:

> The two approaches are somewhat complementary to each other. Your
> monad does exact inference on discrete distributions by running
> through all possibilities. Mine is sampling based and does approximate
> inference using MCMC.

I tried that approach as well:


https://github.com/richhickey/clojure-contrib/blob/master/src/main/clojure/clojure/contrib/probabilities/monte_carlo.clj

but I never used it much because for my own applications, exact inference
was very doable. I'll check out yours for comparison!

Konrad.

Nils Bertschinger

unread,
Nov 18, 2011, 6:32:14 PM11/18/11
to Clojure
On Nov 18, 8:05 am, Konrad Hinsen <googlegro...@khinsen.fastmail.net>
wrote:
> --On 17 novembre 2011 15:09:11 -0800 Nils Bertschinger
>
> <nils.bertschin...@googlemail.com> wrote:
> > The two approaches are somewhat complementary to each other. Your
> > monad does exact inference on discrete distributions by running
> > through all possibilities. Mine is sampling based and does approximate
> > inference using MCMC.
>
> I tried that approach as well:
>
> https://github.com/richhickey/clojure-contrib/blob/master/src/main/cl...
>
> but I never used it much because for my own applications, exact inference
> was very doable. I'll check out yours for comparison!

Just checked your implementation, the stream approach is indeed quite
nice to thread random numbers through programs. It seems that I handle
downstream conditioning somewhat different. The stream can basically
be filtered to implement rejection sampling, whereas I thread a
database state through the program to record all random choices (as
well as their probability) that have been taken. That way conditioning
does not have to be based on rejection, but is simply accounted for by
including the probability of the conditioned value. Then I can propose
a change to this database store, re-run the program and implement
Metropolis Hastings sampling on top of this, i.e. test whether the
change increased the probability of the random decisions taken
throughout the program and either accept or reject it accordingly.
Your stream approach can probably be nicely extended to particle
filters. I'll think about that ...

Nils
>
> Konrad.

Konrad Hinsen

unread,
Nov 19, 2011, 12:28:55 PM11/19/11
to clo...@googlegroups.com
On 19/11/11 00:32, Nils Bertschinger wrote:

> downstream conditioning somewhat different. The stream can basically
> be filtered to implement rejection sampling, whereas I thread a
> database state through the program to record all random choices (as
> well as their probability) that have been taken.

Right, your approach is very different. There are many ways to skin this
cat...

Konrad.

Jeff Rose

unread,
Nov 19, 2011, 11:32:01 PM11/19/11
to Clojure
Cool!  I experimented a little bit with Church a while back, but
having something like this in Clojure could be really interesting.  I
don't have much experience with sampling, but if I understand it
correctly, your grass-is-wet demo is defining a belief network where
each sample taken represents the complete state of the graph, or just
the final outcome?  What does a sample look like?  It would be great
if we could use this kind of generative model to create chord
sequences, melodies, and rhythms for Overtone.  I don't know what
kinds of choice points would be appropriate, or if we could train them
based on a database of existing progressions?
-Jeff
On Nov 18, 12:57 am, Nils Bertschinger

Julius Seporaitis

unread,
Nov 20, 2011, 11:58:41 AM11/20/11
to clo...@googlegroups.com
Hello guys,

I would like to try out this library, but ran into a problem with Clojure 1.3, 'lein repl' throws an exception, when:

user=> (use 'probabilistic-clojure.monadic.demos)
user=> (test-mixture mixture-mem)                
Trying to find valid trace ...
Starting MH-sampling.
IllegalArgumentException No value supplied for key: 0.7  clojure.lang.PersistentHashMap.createWithCheck (PersistentHashMap.java:89)

I am a total beginner with Clojure, if you could provide a at least a hint of how to resolve this - I'd appreciate it.

P.S. I am using the "1.3" branch by Jeff, that works with Leiningen.

Thanks!

- Julius


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Nils Bertschinger

unread,
Nov 21, 2011, 6:19:13 AM11/21/11
to Clojure
Hi Jeff,

good idea to move this over to clojure 1.3. I have just included your
patch.

On Nov 20, 5:32 am, Jeff Rose <ros...@gmail.com> wrote:
> Cool!  I experimented a little bit with Church a while back, but
> having something like this in Clojure could be really interesting.  I
> don't have much experience with sampling, but if I understand it
> correctly, your grass-is-wet demo is defining a belief network where
> each sample taken represents the complete state of the graph, or just
> the final outcome?  What does a sample look like?  It would be great
> if we could use this kind of generative model to create chord
> sequences, melodies, and rhythms for Overtone.  I don't know what
> kinds of choice points would be appropriate, or if we could train them
> based on a database of existing progressions?

The grass-is-wet demo indeed specifies a belief network. In contrast
to Church, the definition of the model, conditioning on observations
and specifying the output variables is all done in one path. This
works exactly like the probability monad in clojure.contrib. Thus,
each sample corresponds to an outcome of the output variables, i.e.
"rain" in the example. Since the model is conditioned on "grass-is-wet
= true", using m-zero of the monad implements rejection sampling, you
obtain samples of the posterior distribution p(rain | grass-is-wet =
true).
In principle it should be possible to use it for generative models of
music. Since I'm not an expert in this area, I don't know which kind
of models and probability distributions are useful to describe musical
structure. Let me know if you have an idea, I would be happy to help
putting it into clojure.

Best,

Nils

Nils Bertschinger

unread,
Nov 21, 2011, 6:20:38 AM11/21/11
to Clojure
Hi Julius,

good catch, I don't know how I missed that???
Just uploaded a fix ... should work now.

Nils

On Nov 20, 5:58 pm, Julius Seporaitis <jul...@seporaitis.net> wrote:
> Hello guys,
>
> I would like to try out this library, but ran into a problem with Clojure
> 1.3, 'lein repl' throws an exception, when:
>

> *user=> (use 'probabilistic-clojure.monadic.demos)*
> *user=> (test-mixture mixture-mem)                *
> *Trying to find valid trace ...*
> *Starting MH-sampling.*
> *IllegalArgumentException No value supplied for key: 0.7
>  clojure.lang.PersistentHashMap.createWithCheck (PersistentHashMap.java:89)*

Reply all
Reply to author
Forward
0 new messages