Haskellで確率モデル(書き直し)

  • ここ数日間の記事は、調べ物をしながらのメモの堆積物のようになってしまった
  • もう一度、全体を見渡して、整理しよう
  • 確率モデルとは
    • 一般化して考えたい
    • 特にパラメトリックモデルもノンパラメトリックモデルも併せて考えたい
    • パラ、ノンパラは、パラメタの個数が有限なものと、無限(になりうる)ものとの違いである
    • いずれにしろ、すべての確率モデルは
      • 事象空間 Xがあったときに
      • それに確率をくっつけたProbability Measures on Xの空間PM(X)を考えて
      • その部分集合 M \subset PM(X)を確率モデルと呼び
      • M = \{P_{\mathbf{\theta}} | \mathbf{\theta} \in T\}のように表現することにする
      • ただしTはパラメタの空間であり
      • Tの次元が有限ならパラメトリックモデル、無限ならノンパラメトリックモデルを指す
  • 確率モデルを定義する
    • 確率モデルを計算機に教える(特異的にこれだ、と定義を授ける)
    • 確率モデルには、事象空間Xとモデル空間Mとその表現であるところの\mathbf{\theta}パラメタ空間がある(パラメタが張る空間Tもある)
    • 今、X,M,\mathbf{\theta},Tのすべてを授けてやってもよいが
    • \mathbf{\theta}インスタンスが、X,M,Tを『知って』いるものと考えれば、規定するべきは
    • \mu( \mathbf{\theta}  )という、\mathbf{\theta}を持ったモデル\mu
    • Haskellの確率的プログラミングの記事では、この\mu
Dist a where
  Pure :: a -> Dist a
    • として定義している。
    • aをパラメタとして、パラメタでindexedされた確率モデル集合のことである
    • aを何でもありにせず、ParameterVectorタイプのようなものを作って、それにしておくのもよいのではないかと思い
    • たとえば、「1次元正規分布という確率モデルのパラメタ」として定義し、その中身は、(Double, Double)である、というようなやり方である
  • 確率モデルの代数的世界を作る
    • (単純な)確率モデルは上記のようにPureを使って作れる。このモデルは単一の事象空間X上を使っているモデルである
    • 確率モデルは異なる事象空間X_i,X_jを用いて定義することも出来る
    • 二つの異なる事象空間にある確率モデルの間をつなぐ関数によって、X_i上の確率モデルからX_j上の確率モデルに変換することを可能にすると、その変換全体が「確率モデル」になる
    • それをBind(モナドの仕様)で実現している
    • a, bのそれぞれがX_i,X_jに対応する
data Dist a where
  Bind :: Dist b -> (b -> Dist a) -> Dist a
  • 確率モデルの修飾
    • 確率モデルは、パラメタでindexedして表現されている
    • パラメタにどんな値を持たせるのが「よい」かということを考えない限り、何もする必要はないが
    • いったん、そのことを気にするとすると、それは『重みで修飾』することになる
    • 『重み修飾』とは、パラメタの具体的な値に関して非負の重み値を付与すること
    • この『重み修飾』は、パラメタ空間への非負値付けなので、「分布関数のようなもの」でもある
    • また、元の確率モデルを「ある観察をする確率関数を定めたもの」と考えれば、それに、『重み修飾』をする、とは、個々の確率関数を重みで大小をつけて、「起き易さ・起き難さ」を関数の積として表現したもの、と言える
    • 実際、以下のConditionalはそのような作りになっている
data Dist a where
  Conditional :: (a -> Prob) -> Dist a -> Dist a
  • 作成した確率モデルの利用
    • 確率の計算
      • モデルがあったら、パラメタ値を具体的に決め、観察事象を具体的に決めると、その生起確率・観測尤度が計算できる
      • 上記のConditionalの使い方だと、必ずしも、「積分して1」になるという意味での、生起確率は算出できないが、相対的なそれは計算できる
      • 尤度比計算、メトロポリスヘイスティングなど、相対値のみが必要ならば、これでよい
    • 乱数の発生
      • これは難しい…
      • 実装されていないことからも解る
instance Sampleable Dist IO a where
  sampleFrom _ (Conditional _ _) = undefined
    • 事後分布推定
      • メトロポリスヘイスティングがそれ
      • Conditionalで修飾された条件付き確率モデルの相対的生起確率が計算できるように、priorという関数を作っている
      • 以下のコードの Dist ( a, Prob ) のProbというのがモデルのパラメタの値がこれこれのときにProbなる尤度である、ということを表している
      • 何の条件も無ければ、「尤度は1からスタート」とも定義してある。これは、事前分布がパラメタのとりかたaの変数設定において一様、という前提での実装である
prior :: Dist a -> Dist (a, Prob)
prior (Conditional c d) = do
  (x,s) <- prior d
  return (x, s * c x)
prior (Bind d f) = do
  (x,s) <- prior d
  y <- f x
  return (y,s)
prior d = do
  x <- d
  return (x,1)
  • 確率モデルの積
    • 確率変数モデルと確率モデルの同時確率モデルというものもあるだろう。それには、ここに書いたようなApplicativeを用いた、Dist a -> Dist b -> Dist (a,b)のような仕組みを入れればよい