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
1
2
)(
)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 の理解
が深まったように思います。
謝辞

Stan で欠測データの相関係数を推定してみた