4 people like it.

Bayesian Inference with Infer.Net: M&M problem

Solve a sample problem from the book "Think Bayes" by Allen B. Downey. Shows how the problem can be modeled with Infer.Net and also provide the manual solution as presented in the book. The code relies on the Infer.Net "FSharpWrapper" project which is not included in the nuget package (as of now).

 ``` 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: ``` ``````(* In 1995, they introduced blue M&M’s. Before then, the color mix in a bag of plain M&M’s was 30% Brown, 20% Yellow, 20% Red, 10% Green, 10% Orange, 10% Tan. Afterward it was 24% Blue, 20% Green, 16% Orange, 14% Yellow, 13% Red, 13% Brown. Suppose a friend of mine has two bags of M&M’s, and he tells me that one is from 1994 and one from 1996. He won’t tell me which is which, but he gives me one M&M from each bag. One is yellow and one is green. What is the probability that the yellow one came from the 1994 bag? Downey, Allen B.. Think Bayes . O'Reilly Media. Kindle Edition. *) #r "nuget: Microsoft.ML.Probabilistic.Compiler.Visualizers.Windows" #r @"../FsharpWrapper/bin/Debug/net48/Microsoft.ML.Probabilistic.FSharp.dll" //need to compile this from infer.net source open Microsoft.ML.Probabilistic.Models open Microsoft.ML.Probabilistic.FSharp open Microsoft.ML.Probabilistic.Distributions type Cls = Br | Bl | Y | R | G | T | O let check ls = (ls |> List.sumBy snd) - 1.0 |> abs < 0.000000001 let ``1994 mix`` = [Br, 0.3; Y, 0.2; R, 0.2; G, 0.1; O, 0.1; T, 0.1; Bl, 0.0] let ``1996 mix`` = [Br,0.13; Y,0.14; R,0.13; G,0.20; O,0.16; T, 0.0; Bl,0.24] check ``1994 mix`` check ``1996 mix`` let bag94Mix() = ``1994 mix`` |> Seq.map snd |> Seq.toArray |> Variable.Discrete let bag96Mix() = ``1996 mix`` |> Seq.map snd |> Seq.toArray |> Variable.Discrete let mutable bag1 = Variable.New().Named("bag1") let mutable bag2 = Variable.New().Named("bag2") let ``p(bag1=94)`` = Variable.Bernoulli(0.5).Named("p(bag1=94)") Variable.IfBlock ``p(bag1=94)`` (fun _ -> bag94Mix() |> bag1.SetTo; bag96Mix() |> bag2.SetTo) (fun _ -> bag96Mix() |> bag1.SetTo; bag94Mix() |> bag2.SetTo) bag1.ObservedValue <- 1 //Y bag2.ObservedValue <- 3 //G let ie = InferenceEngine() ie.ShowFactorGraph <- true //need to install graphviz s.t. 'dot' command is available let ``p(bag1=94)_posterior`` = ie.Infer(``p(bag1=94)``) //, Microsoft.ML.Probabilistic.QueryTypes.Samples) module ManualMethod = //manual approach using the 'table' method (see book ref above) let ``p(bag1=94)`` = 0.5 let ``p(H|D,bag1=94)`` = 0.2 * 0.2 //likelihoods let ``p(H|D,bag1=96)`` = 0.14 * 0.1 let caseA_unormailzied = ``p(bag1=94)`` * ``p(H|D,bag1=94)`` let caseB_unormalized = (1.0 - ``p(bag1=94)``) * ``p(H|D,bag1=96)`` let ``p(D)`` = caseA_unormailzied + caseB_unormalized let ``p(D|H,bag1=94)`` = caseA_unormailzied / ``p(D)`` ``````
namespace Microsoft
type Cls =
| Br
| Bl
| Y
| R
| G
| T
| O
union case Cls.Br: Cls
union case Cls.Bl: Cls
union case Cls.Y: Cls
union case Cls.R: Cls
union case Cls.G: Cls
union case Cls.T: Cls
union case Cls.O: Cls
val check : ls:('a * float) list -> bool
val ls : ('a * float) list
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetReverseIndex : rank:int * offset:int -> int
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
...
val sumBy : projection:('T -> 'U) -> list:'T list -> 'U (requires member ( + ) and member get_Zero)
val snd : tuple:('T1 * 'T2) -> 'T2
val abs : value:'T -> 'T (requires member Abs)
val ( 1994 mix ) : (Cls * float) list
val ( 1996 mix ) : (Cls * float) list
val bag94Mix : unit -> 'a
module Seq

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
val toArray : source:seq<'T> -> 'T []
val bag96Mix : unit -> 'a
val mutable bag1 : obj
Multiple items
val int : value:'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val mutable bag2 : obj
val ( p(bag1=94) ) : obj
val ie : obj
val ( p(bag1=94)_posterior ) : obj
module ManualMethod

from Script
Multiple items
val ( p(bag1=94) ) : float

--------------------
val ( p(bag1=94) ) : obj
val ( p(H|D,bag1=94) ) : float
val ( p(H|D,bag1=96) ) : float
val caseA_unormailzied : float
val ( p(bag1=94) ) : float
val caseB_unormalized : float
val ( p(D) ) : float
val ( p(D|H,bag1=94) ) : float