駆け足で読む『確率とモナドと確率論的プログラミング』

  • 記事
  • ぱらぱらとめくるには、Haskellの理解が浅すぎて無理なので、がんばって読む(が時間は掛けられない)
  • 読みながら気になったこと、調べたこと、等をメモしていく
  • 確率変数を扱いたい。確率変数はいろいろな値をとる変数なので、有限・無限集合。これをリストモナドとして扱うことは出来る
  • 確率分布は?
    • 確率分布とは、確率事象空間と、その空間に非負の値が張り付いたもの
    • したがって、事象と確率質量/確率密度のペア、これの集合
    • これを新たなデータ型とする
  • 確率質量関数・確率密度関数というのは、事象から実数への関数に相当する
  • Functor/Applicative/Monad
    • 確率分布は「事象と値のペアの集合」になっている。「集合」のカッコで包まれているので、その集合構造を保ったまま、中の事象やら、確率質量・密度やらをいじるには、Functor,Applicative,Monadなどの仕組みを使うのがよい
  • Functor
    • Functorは「集合の要素(事象と値のペア)」に触って、それを変更して、「集合」を返す仕組み
    • 確率変数X1に確率の値がくっついているときに、確率変数X1から確率変数X2に変換する関数を定めて、確率値はそのままにする、というような処理ができるようになる
    • ただし、こんなことに注意するべき
    • χ分布をχ二乗分布に変換することを考える
    • 確率というのは、確率変数の微小変化の幅の分の積分に「確率」としての意味があるので、X1→X2=X1^2という変換をして、確率値を変えないと、積分して1、という原則を守ることができない
    • f(X1) dX1 = g(X2=X1^2) dX2という変換であって、\frac{dX2}{dX1} = 2X1を考慮しないといけない
    • この変換は、X1->X2、確率値はそのまま、というFunctor処理をした後に、確率値をX2の値に応じて修正する、という処理をすることで、確率分布の事象空間の変数変換を実現することが出来る
    • Functorの肝は、fmap関数が定義されていることで、fmapのエイリアスは(<$>)であり、中置演算子として使うときは、(<$>) a b が a <$> b のことであることも忘れずにおく
  • Applicative
    • 以下の対応を見ると、Functorとの異同が見える
type Prob = Double
newtype Dist a = Dist [(a,Prob)]
instance Functor Dist where
  (<$>) f (Dist as) = Dist [(f a,p) | (a,p) <- as]

instance Applicative Dist where
  pure x = Dist [(x,1.0)]
  (<*>) (Dist bs) (Dist as) = Dist [(b a,q*p) | (b,q) <- bs, (a,p) <- as]
    • Dist aは、事象空間を型変数 a で表しているように、いろいろ代えられるように作ってあるが、Probの方は型が固定してある。したがって、Applicativeでは型変換に対応するほうにいわゆる関数が作用していて、Probの方は型を変えることを許さない演算(この場合はProb同士の掛け算)が定義として採用されている。q*pの代わりにq+pにしてもよいが、q*pにすると、以下のような、同時分布定義が出来るから*がよいかもしれない。それは、確率は「独立なときは積」という代物なので、「積」を使っておくのは、意味がある
joint :: Dist a -> Dist b -> Dist (a,b)
joint da db = (,) <$> da <*> db
    • 呪文のような定義式だ・・・
    • <$> と <*> とはどちらも中置演算子であって、以下に示されるように、infixl (左作用型)の優先順位4番である。<*>も左作用型で4番なので、
Prelude> :i <$>
(<$>) :: Functor f => (a -> b) -> f a -> f b
        -- Defined in ‘Data.Functor’
infixl 4 <$>
    • 優先順位がわかるように括弧を加えると以下のようになる
joint da db = ((,) <$> da )<*> db
    • (,)というのは、(,) a b = (a,b)なので、((,) <$> da) は d ((,) a) というように、ペアの2番目要素を待っている状態の関数
    • 結局、(a,b)なる事象に対して、p*qなる積で決まる確率値が与えられた分布となり、それは「同時分布」
  • Monad
    • Monadは結局、モナドがあって、そのモナドモナドというものを考えたいが、そうするとモナド入れ子がすごいことになるので、モナドの多重入れ子を1重にしたい、という仕組み
    • 確率分布の文脈で言うと、確率分布をたくさん集めて確率分布の集合にして、それに確率や尤度を付与したものが「確率分布」として処理したいよね、と言う話で、情報幾何による、確率分布を座標として表して、確率分布集合を多様体として現したときに、その確率分布集合多様体に確率を乗せて、それを確率分布としてみるよ、ということに対応する(たぶん)