ETOOBUSY 🚀 minimal blogging for the impatient
Think Bayes in Raku - Pmf class
TL;DR
A couple of initial classes in Raku to help with following Think Bayes with some Raku code.
In previous post Think Bayes we saw that there’s a free book available (Think Bayes) with code in Python, which I’d like to somehow follow using Raku.
Chapter 2 Computational Statistics introduces class Pmf
; the first
examples can be followed with this basic implementation:
class Pmf {
has %.pmf;
method TWEAK (:%!pmf) {}
method gist () {
return gather {
take '---';
for %!pmf.keys.sort -> $key {
take " «$key» {%!pmf{$key}}";
}
}.join("\n");
}
method total () { return [+] %!pmf.values }
method normalize (Numeric:D $sum = 1) {
my $total = self.total or return;
my $factor = $sum / $total;
%!pmf.values »*=» $factor;
self;
}
method set ($key, $value) { %!pmf{$key} = $value; self }
method increment ($key, $amount) {
%!pmf{$key} += $amount;
return self;
}
method multiply ($key, $factor) {
%!pmf{$key} *= $factor;
return self;
}
method probability ($key) { self.P($key) }
method P ($key) {
die "no key '$key' in PMF" unless %!pmf{$key}:exists;
return %!pmf{$key} / self.total;
}
}
As anticipated, the implementation is basic and functional to following
the examples. As an example, the normalize
method is virtually not
needed because the normalization is always performed on the fly by the
P
method.
We can re-create the cookies example from section 2.2:
my $cookie = Pmf.new(pmf => ('Bowl 1', 1, 'Bowl 2', 1).hash);
$cookie.multiply('Bowl 1', 3/4);
$cookie.multiply('Bowl 2', 1/2);
say 'probability it came from Bowl 1: ', $cookie.P('Bowl 1');
The initialization is done assigning the same value to the two
hypotheses, i.e. Bowl 1
and Bowl 2
. As long as they are the same,
it means that they have the same probability (because probabilities are
calculated by dividing by the total).
Then we do the update phase, where we multiply each of the prior
probabilities by the likelihood that the cookie came from each bowl. At
the end, we print out the upated estimation that the cookie indeed comes
from Bowl 1
.
As it often happens, if you want to play with the code above, there is a local version here - enjoy and I hope it can be of help!