スタートページ> JavaScript> 他言語> R 目次
ベイズ推定(Bayesian inference)とは、事前に設定された確率データ(事前確率行列)があり、そのうちの幾つかが実現したとき、そをの起因事象を推定する(事後確率を求める)という確率の方法で、ベイズの定理に基づいています。
首輪 | 木の上 | 二足直立 | |
ネコ | 0.7 | 0.5 | 0.2 |
イヌ | 0.8 | 0.1 | 0.3 |
サル | 0.2 | 0.9 | 0.8 |
クマ | 0.1 | 0.1 | 0.6 |
合計 | 1.8 | 1.6 | 1.9 |
第1表のような事前確率行列があります。例えば、都会ではネコが首輪をしている確率は 0.7、イヌを木の上で見かける確率は 0.1、サルが二足直立をしている確率は 0.8 であることが、何らかの調査でわかっている(どんな調査?)とします。
あるとき、首輪をしている動物を木の上にいるのを見かけました(これが実現特性です)。この動物が何であるかを統計的に知りたい(事後確率)のです。
<首輪 | 木の上 | 二足直立 | |
ネコ | 0.389 | 0.313 | 0.105 |
イヌ | 0.444 | 0.063 | 0.158 |
サル | 0.111 | 0.563 | 0.421 |
クマ | 0.056 | 0.063 | 0.316 |
合計 | 1 | 1 | 1 |
「首輪をしていた」という事実だけがあったとします。第1表の「首輪」の列だけが対象になります。これだけでも最もありそうなのはイヌだとわかります。
しかし、事後確率という考え方では「首輪をしていた」とは、この列の合計行の値が「確率=1」になったのですから、そうなるように各列を合計で割る操作をします(第2表)。
首輪 | 木の上 | 首*木 | 修正 | |
ネコ | 0.7 | 0.5 | 0.35 | 0.565 |
イヌ | 0.8 | 0.1 | 0.08 | 0.129 |
サル | 0.2 | 0.9 | 0.19 | 0.290 |
クマ | 0.1 | 0.1 | 0.01 | 0.016 |
合計 | 0.215 | 1 |
「首輪をしている動物が木の上にいるのを見た」場合です。
「首輪~」と「木の上~」は互いに独立の事象ですから、「首輪~、かつ、木の上~」の確率は、両者の積になります。
そして、「実現特性が一つのとき」と同様に合計を1になるように修正すると第3表になります。
これより、
ネコ 56.5%
サル 29.0%
などが得られます。
# ============ 入力データ 事前確率行列 <- matrix(c(0.7, 0.5, 0.2, # ネコ 0.8, 0.1, 0.3, # イヌ 0.2, 0.9, 0.8, # サル 0.1, 0.1, 0.6), # クマ nrow=4, byrow=T) 実現特性 <- c(1, 2) # 1(首輪)、2(木の上)を見た # ============= 事後確率の計算 # ====== 作業変数 行数 <- nrow(事前確率行列) 列数 <- ncol(事前確率行列) 合計行 <- matrix(0, nrow=1, ncol=列数) 事後確率列 <- matrix(1, nrow=行数, ncol=1) # ====== 計算 for (特性列 in 実現特性){ 合計行[特性列] <- sum(事前確率行列[ , 特性列]) 事後確率列 <- 事後確率列 * 事前確率行列[ , 特性列] / 合計行[特性列] } 事後確率列合計 <- sum(事後確率列) 事後確率列 <- 事後確率列 / 事後確率列合計 事後確率列 # ============== 結果出力 順位 <- order(-事後確率列) sprintf("%d, %8.3f", 順位[1],事後確率列[順位[1]]) sprintf("%d, %8.3f", 順位[2],事後確率列[順位[2]])
# 事後確率列 # 0.56451613 # 0.12903226 # 0.29032258 # 0.01612903 # 結果出力 1 0.565' 3 0.290'
上のプログラムで「事後確率の計算」がこのロジックの中核であり、入力データの影響を受けないので、関数にしてみました。この事後確率計算関数をライブラリにしておけば、この部分を記述する必要はありません。
# ============= 事後確率の計算 事後確率計算関数 <- function(事前確率行列, 実現特性) { 行数 <- nrow(事前確率行列) 列数 <- ncol(事前確率行列) 合計行 <- matrix(0, nrow=1, ncol=列数) 事後確率列 <- matrix(1, nrow=行数, ncol=1) for (特性列 in 実現特性){ 合計行[特性列] <- sum(事前確率行列[ , 特性列]) 事後確率列 <- 事後確率列 * 事前確率行列[ , 特性列] / 合計行[特性列] } 事後確率列合計 <- sum(事後確率列) 事後確率列 <- 事後確率列 / 事後確率列合計 return(事後確率列) } # ============ 入力データ (これ以降を記述するだけでよい) 事前確率行列 <- matrix(c(0.7, 0.5, 0.2, 0.8, 0.1, 0.3, 0.2, 0.9, 0.8, 0.1, 0.1, 0.6), nrow=4, byrow=T) # ============ 関数の利用 事後確率列 <- 事後確率計算関数(事前確率行列, c(1,2)) 事後確率列 順位 <- order(-事後確率列) sprintf("%d, %8.3f", 順位[1],事後確率列[順位[1]]) sprintf("%d, %8.3f", 順位[2],事後確率列[順位[2]])
このモデルは単純なわりに、適用できる分野が広く、実用性が高いように思われます。
ところがこの 事後確率計算関数 を実務で利用するのは不適切です。
これらの対策を講じたモデルが多数公開されていますが、その内部構造はかなり複雑なようです。