F# で最高事後密度区間 (highest posterior density interval, HPDI) を求めます。
let hpdi mass (values : float list) = let size = List.length values let shift = int <| mass * float size let sorted = List.sort values let width = Seq.map2 (-) (Seq.skip shift sorted) sorted |> Seq.toList let minIndex = Seq.zip (Seq.initInfinite id) width |> Seq.minBy snd |> fst sorted.[minIndex], sorted.[minIndex + shift]
取りうる区間の中でもっとも幅が狭いものを選択しています。
例として標準正規乱数を 100,000 個生成してその 95% HPDI を求めてみます。
let rec normal (random : System.Random) = seq { let u1 = random.NextDouble () let u2 = random.NextDouble () let r = sqrt <| -2.0 * log u1 let theta = 2.0 * System.Math.PI * u2 yield r * sin theta yield r * cos theta yield! normal random } let samples = normal (System.Random ()) |> Seq.take 100000 |> Seq.toList hpdi 0.95 samples |> printfn "%A" // (-1.940508623, 1.96964806)
結果がおよそ (-1.96, 1.96) になっていますね。