Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

rstanで簡単にGLMMができるglmmstan()を作ってみた

21,952 views

Published on

rstanで簡単にGLMMができるglmmstan()を作りました。
lme4のglmer()と同じ文法でコードを書くと,内部でstanコードを自動生成して,MCMCを走らせてくれます。

Published in: Software

rstanで簡単にGLMMができるglmmstan()を作ってみた

  1. 1. rstanで簡単にGLMMができる glmmstan()を作ってみた 2015年6月13日 SapporoR #4 @simizu706
  2. 2. 自己紹介 • 清水裕士(@simizu706) – 関西学院大学社会学部 – 兵庫県西宮市にあります • 専門 – 社会心理学っぽいこと • 趣味 – 心理統計,統計ソフト開発 – 最近はStanとか • Web: – http://norimune.net
  3. 3. Excelで動くフリーの統計ソフトHAD
  4. 4. 今日はRの勉強会
  5. 5. 【※注意※】 • この発表は(かなり)マニアックです – GLMM,ベイズ統計,MCMC,rstan・・・ – 必要な事前知識が多いですが,ぼーっと聞いて おいてください • 発表者は早口です – 30分でスライド64枚を疾走します
  6. 6. 今日のお話 • GLMMってやっぱほら,MCMCじゃない? • glmmstan()という代筆関数を作った • glmmstan()を使ってみた • まとめ
  7. 7. 今日のお話 • GLMMってやっぱほら,MCMCじゃない? • glmmstan()という代筆関数を作った • glmmstan()を使ってみた • まとめ
  8. 8. 今日使うデータ • 野球のデータ – 2014年のプロ野球野手140名の打撃成績と翌年の 年俸 – プロ野球Freakからダウンロードできる • http://baseball-freak.com/ • (ただし,年俸のデータはWikipediaから集めた) • 知りたいこと – ホームラン数はどういう分布でモデリングできる? – ホームラン一本打ったら,年俸はいくら増えるの?
  9. 9. ホームランの本数をモデリング • まずは度数分布を確認 ・・・ポアソン分布? でもどう考えても個人差が・・・ GLMMだ!
  10. 10. 年俸をホームラン数で予測したい
  11. 11. 年俸をホームランで予測したい (G)LMMだ! 球団ごとに回帰直線 が違う・・・
  12. 12. GLMMってなんだっけ • Generalized Linear Mixed Modeling – 一般化線形混合モデル – 線形モデル+指数分布族+変量効果 • どういうときにGLMMを使うのか? – データが離散分布に従うが,過分散が生じるとき • 個体差が大きい場合 – データがネストされた構造になっていて,グルー プごとに効果が異なるとき
  13. 13. いつもの by 久保先生のWebから
  14. 14. みどり本
  15. 15. GLMMがMCMCな理由 • 推定上の問題 • モデル比較の問題
  16. 16. GLMMにおける最尤法の困難 • 尤度関数が異なる分布の積の形になる • これを解くには積分計算が必要 – 変量効果のグループが1つなら,頑張って数値積 分することができる – でも2つ以上になると,近似計算が必要 • 場合によっては,バイアスが生じる
  17. 17. そこでMCMCを使ったベイズ推定 • 積分計算を避けられる – 事後分布を積分計算をせずにシミュレーションで 推定する • その他,最尤法に対するアドバンテージ – 事後分布が正規分布でなくてもよい – 分散成分の推定にバイアスが生じない • 最尤法は分散成分が不偏推定量ではない • 特に小サンプルでバイアスが大きい
  18. 18. 最尤法におけるモデル選択 • モデル比較といえばAIC – でもAICはモデルが真の分布を含んでいる必要がある • つまり,データがどの分布に従うかを決めるのには使えない – AICは事後分布が正規分布に従う必要がある • しかし,多くのGLMMの変量効果の分散成分の事後分布は 正規分布にならない • もっと柔軟につかえる情報量規準はないの? – それがWAIC! – MCMCを使うと簡単に計算ができる
  19. 19. WAICかわいいよWAIC • 広く使える情報量規準 – Widely Applicable information Criterion – Watanabe Akaike Information Criterionとも • WAICの利点(渡辺先生のWebサイトから) – 真の分布・事前分布がどのような場合でも使える – 事後分布が正規分布でなくても使える • 仮に正規分布で近似できても従来法より正確 – 正則モデルでなくても使える – 簡単に計算できる
  20. 20. WAICを使うと・・・ • 残差の分布族をこえてモデル選択できる? – たぶん • どの事前分布が適切かが選択できる – らしい • AICで比較できることはWAICで全て可能 – AICは統計的に正則で真の分布を含む場合,WAICに一致 • WAIC使うっきゃない! – 「WAICは現状もっとも有力かつ汎用的な、MCMCから算 出できる予測のよさの指標である」 by 岡田先生
  21. 21. MCMCソフトウェア事情 • MCMCglmmパッケージ – 比較的簡単にGLMMをMCMCできる – 変量効果が複数あるとほぼ推定できない • BUGS – コードを書けば,いろんなモデルを推定できる – 相関が高い変量効果の推定では,いつまでたっても収束 しないという事態がある(らしい) • Stan – 複雑な階層ベイズのモデルでも早く収束する – NUTSという最新のMCMCアルゴリズムを使っている
  22. 22. stanかわいいよstan • フリーのベイズ推定(MCMC)用のソフト – R上からでもrstanパッケージをいれると動かせる • rstanパッケージのインストール – C++コンパイル用のツールをインストール – Githubからダウンロード+インストール – 山口大学の小杉先生の資料がわかりやすい • http://www.slideshare.net/KojiKosugi/r-stan
  23. 23. 今月中に発売予定 • 基礎からのベイズ統計学 – ハミルトニアンモンテカルロ法による実践的入門 – 豊田秀樹著 – Stanについての初めての日本語の本
  24. 24. 今日のお話 • GLMMってやっぱほら,MCMCじゃない? • glmmstan()という代筆関数を作った • glmmstan()を使ってみた • まとめ
  25. 25. GLMMをStanでやりたい • でもStanは初心者には敷居が高い – データの読み込みとそれに対応した変数の宣言 など,慣れないとぱっとさっとはできない • Rのコードだけ書いて,ぱぱっとGLMMしたい – たとえば・・・glmer()と同じ書き方をしたらできる, みたいな。
  26. 26. なんかそんなの聞いたことが・・・?
  27. 27. glmer2stanパッケージ • lme4文法で簡単にMCMCができる – WAICも計算してくれる – すてきやん?それでええやん? • しかし,いろいろ不満がある – 推定が妙に遅い – 変数名に依存するので毎回コンパイルが必要 – 謎のエラーが頻発する – 使える分布が限られる – コードがいじりにくい
  28. 28. で,新しい関数を作った • glmmstan() – lme4タイプの式を入力すると,内部でstanコードを自 動生成し,stanでMCMCを走らせる – 基本はglmer2stanと同じ – source(“http://bit.ly/glmmstan”) で読み込める • 必要パッケージ – rstanパッケージ • stanがないと始まらない – doParallelパッケージ • 並列化処理に必要 • なくても並列化しなければ一応走る
  29. 29. glmer2stanとの違い • glmmstanのほうが推定が速い – ベクトル化して書いてるので,その分計算が速い • glmer2stanはあえてベクトル化せず書いてるらしい – 後述する,並列化を使うことでさらに速い glmer2stan
  30. 30. glmer2stanとの違い • コンパイルを避けられる – 変数名に依存しないので,固定効果を変えるだ けなら,コンパイルしなくてもいい – コンパイル済みのstanモデルの出力も可能 • stanコードをいじりやすい – stanコードだけを出力して,それを編集し,その コードで分析ができる – 事前分布を変えたり,微調整がしやすい
  31. 31. 使える分布 • 正規分布(”gaussian” or “normal”) • ベルヌーイ分布(”bernoulli”) ロジットリンク • 二項分布(”binomial”) ロジットリンク • ポアソン分布(”poisson”) 対数リンク • 負の二項分布(”nbinomial”) 対数リンク • ガンマ分布(”gamma”) 対数リンク • 対数正規分布(”lognormal”) 対数リンク • ベータ分布(”beta”) ロジットリンク • 順序カテゴリカル(”ordered”) ロジットリンク
  32. 32. WAICを計算できます • 全てのモデルでWAICを出力 – 一応,glmer2stanと一致することは確認 • しかし,本当にあっているのか・・・ – 岡田先生の行動計量学会資料を参考に計算 • http://www3.psy.senshu-u.ac.jp/~ken/BSJ2015spring_okada.pdf – 他にWAICを出力するソフトがないので,イマイチ自信 がありません。 – 詳しい方はstanコードを覗いてみて,間違いがあれば ご指摘いただけると助かります – 今回はたぶん大丈夫ということで結果を発表します
  33. 33. その他の機能 • 交互作用項と単純効果の分析 – 交互作用項があるとき,スライス変数を指定する ことで単純効果の分析が可能 – 今のところ±1SDでスライス • オフセット項を追加できる – みどり本6章,「offset項わざ」を参照 – 今のところポアソンか負の二項分布のみ可
  34. 34. 今日のお話 • GLMMってやっぱほら,MCMCじゃない? • glmmstan()という代筆関数を作った • glmmstan()の使い方 • glmmstan()を使ってみた
  35. 35. glmmstan()の使いかた • 基本的な使いかたはglmerと同じ • 必須の引数 – formula:式を書く glmerと同じ文法 – data:データフレームを指定 – family:使用する分布を入力 デフォルトは正規分布 • 戻り値 – stanfitクラスのオブジェクトを返す – なので,rstanの出力関数が使える fit <- glmmstan(salary ~ HR+(1+HR|team), data=dat, family="gaussian")
  36. 36. コンパイルを避けたい • 一度分析した出力をstanfitに入れる – 変数名に依存しないので,毎回コンパイルしなく てもいい – 固定効果を変えるだけなら,次のように書くだけ で推定が可能 fit1 <- glmmstan(salary ~ HR+(1+HR|team),data=dat, family=“gaussian") fit2 <- glmmstan(salary ~ HR+(1+HR|team),data=dat, family=“gaussian", stanfit = fit1)
  37. 37. stanコードを修正して分析したい • stanコードを指定すると優先的に分析 – stanコードだけを出力して,それを編集し,その コードで分析ができる code1 <- glmmstan(salary ~ HR+(1+HR|team),data=dat, family="gaussian", codeonly = TRUE) fit <- glmmstan(salary ~ HR+(1+HR|team),data=dat, family="gaussian", stancode = code1)
  38. 38. glmmstanのstanコード例 data{ int<lower=1> N; int<lower=1> P; row_vector[P] x[N]; int<lower=1> R; int<lower=1> G[R]; int<lower=1> Q[R]; real y[N]; int<lower=1> id1[N]; row_vector[Q[1]] z1[N]; } transformed data{ vector[Q[1]] mu1; for(q in 1:Q[1]) mu1[q] <- 0; } parameters{ vector[P] beta; vector[Q[1]] r1[G[1]]; vector<lower=0>[Q[1]] tau_sd1; corr_matrix[Q[1]] tau_corr1; real<lower=0> s; } transformed parameters{ real<lower=0> sigma; cov_matrix[Q[1]] tau1; sigma <- s^2; tau1 <- quad_form_diag(tau_corr1,tau_sd1); } model{ real predict[N]; beta ~ normal(0,1000); r1 ~ multi_normal(mu1,tau1); tau_sd1 ~ cauchy(0,2.5); tau_corr1 ~ lkj_corr(2); s ~ cauchy(0,2.5); for(n in 1:N){ predict[n] <- x[n]*beta+z1[n]*r1[id1[n]]; } y ~ normal(predict, s); } generated quantities{ real log_lik[N]; real predict[N]; for(n in 1:N){ predict[n] <- x[n]*beta+z1[n]*r1[id1[n]]; log_lik[n] <- normal_log(y[n], predict[n], s); } }
  39. 39. その他の機能 • 交互作用項と単純効果の分析 • オフセット項を追加できる – 今のところポアソンか負の二項分布の場合のみ fit <- glmmstan(salary ~ HR*AVG+(1+HR|team), data=dat, family="poisson", center = TRUE, slice="AVG") fit <- glmmstan(salary ~ HR+(1+HR|team),data=dat, family="poisson", offset = "ATbase") ※Log()をつけなくてもいい
  40. 40. 並列化処理 • chainごとに並列化したほうが計算が速い – parallel = Tと書けば並列化可能 – あるいは,Pglmmstan()関数を使ってもよい – コア数はcores=で指定 • デフォルトはchainsと同じ fit <- Pglmmstan(salary ~ HR+(1+HR|team),data=dat, family="gaussian", chains = 4, cores = 4)
  41. 41. 並列化 • 4chainでも別に4倍速になるわけではないが・・ – 基本的には常に並列化するのがオススメ – いらんinformational messagesがでなくなるのもいい • 並列化が「ない」とき • 並列化が「ある」とき
  42. 42. ※注意 • ものすごいinformational Messagesが出る – でも,これはエラーではなく,推定は問題ない – 赤字で出るので最初はたぶんビビる
  43. 43. stanに関する引数 • MCMCについての引数 – iter:サンプリング回数 デフォルトは2000 – warmup:バーンイン期間 デフォルトはiterの半分 – chains:マルコフ連鎖の数 デフォルトは2 – thin:何回おきに採用するか デフォルトは1 • stanにいれる便利な引数 – stancode:いじったstanコードを入力する – standata:いじったstanにいれるdataを入力する – stanmodel:コンパイル済みのモデルを入力する – stanfit:stanの出力を入力する(コンパイルを避ける)
  44. 44. その他の引数 • Stanに入れるためのオブジェクトを返す – codeonly: TRUEでstanコードだけを返す – dataonly: TRUEでstan用のデータだけを返す – modelonly: TRUEでコンパイル済みのモデルを返す • 推定のオプション – center: TRUEで説明変数を平均値で中心化する – slice: 単純効果をみるときのスライス変数を指定 – offset: オフセット項わざを使うときの変数を指定
  45. 45. その他の引数 • 並列化に関する引数 – parallel: TRUEで並列化 • ただし,Pglmmstan()を使うほうが楽 – cores:使用するコア数を指定する • デフォルトはchainsとおなじ
  46. 46. 今日のお話 • GLMMってやっぱほら,MCMCじゃない? • glmmstan()という代筆関数を作った • glmmstan()の使い方 • glmmstan()を使ってみた
  47. 47. glmmstan()を使ってみる • 忘れたと思うのでもう一度 – 2014年のプロ野球野手140名の打撃成績と翌年の 年俸 – プロ野球Freakからダウンロードできる • http://baseball-freak.com/ • (ただし,年俸のデータはWikipediaから集めた) • 知りたいこと – ホームラン数はどういう分布でモデリングできる? – ホームラン一本打ったら,年俸はいくら増えるの?
  48. 48. ホームランの本数をモデリング • まずは度数分布を確認 ・・・ポアソン分布?
  49. 49. glmmstanを使ってMCMC • ホームラン数を予測するモデル – ポアソン分布を仮定 fit0 <- Pglmmstan(HR~1,dat, family="poisson",iter=5000) でもどう考えても,プレイヤー差 は無視できない
  50. 50. 変量効果をいれて推定 • プレイヤーの打力差をモデルに入れる – ポアソン分布を仮定 – プレイヤーを変量効果として推定 fit1 <- Pglmmstan(HR~1+(1|player),dat, family="poisson",iter=5000) アホみたいに改善された ただし,このWAICはAICに比べて かなり小さい値なので,あってる か自信がない
  51. 51. 年俸をホームラン数で予測したい plot(dat$HR,dat$salary)
  52. 52. 年俸の分布を見てみる hist(dat$salary) わ~,きれいな正規分布・・・ なわけもなく ※100万単位 ↓阿部(6億)
  53. 53. ・・見なかったことにして線形回帰 fit2 <- Pglmmstan(salary~HR,dat) AIC(lm(salary~HR,dat)) 単純なモデルだとAICとほぼ一致
  54. 54. 要約した結果を見る output_result(fit2)$beta ホームラン1本打つと,平均600万年俸が増える! ※__sigmaはスケールパラメータで,線形回帰でいう残差分散です。 標準偏差ではありません。
  55. 55. 年収って,対数正規分布らしい
  56. 56. OK,分布を変えよう • 対数正規分布を指定して,後は同じ – 一般化線形モデル fit3 <- Pglmmstan(salary~HR,dat,family="lognormal") 正規分布を仮定したモデル(1660.6485)に 比べて大幅に改善!
  57. 57. 結果を見ると HRが10本から11本に増えると・・・ →約410万増! HRが20本から21本に増えると・・・ →約760万増! でもまぁ,HRだけでは全然予測できない・・・ Output_result(fit3)$beta
  58. 58. 球団によって違うんじゃね? • チーム(12球団)を変量効果に入れて分析 – →GLMM(一般化線形混合モデル) – HRの効果が球団によって違うかどうか fit4 <- Pglmmstan(salary~HR+(1+HR|team),dat, family = "lognormal", iter=5000) 多少改善された・・・?
  59. 59. MCMCが収束しているかを確認 output_stan(fit4)
  60. 60. 結果の要約 output_result(fit4) ※対数正規分布は対数リンクを使用 ホームランの係数0.06に対して球団間変動はSDで0.017 球団によってHRの効果が結構違いそう
  61. 61. shinystanかわいいよshinystan ソフトバンク→ 阪神→ 広島→ 巨人→ 金持ちの球団ほど効果が高い・・・ そりゃそうか
  62. 62. 打率は? • 打率の程度によってどれくらい変わる? fit5 <- Pglmmstan(salary~HR*AVG+(1+HR|team),dat, family="lognormal", center=T, slice="AVG", iter=5000) ふむ。 ※±1SDでスライス
  63. 63. 打率が高い人と低い人の効果 ホームランと打率の交互作用効果はイマイチ でも,一応打率の高さでHRの効果は変わっているようにみえる →打率が高い人がHR打つほうが年俸への効果は高そう output_result(fit5)$beta output_result(fit5)$simple
  64. 64. いろんな分布で遊んでみる • ガンマ分布 – 対数正規分布に似た分布 – 対数リンクで,0より大きい実数をとる fit6 <- Pglmmstan(salary~HR*AVG+(1+HR|team),dat, center=T,slice="AVG", family=“gamma",iter=5000) ふむ。 やはり年俸は対数正規分布か。
  65. 65. まとめ • GLMMってやっぱほら,MCMCじゃない? – MCMCを使えば,複雑なモデルも同じ要領・アル ゴリズムで推定できる – 分布を超えてモデル比較ができる(らしい) • glmmstan()を作ったよ – いま流行りのstanで自動的にGLMMしてくれる – まだまだ改良の余地があるので要望・間違いが あれば@simizu706までご連絡ください
  66. 66. Enjoy! @simizu706 http://norimune.net

×