Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Embedded Probabilistic Programming

Embedded Probabilistic Programming

Ryosuke TAKASHIMA

June 30, 2010
Tweet

More Decks by Ryosuke TAKASHIMA

Other Decks in Programming

Transcript

  1. ふつうにプログラミング OCamlでふつうに書くとこんな感じ。 モンテカルロ法で解くと47%くらい。 let flip p = dist [(p, true);

    (1.-.p, false)] let grassModel = let rain = flip 0.3 and sprinkler = flip 0.5 in let grass_is_wet = flip 0.9 && rain || flip 0.8 && sprinkler || flip 0.1 in if grass_is_wet then rain else fail()
  2. 確率分布DSL こんなDSLを用意する。(Haskell) type Prob = Float data PM a dist

    :: [(Prob, a)] -> PM a con :: PM Bool -> PM Bool -> PM Bool dis :: PM Bool -> PM Bool -> PM Bool if_ :: PM Bool -> PM a -> PM a -> PM a let_ :: PM a -> (PM a -> PM b) -> PM b
  3. DSLで記述した確率モデル 芝生の例はDSLでこんな風に書ける。 grassModel = let_ (flip_ 0.3) (¥ rain ->

    let_ (flip_ 0.5) (¥ sprinkler -> let_ (dis (con (flip_ 0.9) rain) (dis (con (flip_ 0.8) sprinkler) (flip_ 0.1))) (¥ grassIsWet -> if_ grassIsWet rain (dist []))))
  4. 確率を木構造で表現 T T T X T T X T X

    F F X F F X F X F X F X F X 0.1 0.9 0.2 0.8 0.1 0.9 0.1 0.9 0.1 0.9 0.8 0.2 0.9 0.1 0.5 0.5 0.1 0.9 0.2 0.8 0.1 0.9 0.2 0.8 0.9 0.1 0.1 0.9 0.1 0.9 0.8 0.2 0.9 0.1 0.9 0.1 0.9 0.8 0.2 0.1 0.5 0.5 0.3 0.7 1.0
  5. 木探索でDSLを実装(1) data VC a = V a | C (PV

    a) type PV a = [(Prob, VC a)] type PM a = PV a pvUnit :: a -> PV a pvUnit x = [(1.0, V x)] pvBind :: PV a -> (a -> PV b) -> PV b pvBind m f = map g m where g (p, V x) = (p, C (f x)) g (p, C t) = (p, C (pvBind (t f)))
  6. 木探索でDSLを実装(2) dist ch = map (¥(p,v) -> (p, V v))

    ch con e1 e2 = pvBind e1 (¥v1 -> if v1 then e2 else pvUnit False) dis e1 e2 = pvBind e1 (¥v1 -> if v1 then pvUnit True else e2) if_ et e1 e2 = pvBind et (¥t -> if t then e1 else e2)
  7. CPSでDSLを実装 data VC a = V a | C (PV

    a) type PV a = [(Prob, VC a)] type PM a = (a -> PV Bool) -> PV Bool dist ch k = map (¥(p,v) -> (p, C (k v))) ch con e1 e2 k = e1 (¥v1 -> if v1 then e2 k else k False) dis e1 e2 k = e1 (¥v1 -> if v1 then k True else e2 k) if_ et e1 e2 k = et (¥t -> if t then e1 k else e2 k)
  8. 限定継続の扱いの違い OCaml let rec times lst = match lst with

    [] -> 1 | 0 :: rest -> shift (fun cont -> 0) | first :: rest -> first * times rest Haskell times lst = case lst of [] -> return 1 0 : rest -> shift (¥ cont -> 0) first : rest -> (first *) `liftM` times rest ← 戻り値は数値 ← 戻り値は継続
  9. shift / reset で実装(OCaml) let dist ch = shift (fun

    k -> List.map (fun (p,v) -> (p, C (fun () -> k v))) ch) let neg e = not e let con e1 e2 = e1 && e2 let dis e1 e2 = e1 || e2 let if_ et e1 e2 = if et then e1 () else e2 () let reify0 m = reset (fun () -> pv_unit (m ()))
  10. shift / reset で実装(Haskell) dist ch = shift (¥k ->

    map (¥ (p,v) -> (p, C (k v))) ch) neg = liftM not con = liftM2 (&&) dis = liftM2 (||) if_ et e1 e2 = et >>= (¥t -> if t then e1 else e2) reify0 m = reset (pvUnit `liftM` m) いろいろ余計なものが付いてる
  11. モナドの力 do記法を使うと、擬似的に生のデータを扱える grassModel = do rain <- flip_ 0.3 sprinkler

    <- flip_ 0.5 wetByRain <- flip_ 0.9 wetBySprinkler <- flip_ 0.8 wetByOther <- flip_ 0.1 let grassIsWet = wetByRain && rain || wetBySprinkler && sprinkler || wetByOther if grassIsWet then return rain else dist []
  12. メモして高速化 F T F T F T F T F

    T F T F T F T T F T F T F T F T F T F T F T F T 1回目 2回目 3回目 4回目 5回目 N回までの計算結果を再利用できる