勉強などのメモ

勉強用のメモ

Chapter5 練習問題 Part1

(1)model5-3.stan(P.57)をRから実行して得られるMCMCサンプルを使って、それぞれのnにおけるε[n]=Y[n]-μ[n]のMCMCサンプルを算出するRコードを書け

インプットするデータは以下のようなもの(冒頭の10行ほど)

data-attendance-1.txt

A,Score,Y
0,69,0.286
1,145,0.196
0,125,0.261
1,86,0.109
1,158,0.23
0,133,0.35
0,111,0.33
1,147,0.194
0,146,0.413

まず、model5-3.stanの元となるモデル式は・・・

\mu[n] = b_{1} + b_{2}A[n] + b_{3}Score[n]   (n=1,\cdots,N)
Y[n] \sim Normal(\mu[n], \sigma)   (n_{1}=1,\cdots,N)

model5-3.stanは以下のとおり。

data{
  int N;
  int<lower=0,upper=1> A[N];
  real<lower=0,upper=1> Score[N];
  real<lower=0,upper=1> Y[N];
}

parameters{
  real b1;
  real b2;
  real b3;
  real<lower=0> sigma;
}

transformed parameters{
  real myu[N];
  for(n in 1:N)
    myu[n] = b1 + b2*A[n] + b3*Score[n];
}

model{
  for(n in 1:N)
    Y[n] ~ normal(myu[n], sigma);
}

generated quantities{
  real y_pred[N];
  for(n in 1:N)
    y_pred[n] = normal_rng(myu[n],sigma);
}

これをRで実行する。

#データ読み込み
d <- read.csv(file="data-attendance-1.txt")
#データリストの指定
#スコアは200で割ってスケーリングし、0-1の値にする
data <- list(N=nrow(d), A=d$A, Score=d$Score/200, Y=d$Y)

#モデル作成
fit <- stan(file="model5-3.stan", data=data, seed=1234)

ようやく本題。ε[n]を求めるRコードは・・・

ms <- rstan::extract(fit) #MCMCデータの取り出し
e <- d$Y - ms$myu

これでいいのかな、と思って回答を見に行ったら・・・

noise <- t(-t(ms$mu) + d$Y)

なんだこれは・・・よくわからないので、ひとまず置いておいて先に進む。

(2)model5-3.stanを修正し、Stan内でε[n]を算出せよ

generated quantitiesのところを修正すればいいはず

data{
  int N;
  int<lower=0,upper=1> A[N];
  real<lower=0,upper=1> Score[N];
  real<lower=0,upper=1> Y[N];
}

parameters{
  real b1;
  real b2;
  real b3;
  real<lower=0> sigma;
}

transformed parameters{
  real myu[N];
  for(n in 1:N)
    myu[n] = b1 + b2*A[n] + b3*Score[n];
}

model{
  for(n in 1:N)
    Y[n] ~ normal(myu[n], sigma);
}

generated quantities{
  real y_pred[N];
  real e[N];
  for(n in 1:N){
    y_pred[n] = normal_rng(myu[n],sigma);
    e[n] = Y[n] - myu[n];
  }
}

これを実行して、(1)の2つの計算方法で算出したε[n]の値と、Stan内で算出したε[n]を比較してみる。

fit2 <- stan(file="model5-3-2.stan", data=data, seed=1234)
ms2 <- rstan::extract(fit2)
e2 <- ms2$e
e <- d$Y - ms2$myu
noise <- t(-t(ms2$myu)+d$Y)

結果は

#差の合計でチェック
> sum(e-e2)
[1] 4.551914e-15
> sum(noise-e2)
[1] 0

t関数を組み入れた方がやはり一致。なぜだかよく理解できていないが、こういうものと覚えておくしかない。。。

<9/5追記>
ようやくわかった。
t関数は行列の行と列を入れ替える関数(要するに転置行列を作る関数)
今回扱っているデータ件数は50件のもの。
d$Yは行の方向にデータが入っている(50行)けど、ms2$myuは列の方向にデータが入っている(50列)。
ms2$myuの行方向にはMCMCサンプル数分のデータが入っている(ここでは4000行)
よって引き算するために、ms2$myuの転置行列を作らないといけない(1つ目のt関数)
しかし、そのままだと結果が50行×4000列の行列となるので、もう1回t関数をかまして、
4000行×50列の行列にしている。
解釈はこれであってるはず。


(3)以降はまた後日。

Chapter4 練習問題

t検定に相当することをStanで行う。以下のRコードで生成されたデータを用いて、グループ1(Y1)の平均パラメーターμ1とグループ2(Y2)の平均パラメーターμ2に差があるか、Prob[μ1<μ2](μ1<μ2である確率)を求めることで判断したい

set.seed(123)
N1 <- 30
N2 <- 20
Y1 <- rnorm(n=N1, mean=0, sd=5)
Y2 <- rnorm(n=N2, mean=1, sd=4)

(1)各グループの値に差が認められるか、おおよそ把握するために図を描け

hist(Y1, breaks=seq(-10,10,2))

f:id:prism0081:20170902015501j:plain

hist(Y2, breaks=seq(-10,10,2))

f:id:prism0081:20170902015508j:plain

とりあえず簡単にヒストグラムで確認。まあ違うっぽい。

(2)各グループで標準偏差が等しいと仮定してモデル式を書け

Y_{1}[n_{1}] \sim Normal(\mu_{1}, \sigma)   (n_{1}=1,\cdots,30)
Y_{2}[n_{2}] \sim Normal(\mu_{2}, \sigma)   (n_{2}=1,\cdots,20)

(3)Stanで(2)のモデルファイルを作成して実行せよ

Stanのコードは以下のとおり。

data{
  int N1;
  int N2;
  real Y1[N1];
  real Y2[N2];
}

parameters{
  real myu1;
  real myu2;
  real<lower=0> sig;
}

model{
  for(n in 1:N1)
    Y1[n] ~ normal(myu1, sig);
  for(n in 1:N2)
    Y2[n] ~ normal(myu2, sig);
}

これをRで実行する。

library(rstan)
model1 <- stan(file="Rstan4-4-1.stan", data=list(N1=N1,N2=N2,Y1=Y1,Y2=Y2))

トレースプロットをみてみる。

traceplot(model1)

f:id:prism0081:20170902021821j:plain

問題なさそう。

(4)得られたMCMCサンプルからR側でProb[μ1<μ2]を計算せよ

ベタ打ちだけどこれでいいのかな。

myu1 <- rstan::extract(model1)$myu1

myu2 <- rstan::extract(model1)$myu2

prob <- sum(ifelse(myu1<myu2,1,0)) / nrow(myu1)

prob

[1] 0.92175

(5)グループごとの標準偏差が異なる場合をモデル式で表現せよ。同様にProb[μ1<μ2]を計算せよ

モデル式は以下。

Y_{1}[n_{1}] \sim Normal(\mu_{1}, \sigma_{1})   (n_{1}=1,\cdots,30)
Y_{2}[n_{2}] \sim Normal(\mu_{2}, \sigma_{2})   (n_{2}=1,\cdots,20)

σに添え字がついただけ。

Stanのコードも微修正の範囲。

data{
  int N1;
  int N2;
  real Y1[N1];
  real Y2[N2];
}

parameters{
  real myu1;
  real myu2;
  real<lower=0> sig1;
  real<lower=0> sig2;
}

model{
  for(n in 1:N1)
    Y1[n] ~ normal(myu1, sig1);
  for(n in 1:N2)
    Y2[n] ~ normal(myu2, sig2);
}

これを実行する。

model2 <- stan(file="Rstan4-4-2.stan", data=list(N1=N1, N2=N2, Y1=Y1,Y2=Y2))
traceplot(model2)

f:id:prism0081:20170902022911j:plain

myu12 <- rstan::extract(model2)$myu1

myu22 <- rstan::extract(model2)$myu2

prob2 <- sum(ifelse(myu12<myu22,1,0)) / nrow(myu12)

変数名適当すぎるけど、結果は・・・

prob2

[1] 0.93625

これであっているのかわからないけど、とりあえず問題なく処理はできた。