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<int>().Named("bag1")
let mutable bag2 = Variable.New<int>().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<Bernoulli>(``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 IReadOnlyList<'T>
    interface IReadOnlyCollection<'T>
    interface IEnumerable
    interface IEnumerable<'T>
    member GetReverseIndex : rank:int * offset:int -> int
    member GetSlice : startIndex:int option * endIndex:int option -> 'T list
    member Head : 'T
    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
Raw view Test code New version

More information

Link:http://fssnip.net/84s
Posted:3 months ago
Author:Faisal Waris
Tags: #applicatives , bayestheorem , inference , infer.net