スタートページ> 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]])
このモデルは単純なわりに、適用できる分野が広く、実用性が高いように思われます。
ところがこの 事後確率計算関数 を実務で利用するのは不適切です。
これらの対策を講じたモデルが多数公開されていますが、その内部構造はかなり複雑なようです。