stan で欠測データの相関係数を推定してみた
TRANSCRIPT
Stanで欠測データの 相関係数を推定してみた
@hoxo_m
2014/07/12
自己紹介
• hoxo_m
某ECサイトでデータ分析をやっています
• RPubsRecent
RPubs の新着エントリを流す Twitter Bot
フォロワー 200人達成!
欠測データ(Missing Data)
• とある学校の入学試験の得点 x
• 入学後の成績 y は x ≧ 60 のときのみ観測
x y 1 44.39524 NA 2 47.69823 NA 3 65.58708 62.34380 4 50.70508 NA 5 51.29288 NA 6 67.15065 71.00453
head(data)
欠測データ(Missing Data)
• 入学試験 60 点以上が合格
欠測データ(Missing Data)
このデータだけで 求めると 相関係数 = 0.55
灰色のデータまで使うと 相関係数 = 0.77
欠測データから求めた相関係数には
バイアスが生じる
今回の解析の目的
データに欠測があった場合に
正しく相関係数を推定したい
Stan で相関係数を求める
• 二変量正規分布
• 相関係数
21
12
Corr
2
212
12
2
1
2
1,
N
y
x
共分散
標準偏差
Stan で相関係数を求める
parameters { vector[2] mu; real<lower=0> var_x; real<lower=0> var_y; real cov; } transformed parameters { matrix[2,2] sigma; sigma[1,1] <- var_x; sigma[2,1] <- cov; sigma[1,2] <- cov; sigma[2,2] <- var_y; }
共分散
分散
分散共分散行列
平均
Stan で相関係数を求める
model{ for(i in 1:N) y[i] ~ multi_normal(mu, sigma); } generated quantities { real cor; cor <- cov / sqrt(var_x * var_y); }
参考:Stan で相関係数を推定する
http://qiita.com/hoxo_m/items/0f1b05681f5d6c4b560a
二変量正規分布
相関係数
Stan で相関係数を求める
mean se_mean sd 2.5% 25% 50% 75% 97.5% mu[1] 65.54 0.01 0.39 64.76 65.29 65.54 65.81 66.27 mu[2] 63.42 0.02 0.69 62.02 62.96 63.42 63.87 64.75 var_x 22.46 0.11 2.63 17.98 20.61 22.20 24.05 28.05 var_y 74.19 0.34 8.92 59.32 67.83 73.58 79.49 94.19 cov 22.64 0.17 3.92 15.98 19.89 22.38 25.10 31.14 sigma[1,1] 22.46 0.11 2.63 17.98 20.61 22.20 24.05 28.05 sigma[1,2] 22.64 0.17 3.92 15.98 19.89 22.38 25.10 31.14 sigma[2,1] 22.64 0.17 3.92 15.98 19.89 22.38 25.10 31.14 sigma[2,2] 74.19 0.34 8.92 59.32 67.83 73.58 79.49 94.19 cor 0.55 0.00 0.06 0.44 0.52 0.56 0.59 0.66 lp__ -698.69 0.06 1.60 -702.49 -699.54 -698.39 -697.48 -696.59
data1 <- subset(data, !is.na(data$y)) datastan <- list(N=nrow(data1), y=data1) fit <- stan(model_code=stancode, data=datastan, iter=1000, chain=4) print(fit, digit=2)
• x と y 両方そろっているデータのみを使うと、相関係数は 0.55
• 真の相関係数は 0.77
• x のみ観測されたデータを加えることで、精度を上げられないだろうか?
x y 1 44.39524 NA 2 47.69823 NA 3 65.58708 62.34380
• 観測データの尤度
を最大化する σ12 は一致推定量
0:
2
11
1:
12
2
2
2
121 ),|(),,,,|,(ii mi
i
mi
ii xpyxp
星野 崇宏『調査観察データの統計科学』(p.31)
http://www.amazon.co.jp/dp/4000069721
• 観測データの尤度
0:
2
11
1:
12
2
2
2
121 ),|(),,,,|,(ii mi
i
mi
ii xpyxp
二変量正規分布 正規分布
m は欠測インジケータ(mi=0 のとき yi は欠測)
increment_log_prob()
• 対数事後分布に自由に尤度を追加できる関数
• これを用いて、二変量正規分布のモデルに正規分布の対数尤度を追加する
2
1
2
12
12
)()2log(
2
1
ix
increment_log_prob()
data{ int<lower=0> N; vector[2] y[N]; int<lower=0> Nmiss; real x[Nmiss]; } ... model{ for(i in 1:N) y[i] ~ multi_normal(mu, sigma); for(i in 1:Nmiss) increment_log_prob(-0.5 * log(2 * pi() * sigma[1,1]) - 0.5 * ((x[i] - mu[1])^2)/sigma[1,1]); }
increment_log_prob()
mean se_mean sd 2.5% 25% 50% 75% 97.5% mu[1] 50.17 0.01 0.30 49.58 49.96 50.17 50.37 50.74 mu[2] 48.32 0.09 1.98 44.24 47.06 48.36 49.62 52.34 var_x 98.61 0.15 4.39 90.43 95.56 98.56 101.61 107.55 var_y 147.35 1.16 24.86 101.85 130.51 145.74 162.11 203.76 cov 96.75 0.61 12.96 70.47 88.04 96.66 105.29 123.78 sigma[1,1] 98.61 0.15 4.39 90.43 95.56 98.56 101.61 107.55 sigma[1,2] 96.75 0.61 12.96 70.47 88.04 96.66 105.29 123.78 sigma[2,1] 96.75 0.61 12.96 70.47 88.04 96.66 105.29 123.78 sigma[2,2] 147.35 1.16 24.86 101.85 130.51 145.74 162.11 203.76 cor 0.80 0.00 0.04 0.71 0.78 0.81 0.83 0.87 lp__ -3955.27 0.06 1.61 -3959.13 -3956.11 -3954.96 -3954.10 -3953.20
data2 <- subset(data, is.na(data$y)) datastan <- list(N=nrow(data1), y=data1, x=data2$x, Nmiss=nrow(data2)) fit <- stan(model_code=stancode, data=datastan, iter=1000, chain=4) print(fit, digit=2)
結果
• 推定値:0.55 ⇒ 0.80
• 真値:0.77
• y が欠測している場合の x の値を使って、推定を良くすることができた。
ところで・・・
increment_log_prob() 使わなくてもmodel に正規分布を追加すればOK?
data{ int<lower=0> N; vector[2] y[N]; int<lower=0> Nmiss; real x[Nmiss]; } ... model{ for(i in 1:N) y[i] ~ multi_normal(mu, sigma); for(i in 1:Nmiss) x[i] ~ normal(mu[1], sqrt(sigma[1,1])); }
• model に式(sampling statementというらしい)を追加することと、対数尤度関数を追加することは同じこと。
• 遠回りしましたが、少しだけ Stan の理解が深まったように思います。
謝辞