ねこすたっと

ねこの気持ちと統計について悩む筆者の備忘録的ページ。

分散分析(ANOVA):固定効果と変量効果

分散分析(Analysis of Variance, ANOVA)を学ぶ目的でKutner先生のApplied Linear Statistical Models(5th edition)を拾い読みし始めました。 前回は二元配置分散分析で分散分析表を作るところまで確認しました。。

necostat.hatenablog.jp

今回は要因の効果をどのように捉えるかについて、"Chapter 25: Random and Mixed Effects Models" を拾い読みします。

基本的な実験デザイン

完全無作為法

最も標準的でシンプルな実験デザインは、実験単位(exprimental unit)をそれぞれの治療群に無作為に割り付ける方法です。 これを完全無作為化法(completely randomized design, CRD)と呼びます。

いま治療a1と治療a2を比較することを想定しましょう。対象者は観察可能な属性(ここでは性別としておきます)によって、治療の効きやすさが異なるとします。

対象者を無作為に割り付けて比較すれば、観察された差は治療の効果の差と考えることができるはずですが、下の図のように、たまたま性別の偏りが生じ、適切に比較することができなくなることがあります。

乱塊法

そこで、ランダム割り付けをする前に、対象者を性別で分けておき、それぞれの性別においてランダム割り付けを行います。こうすれば治療群間で性別の偏りが生じません。 似たもの同士で集められた塊をブロック(block)と呼びます。

このように、対象を似たもの同士集めてブロックとしてから、そのブロックごとに治療をランダムに割り付けるデザイン乱塊法(randomized blocked design, RBD)と言います。

ブロック化に用いられる変数をブロック因子あるいはブロック変数(blocking factor/variable)と言います。ブロック因子に使われるものとしては、(1) 実験単位の特性(年齢、性別、教育など)や、(2) 実験のセッティング(評価者、評価時期、使用機器など)があります。同一個人に対して反復して実験を行うデザイン(repeated measurement design)は、個人をブロック因子としたブロック化の特殊な状況です。

固定効果と変量効果

固定効果(fixed effect)変量効果(random effect)については以前、マルチレベルモデルを勉強したときに少しだけ触れました。

necostat.hatenablog.jp

ある要因の効果を固定効果と考えるか、それとも変量効果と考えるかは、その要因の効果に興味があるかどうかで判断することが多いようです。

ブロックが評価者や被験者個人の場合は、その個人ごとに効果がどのように違うかに興味がないことがほとんどなので、変量効果として扱うことが多いようです。

一方、ブロックが特定のカテゴリー(例:年齢、収入、処理順序など)によって与えられたものならば固定効果と考えることが多いようです。

「効果が固定されていると考えるか、それともランダム変数と考えるか」という説明をきいてもそんなにスッキリしなかったんですが、モデルの仮定と検証する仮説にもとづいた説明は分かりやすかったです。

Random Cell Means Model*1

前々回の記事で扱ったモデルでは、各群の真の平均値はそれぞれある値に固定されていると考えていました。ここで扱うrandom cell means modelは、各群の真の平均がランダム変数として固定されていないモデルで、数式で表すと下のようになります。

 
\begin{aligned}
Y_{ik} &= \mu_i + \varepsilon_{ik} \\
\mu_i  &\sim Normal(\mu_., \sigma_{\mu} ^2) \\
\varepsilon_{ik} &\sim Normal(0, \sigma ^2) \\
\mu_i &\perp \varepsilon_{ik} 
\end{aligned}

ここで  \mu_. は集団全体の真の平均で、各群の平均  \mu_i \mu_. を中心とした正規分布に従っていて、その分散は  \sigma_{\mu} ^2 です。また、 \varepsilon_{ik} は群内誤差を表していて、  \mu_i とは互いに独立と仮定されています。

群内相関

 \mu_i \varepsilon_{ik} が互いに独立なので、観測値  Y_{ik} =  \mu_i + \varepsilon_{ik} の分散は、

 
\begin{aligned}
Var\{Y_{ik}\} &= Var\{\mu_i\} + Var\{\varepsilon_{ik}\} + Cov\{\mu_i, \varepsilon_{ik}\} \\
&= Var\{\mu_i\} + Var\{\varepsilon_{ik}\} \\
&= \sigma_{\mu}^2 + \sigma^2
\end{aligned}

となります。Yの分散が群間誤差の分散   \sigma_{\mu}^2 と群内誤差の分散   \sigma^2 から構成されていることが分かります。

固定効果モデルでは全ての観測値  Y_{ik} は互いに独立ですが、変量効果モデルでは異なる群に属する観測値の間でのみ独立であることが仮定されます。

 
\begin{aligned}
Cov \{Y_{ik}, Y_{ik'}\} &= Cov \{\mu_i+\varepsilon_{ik}, \mu_i+\varepsilon_{ik'} \} \\
&= Cov\{\mu_i, \mu_i \} + Cov\{\mu_i, \varepsilon_{ik'} \} + Cov\{\varepsilon_{ik},\mu_i \} + Cov\{\varepsilon_{ik},\varepsilon_{ik'} \} \\
&= Var\{\mu_i \} \\
&=  \sigma_{\mu}^2 \\
Cov \{Y_{ik}, Y_{i'k'}\} &= 0
\end{aligned}

上記のように同じ群に属する観測値間の共分散は群間誤差の分散   \sigma_{\mu}^2 になります。同じ群に属するYの相関係数は、

 
\begin{aligned}
Corr \{Y_{ik}, Y_{ik'}\} &= \frac{Cov \{Y_{ik}, Y_{ik'}\}}{SD\{Y_{ik}\} SD\{Y_{ik'}\}} \\
&= \frac{\sigma_{\mu}^2}{\sigma_{\mu}^2+\sigma^2}
\end{aligned}

となり、これを級内相関係数(intraclass correlation coefficient, ICC)と言います。

検定する仮説

固定効果ANOVAモデルにおける帰無仮説は「全ての群で群平均が等しい」でした。

 
\begin{aligned}
H_0: &\  \mu_1 = \mu_2 = ... = \mu_a \\
H_A: &\  not \ H_0
\end{aligned}

これに対し、変量効果ANOVAモデルにおける帰無仮説は「群平均の分散が0である」です。 群平均の分散が0であるということ、群平均が全て等しいということを意味しています。

 
\begin{aligned}
H_0: &\  \sigma_{\mu} = 0 \\
H_A: &\  \sigma_{\mu} \neq 0
\end{aligned}

分散分析表

要因が2つ以上の場合、

  • 固定効果ANOVAモデル(Fixed ANOVA model)
    要因全てについて固定効果と考えるモデル
  • 変量効果ANOVAモデル(Random ANOVA model)
    要因全てについて変量効果と考えるモデル
  • 混合効果ANOVAモデル(Mixed ANOVA model)
    固定効果と変量効果の両方を含むモデル

が考えられます。それぞれのモデルにおいて平均平方(MS)が何を推定しているかを表にまとめました(MSについては前回の記事を参照)。

仮説を検定するときは、次のように検定統計量(F統計量)を決めます。

  • 帰無仮説が正しければ、同じ値になることが期待される
  • 対立仮説が正しければ、分子が分母よりも大きな値を取ることが期待される

まとめると下の表のようになります。

おわりに

  • 実験デザインはまだまだ学ぶことがありそうですが、自分はあまり使う機会がなさそうです。
  • これで一旦ANOVAから離れたいと思います。
  • ガツガツ食べて、吐いて、すっきりしてまたガツガツ食べて...(以下略)

*1:ランダムセル平均モデルと書くと平均の部分以外訳せていないのでそのまま英語にしました

分散分析(ANOVA):二元配置分散分析

分散分析(Analysis of Variance, ANOVA)を学ぶ目的でKutner先生のApplied Linear Statistical Models(5th edition)を拾い読みし始めました。 前回は平方和と自由度の分割について、要因が1つの場合を使って確認しました。

necostat.hatenablog.jp

今回は要因が2つの場合の分散分析について、"Chapter 19: Two-Factor Studies with Equal Sample Sizes" を拾い読みします。

二元配置分散分析(Two-way ANOVA)とは

要因が1つだけのときは、要因の各水準(=グループ)の真の平均を  \mu_i としたセル平均モデル(cell mean model)を考えました。これは、次のように要因の各水準ごとの真の平均値をパラメータとして設定したモデルです(添字については分散分析(ANOVA):平方和と自由度の分割を参照してください。)。

 
\begin{aligned}
Y_{ik} &= \mu_i + \varepsilon_{ik} \\
\varepsilon_{ik} &\sim Normal(0, \sigma ^2) \\
\varepsilon_{ik} &\perp \varepsilon_{i'k'} 
\end{aligned}

要因が2つのときも同じようにセル平均モデルを考えることができます。例えば水準がa個ある要因Aと、水準がb個ある要因Bがある場合、全体ではa×b個の水準があることになりますので、a×b個の水準を持った1つの要因について一元配置分散分析を行うことができます。

でもこの方法だと、「a×b個の水準のどこかには違いがある」ということは分かっても、要因Aのa個の水準が全て等しい効果を持つか、ということは分かりません。そこで、a×b個の水準の平均値がそれぞれの要因の効果から導かれるモデルを考えます。このようなモデルを、セル平均モデルに対して因子効果モデル(factor effect model)と呼ぶようです*1

一方の要因の効果は他方の要因の状態によらず一定であると仮定する場合

最もシンプルなのは、あるセル(=2つの要因の組み合わせ)における平均値が、それぞれの要因の効果の和となっていると考えるモデルでしょう。このとき、一方の要因の効果は他方の要因の状態によらず一定であると仮定していることになります。

数式で表せば次のとおりです(観測値  Y_{ijk} との関係を表す式は前述のセル平均モデルと同じなので割愛)。

 
\begin{aligned}
\mu_{ij} &= \mu_{..} + \alpha_{i.} + \beta_{.j} \\
\sum_{i} a_{i.} &= 0 \\
\sum_{j} b_{.j} &= 0 \\
\end{aligned}

ここで、

  •  \mu_{ij} = \frac{ \Sigma_i \Sigma_j \mu_{ij}}{ab} :要因Aがi番目の水準で要因Bがj番目の水準であるセルの真の平均
  •  \alpha_{i.} = \mu_{i.} -  \mu_{..} :要因Aのi番目の水準が持つ効果
  •  \beta_{.j} =  \mu_{.j} - \mu_{..} :要因Bのj番目の水準が持つ効果

です。個々のセルの平均  \mu_{ij} が全体の平均 \mu_{..} = \Sigma_i \Sigma_j \mu_{ij} /ab に一致するように、α, βのそれぞれの和が0になるよう制約を設けています。

一方の要因の効果が他方の要因の状態に依存すると仮定する場合

例えば「ある治療の効果が男性と女性で異なる」のような状態がこれに相当します。この状態を「要因間に交互作用(interaction)がある」と表現します。数式で表すと以下のとおり。

 
\begin{aligned}
\mu_{ij} &= \mu_{..} + \alpha_{i} + \beta_{j} + (\alpha\beta)_{ij}\\
\sum_{i} \alpha_{i} &= 0 \\
\sum_{j} \beta_{j} &= 0 \\
\sum_{i} (\alpha\beta)_{ij} &=0 \\
\sum_{j} (\alpha\beta)_{ij} &=0
\end{aligned}

ここで、

  •  \mu_{ij} = \frac{ \Sigma_i \Sigma_j \mu_{ij}}{ab} :要因Aがi番目の水準で要因Bがj番目の水準であるセルの真の平均
  •  \alpha_{i.} = \mu_{i.} -  \mu_{..} :要因Aのi番目の水準が持つ効果
  •  \beta_{.j} =  \mu_{.j} - \mu_{..} :要因Bのj番目の水準が持つ効果
  •  \alpha \beta_{ij} = \mu_{ij} - \mu_{i.} - \mu_{.j} + \mu_{..}: 要因Aのi番目の水準と要因Bのj番目の水準の組み合わせにおける交互作用効果

です。

新たに交互作用の和に関する制約が加わっています。例えば  \sum_{i} (\alpha\beta)_{ij} =0 という制約は、要因Bのj番目の水準の平均について  \mu_{.j} = \mu_{..} + \beta_j が成立するために必要です。

平方和の分割

一元配置分散分析のときと同様、平方和(sum of squares, SS)を分割してみます。要因の各水準の組み合わせ(セル)には等しくn個の観測値が含まれるとして、i-j番目の水準のk番目の観測値と全体平均の差  Y_{ijk} - \bar{Y}_{...} は次のように分解できます。

両辺について \Sigma_i \Sigma_j \Sigma_k を取って、なんやかんや計算すると

 
\begin{aligned}
SSTO &= SSTR + SSE \\
&= SSA + SSB + SSAB +SSE
\end{aligned}
  •  SSTO = \Sigma_i \Sigma_j \Sigma_k (Y_{ijk} - \bar{Y}_{...})^2(全体の平方和)
  •  SSTR = n\Sigma_i \Sigma_j  (\bar{Y}_{ij.} - \bar{Y}_{...})^2(群間平方和)*2
  •  SSA = nb \Sigma_i (\bar{Y}_{i..} - \bar{Y}_{...})^2
  •  SSB = na \Sigma_j (\bar{Y}_{.j.} - \bar{Y}_{...})^2
  •  SSAB = n\Sigma_i \Sigma_j (\bar{Y}_{ij.} - \bar{Y}_{i..}- \bar{Y}_{.j.} + \bar{Y}_{...})^2
  •  SSE = \Sigma_i \Sigma_j \Sigma_k (Y_{ijk} - \bar{Y}_{ij.})^2(群内平方和)

が得られます。

自由度の分割

自由度(degree of freedom, df)も分割します。観測総数がnab, 要因群数がabなので、

  • SSTOの自由度:nab - 1
  • SSTRの自由度:ab - 1
  • SSEの自由度:nab - ab = (n-1)ab

となります。SSEの自由度は「それぞれの群内の観測数(=n)から群内平均の分(=1)を引いたもの(=n-1)がab群分ある」として解釈できそうです。

要因に関する自由度はさらに、

  • SSAの自由度:a-1
  • SSBの自由度:b-1
  • SSABの自由度:(a-1)(b-1)

に分割できます。上記を足し合わせると

 
\begin{aligned}
(a-1) + (b-1) + (a-1)(b-1) = (ab -1)
\end{aligned}

となり、SSTRの自由度に一致します。

分散分析表

平方和を自由度で割った平均平方和(mean square, MS)と合わせて表にまとめてみます。

分散分析では2つの平均平方の比が1からかけ離れているかどうかF分布をもとに計算します。 MSEは群内誤差の分散の推定値ですが、他の平均平方が推定するものは要因の効果をどのように仮定するか(固定効果・変量効果)によって変わります。この話はまた別の機会にまとめます。

おわりに

  • 固定効果・変量効果の話に入らなかったので二元配置分散分析の話としては中途半端になってしまいました。

*1:あまり使われてない名前のようですが、書籍の記載から勝手に訳しました

*2:TRはtreatmentから取っていますが「要因」で統一します

分散分析(ANOVA):平方和と自由度の分割

分散分析(Analysis of Variance, ANOVA)を学ぶ目的でKutner先生のApplied Linear Statistical Models(5th edition)を拾い読みし始めました。今回は主に"Chapter 16: Single Factor Studies" から、分散分析の基本となる平方和・自由度の分割についてです。

ANOVAとは

似たもの同士を同じグループに分類すれば、グループ内は分ける前の全体の状態と比べて均一に近づきます。 意味のある分け方をすれば、バラツキを減らすことができるということです。 別の言い方をすれば、分類してバラツキが減らせたということは、対象物の特性について知ることができたということです。

ANOVAとはデータをグループに分類する(群分けする)ことでバラツキが減るかどうかを検証する方法です。ある変数で分類することでバラツキが統計的に有意に減ったのであれば、その変数はデータの特徴の一部を説明できているだろう、というロジックです。

例えば、下の図の場合はグループ分けすることでバラツキが減っているので、意味のある分類と言えます。

一方、下の図の場合はグループ分けしてもほとんどバラツキは変わっていませんので、この分類はデータの特徴の説明に役に立っていないと言えます。

群分けの方法は、割り付ける治療のように研究者が決めることもできますし、対象にそもそも備わっている特性で分類することもできます。なのでグループの呼び方は「群」の他に、治療あるいは処理(treatment)や、要因(factor)など文脈によって様々です。

セル平均モデル(cell means model)

ANOVAも回帰と同様に解析の際にモデルを想定しますが、セル平均モデルは最もシンプルなものです。

 
\begin{aligned}
Y_{ik} &= \mu_i + \varepsilon_{ik} \\
\varepsilon_{ik} &\sim Normal(0, \sigma ^2) \\
\varepsilon_{ik} &\perp \varepsilon_{i'k'} 
\end{aligned}

1つ目の式において、 Y_{ik} はi番目の治療(要因)群に属するk番目の観測値を表しています。右辺の  \mu_i はi番目の群の真の平均を表すパラメータ、  \varepsilon_{ik} は真の平均と観測値との間の誤差です。

2つ目の式では、誤差が正規分布に従うことを示しています。属する群にかかわらず全ての誤差の分散は同じと想定されます。

3つ目の式では、それぞれの誤差が互いに独立であることを示しています。

変数が2つに増えると、それぞれの治療(要因)の効果を加法性や交互作用についての仮定が登場します。 また、群を決める変数が量的変数の場合は、群平均  \mu_i と変数  i の間に関数を想定して回帰モデルと考えることもできます*1

平方和の分割

平方和とは

バラツキ具合の指標として、平方和(sum of squares, SS*2)を用います。平方和とは、平均と観測値との差の2乗(偏差平方)を足し合わせたものです。単純に平均と観測値との差を足し合わせると正負打ち消しあって0になってしまうので2乗してから足しています。

例えば、a種類の治療があって、いずれの治療群にもn個の観測値が属するとします。このときの総平方和(total sum of squares, SSTO)は、次の式で表されます。

 
\begin{aligned}
\sum_{i=1}^a \sum_{k=1}^n (Y_{ik} - \bar{Y}_{..})^2
\end{aligned}

ここで、 \bar{Y} は平均を表しています。右下についている".."は「iについてもkについても特定のものを想起しない」という意味です。平均なのでkについて考えないのは当たり前ですが、「iも特定しない」としているので、 \bar{Y}_{..} は群を分けない全体の平均であることを意味しています。逆に  \bar{Y}_{i.} と書けば治療群は特定しているので、i番目の治療群の平均値となります。

Σの添字を簡略化して、

 
\begin{aligned}
\sum_{i} \sum_{k} (Y_{ik} - \bar{Y}_{..})^2
\end{aligned}

と書いたり、(文脈上誤解がなければ)添字を省いたりすることもあります。

群間の平方和と郡内の平方和に分ける

i番目の治療群に属するk番目の観測値と全体平均との差を、次のように分解してみます。単にi番目の治療群に属する観測値の平均  \bar{Y}_{i.} を足して引いただけです。

 
\begin{aligned}
Y_{ik} - \bar{Y}_{..} = (Y_{ik} - \bar{Y}_{i.}) + (\bar{Y}_{i.} - \bar{Y}_{..})
\end{aligned}

両辺2乗します。

 
\begin{aligned}
\sum_{i} \sum_{k} (Y_{ik} - \bar{Y}_{..})^2 &= \sum_{i} \sum_{k} [(Y_{ik} - \bar{Y}_{i.}) + (\bar{Y}_{i.} - \bar{Y}_{..})]^2 \\
&= \sum_{i} \sum_{k} [(Y_{ik} - \bar{Y}_{i.})^2 + 2(Y_{ik} - \bar{Y}_{i.})(\bar{Y}_{i.} - \bar{Y}_{..}) +  (\bar{Y}_{i.} - \bar{Y}_{..})^2] \\
&= \sum_{i} \sum_{k} (Y_{ik} - \bar{Y}_{i.})^2 + 2\sum_{i} \sum_{k}(Y_{ik} - \bar{Y}_{i.})(\bar{Y}_{i.} - \bar{Y}_{..}) +  \sum_{i} \sum_{k}(\bar{Y}_{i.} - \bar{Y}_{..})^2
\end{aligned}

第2式は展開しただけ、第3式はΣを分配しただけです。

3行目の第2項において、 (\bar{Y}_{i.} - \bar{Y}_{..}) はkについて和を取るときは定数なので、Σの前に出すことができます(下式)。

 
\begin{aligned}
\sum_{i} \sum_{k}(Y_{ik} - \bar{Y}_{i.})(\bar{Y}_{i.} - \bar{Y}_{..}) = \sum_{i} (\bar{Y}_{i.} - \bar{Y}_{..}) \sum_{k}(Y_{ik} - \bar{Y}_{i.})
\end{aligned}

ここで、 \sum_{k}(\bar{Y}_{ik} - \bar{Y}_{i.}) は平均と観測値の差を2乗せずに足し合わせているので0になり、第2項は消えます。

また、i番目の治療群に属する観測数を n_i とすると、

 
\begin{aligned}
\sum_{i} \sum_{k}(\bar{Y}_{i.} - \bar{Y}_{..})^2 = \sum_{i} n_i (\bar{Y}_{i.} - \bar{Y}_{..})^2
\end{aligned}

となります( (\bar{Y}_{i.} - \bar{Y}_{..}) n_i 個の観測に対して共通だから)。

以上をまとめると、

となります。

右辺第1項は「個々の観測値とそれが属する群の平均の差の平方和」なので、群内平方和と言います。グループ分けによって、群内は同じようなものの集まりとみなされることになるので、群内のバラツキは偶然誤差に起因すると考えられますので、群内平方和(sum of squares within groups)誤差平方和(error sum of squares, SSE)あるいは残差平方和(residual sum of squares, RSS)と呼ばれます。*3

右辺第2項は「群平均と全体平均の差の平方和」なので、群間平方和(sum of squares between groups)と呼ばれます。こちらは群の名前によって、当てられる略号は色々です(例:要因A→SSA, 治療→treatment sum of squares, SSTR)

自由度の分割

自由度とは

自由度(degree of freedom, df)は、変数の中で自由に値を決めることができる数のことです。例えば、3つの数a, b, cとその平均値mがあるとします。変数は4つですが、3つが決まると残りの1つの値は自動的に決まるので、この場合の自由度は3ということになります。

例として、r種類の治療があって、それぞれの治療群に  n_i 個の観測値が属していて、総観察数は n_T とします。ここで総平方和の自由度を考えてみます。

足し合される偏差平方は  n_T 個ありますが、偏差となる平均を求めるために自由度を1つ使うので、総平方和の自由度は  n_T -1 となります。

自由度も群間と郡内に分ける

平方和と同様に、自由度も群間と群内に分けてみましょう。

まず、群内の平方和では、  n_T 個の偏差平方と、基準となるr個の群平均があるので、自由度は  n_T-r となります。 次に群間の平方和では、r個の群平均とそれらの偏差の基準となる全平均が1個あるので、自由度は  r-1 となります。

まとめると、

となり、自由度についても群内・群間に分けることができました。

平均平方

平方和を自由度で割ったものを平均平方(means square, MS*4)といいます。

誤差平均平方(mean square error, MSE)は誤差平方和(SSE)を自由度  n_T-r で割ったものなので、

 
\begin{aligned}
MSE &= \frac{1}{n_T-r} \sum_{i} \sum_{k} (Y_{ik} - \bar{Y}_{i.})^2 \\
&= \frac{1}{n_T-r} \sum_{i} \left[ (n_i-1) \sum_{k} \frac{(Y_{ik} - \bar{Y}_{i.})^2}{n_i-1} \right]
\end{aligned}

ここでi番目の群の標本分散を  s_i ^2 と書くと、

 
\begin{aligned}
s_i^2 = \sum_{k} \frac{(Y_{ik} - \bar{Y}_{i.})^2}{n_i-1} 
\end{aligned}

であり、各群の真の分散が等しく  \sigma ^2 であると仮定すれば、 s_i ^2 \sigma ^2 の不偏推定量( E \{s_i ^2 \} = \sigma ^2)なので、

 
\begin{aligned}
E \{MSE\} &= \frac{1}{n_T-r} \sum_{i}  (n_i-1) E \{ s_i ^2 \} \\
&= \frac{1}{n_T-r} \sum_{i}  (n_i-1) \sigma ^2 \\ 
&= \frac{\sigma ^2}{n_T-r} \sum_{i}  (n_i-1)  \\ 
&= \sigma ^2
\end{aligned}

となり、MSEは誤差の分散σの不偏推定量となります。

治療の平均平方(treatment mean squares, MSTR)については、全ての群で観測数が等しいとすると、

 
\begin{aligned}
E \{MSTR\} = \sigma ^2 + \frac{n \sum_{i} (\mu_i - \mu_.) ^2}{r-1} 
\end{aligned}

となります(途中の計算は割愛しますが、Y=μ+εを使って群平均・全体平均を置き換えて式変形していきます)。

分散分析表

単にこれまで登場したものを表にまとめただけです。

もし全ての群で平均が等しければ、 \mu_i - \mu_. は0になるので、MSEとMSTR(の推定するもの)は同じになるはずです。 データから計算されたMSEとMSTRが同じかどうか(比が1かどうか)を、F分布を使って統計的に検定してP値を計算します。

この先、固定効果・変量効果を考えるモデルが出てきます。解析上の違いがなかなか理解できなかったのですが、「MSE, MSTRの計算方法は同じだが、何を推定していると考えるかが違う」ということかなと思ってます。

おわりに

  • 分類したがるのは人間の普遍的な本質だそうです*5。 分類すると未知の要素が減って安心する...なるほど、そうかもしれません。
  • いつもにも増して説明がスカスカになってしまいました(自分の勉強の記録ということで...)。
  • 猫タワーの傾きがひどくなってきていて心配です。

*1:量的変数でも特定の数値しか取らない場合はANOVAモデルも可。色々な値を連続的に取るならANOVAモデルは群が無数にできてしまい現実的には無理。

*2:SSqと書くこともあります

*3:KutnerではSSEを使っているのでそれに合わせます

*4:MSqと書くこともあります

*5:http://hotozero.com/feature/kyodaitalk_5/

回帰モデルの結果を限界効果(marginal effect)で示す

前回はロジスティック回帰モデルを(少しだけ)学び直してみました。

necostat.hatenablog.jp

ここで扱ったNorton先生の文献では、オッズ比に代わるロジスティック回帰モデルの指標として限界効果(marginal effect)を推奨していましたので、簡単にどんなものなのかとRでの実装方法をまとめてみます。

今回の参考文献は以下のものです。

Norton EC, Dowd BE, Maciejewski ML. Marginal Effects-Quantifying the Effect of Changes in Risk Factors in Logistic Regression Models. JAMA. 2019 Apr 2;321(13):1304-1305.

限界効果(marginal effect)とは

説明変数が1単位増加するときに、アウトカムの期待値(2値アウトカムなら発生割合)がどれだけ変化するかを表したものです。 説明変数が連続変数のときはmarginal effect、カテゴリー変数のときはincremental effectと呼ばれますが、まとめてmarginal effectと呼ばれることが多いようです。説明変数がカテゴリー変数の場合は比較的シンプルだと思うので、以後は説明変数が連続変数の場合の限界効果を考えます。

線形回帰モデルの限界効果

線形回帰モデルではアウトカムの期待値は、

 
\begin{aligned}
E [ y_i | x_i ] = \beta_ 0 + \beta_1 x_{1i} + \beta_2 x_{2i}
\end{aligned}

なので、説明変数  x_1 についての限界効果は  x_1で偏微分して、

 
\begin{aligned}
\frac{\partial}{\partial x_{1i}} E [ y_i | x_i ] = \beta_1
\end{aligned}

となり、 線形回帰モデルでは x_1 の限界効果は  x_1 自身にも、共変量  x_2 にも依存せず、一定であると分かります。

ロジスティック回帰モデルの限界効果

ロジスティック回帰モデルでは、

 
\begin{aligned}
Pr(y_i = 1 | x_i) = \frac{1}{1+\exp \left( -\frac{\beta_0 + \beta_1 x_{1i} + \beta_2 x_{2i} }{\sigma} \right)}
\end{aligned}

なので、

 
\begin{aligned}
\frac{\partial}{\partial x_{1i}} Pr(y_i = 1 | x_i) = \frac{\beta_1 \exp \left( -\frac{\beta_0 + \beta_1 x_{1i} + \beta_2 x_{2i} }{\sigma} \right)}{\sigma \left( 1+\exp \left( -\frac{\beta_0 + \beta_1 x_{1i} + \beta_2 x_{2i} }{\sigma} \right) \right)^2}
\end{aligned}

となり、ロジスティック回帰モデルでは限界効果は  x_1 にも  x_2 にも依存していることが分かります。

ちなみにオッズ比は、

 
\begin{aligned}
OR = \exp \left( \frac{\beta_1}{\sigma} \right)
\end{aligned}

なので一定です。

限界効果の良いところ

オッズ比は全範囲で発生確率を適切に反映しない

下のグラフは標準ロジスティック関数です。

xが非常に小さい値の範囲では、xが1増えても発生確率はほとんど変わりませんが、中央付近だとxが1単位増えるだけで劇的に増加しています。 発生確率の変化は一定でないのに、オッズ比がxの値の大小に寄らず一定というのは、本当に見たいもの(=発生確率)が反映されていない感じです。

限界効果の方がモデルに依存しにくい

オッズ比はモデルの誤差の分散に依存してしまうので、モデルに含める説明変数に依存します。 これを説明変数x, zと誤差でアウトカムが決まるような仮想的なデータセットを作って考えてみましょう。

set.seed(1234)
n=10000
x <- rnorm(n,0,1)
z <- rnorm(n,0,2)

y <- NULL
for(i in 1:n){
  y[i] <- rbinom(1,1,plogis(2*x[i]+z[i]))
}

df <- data.frame(y,x,z)

このサンプルでは対数オッズに

 
\begin{aligned}
\log \left( \frac{p_i}{1-p_i} \right) =  2 x_i + z_i
\end{aligned}

という関係を仮定しました。 これにxとzの両方を含んだモデル(full model)と、xしか含んでないモデルを当てはめます。

# 2値アウトカム
fit <- glm(y ~ x, data=df, family=binomial(link="logit"))
fit_full <- glm(y ~ x+z, data=df, family=binomial(link="logit"))

両方を含んだモデルでは、

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept) 0.005211   0.028973    0.18    0.857    
x           2.016856   0.045406   44.42   <2e-16 ***
z           1.004665   0.022379   44.89   <2e-16 ***

となり、切片と各変数の係数は概ね仮定どおりに推定されています。

ここで、xしか含んでないモデルだと、

Coefficients:
             Estimate Std. Error z value Pr(>|z|)    
(Intercept) -0.002755   0.022880   -0.12    0.904    
x            1.270924   0.029829   42.61   <2e-16 ***

xの係数の推定値は1.27になってしまいました(推定オッズ比にすると7.4→3.6)。

これに対して限界効果を比べると、

> library(ggeffects)
> ggpredict(fit, terms="x [all]")
# Predicted probabilities of y

    x | Predicted |       95% CI
--------------------------------
-3.40 |      0.01 | [0.01, 0.02]
-1.53 |      0.12 | [0.11, 0.14]
-0.97 |      0.23 | [0.21, 0.24]
-0.48 |      0.35 | [0.34, 0.36]
-0.01 |      0.50 | [0.49, 0.51]
 0.47 |      0.64 | [0.63, 0.65]
 0.96 |      0.77 | [0.76, 0.78]
 3.62 |      0.99 | [0.99, 0.99]

> ggpredict(fit_full, terms="x [all]")
# Predicted probabilities of y

    x | Predicted |       95% CI
--------------------------------
-3.40 |      0.00 | [0.00, 0.00]
-1.53 |      0.04 | [0.04, 0.05]
-0.97 |      0.12 | [0.11, 0.13]
-0.48 |      0.27 | [0.26, 0.29]
-0.01 |      0.49 | [0.48, 0.51]
 0.47 |      0.72 | [0.70, 0.73]
 0.96 |      0.87 | [0.86, 0.88]
 3.62 |      1.00 | [1.00, 1.00]

Adjusted for:
* z = -0.02

となり、限界効果を使う方がモデルの違いによる差があまり目立ちません。 限界効果の方が設定したモデルに影響されにくい指標だそうです。

限界効果を使うときの注意点

想定する対象者を決めなくてはならない

前述のとおり、限界効果はモデルに含まれる他の説明変数にも依存しています。そのため、「どのような患者における効果なのか」を決めなくてはなりません。 男性・女性のように変数のカテゴリー別に限界効果を求めてもいいですし、集団全体の平均値を使ってもいいです。ただし後者は、例えば「年齢が63.5歳で55%男性」がどんな人を表しているのか、よく分かりません。

ベースラインの割合と比べる必要あり

「1単位あたり2%増える」と言われても、元の割合が0.5%しかない場合と、50%の場合とでは意味合いが全く異なりますね。

ケースコントロール研究ではサンプルにおける割合が母集団の割合を反映していないので、オッズ比を使わざるをえません。

おわりに

  • Norton先生曰く、限界効果はリスク差みたいなもの。なるほど。
  • "Marginal" effectという用語に違和感を感じる人は少なくないと思います(marginalと言いながら内容はconditionalでは?)。疫学と計量経済学の分野の差でしょうか。
  • ggeffectsパッケージも含めようと思いましたが、想定以上に長くなってしまいました。

参考資料

  • Norton EC, Dowd BE, Maciejewski ML. Marginal Effects-Quantifying the Effect of Changes in Risk Factors in Logistic Regression Models. JAMA. 2019 Apr 2;321(13):1304-1305.

  • "Marginal" という語の使い方が気になるあなたへ。

elsur.jpn.org

www.goodnalife.com

ロジスティック回帰モデルを学び直す

分かったつもりで使っているけど、よくよく勉強し直したらあんまり分かってなかったことがよくあります。今回はロジスティック回帰モデル(ロジットモデル)について学び直してみました。

読んだ文献は、以下のものです(学び直しと言いながら1本だけです。すいません。)。

Norton, E.C. and Dowd, B.E. (2018), Log Odds and the Interpretation of Logit Models. Health Serv Res, 53: 859-878.

登場する関数いろいろ

標準ロジスティック分布(standard logistic distribution)の確率密度関数(probability density function, PDF)は以下の数式で表されます。

 
\begin{aligned}
f(x) = \frac{e^x}{(e^x + 1)^2}
\end{aligned}

グラフを描くとこんな感じ。

curve(exp(x)/(exp(x)+1)^2,
      from=-10,to=10, 
      main="PDF of standard logistic distribution",
      ylab="density")

平均が0で左右対称な分布であるという点で標準正規分布(standard normal distribution)と同じ特徴を有しています。

標準ロジスティック分布の累積分布関数(cumulative distribution function, CDF)は、

 
\begin{aligned}
F(x) &= \int_{- \infty}^{x} \frac{e^{\alpha}}{(e^{\alpha} + 1)^2} d\alpha \\
&= \frac{e^x}{e^x +1} \\
&= \frac{1}{1 +e^{-x}}
\end{aligned}

となります。この関数は、標準ロジスティック関数(standard logistic function)と呼ばれます。

グラフを描くと、

curve(exp(x)/(exp(x)+1),
      from=-10,to=10, 
      main="CDF of standard logistic distribution",
      ylab="density")

となります。 y切片が0.5の単調増加関数で、標準正規分布のCDFと似たような形になります。 ちなみに、標準正規分布のCDFは標準プロビット関数(standard probit function)と呼ばれます。

2値アウトカムのモデル化

潜在的な連続変数を介してモデル化する

線形モデルでは、連続変数  y^{*} を説明変数の線型結合と誤差  \varepsilon_i でモデル化します。

 
\begin{aligned}
y^*_i = \beta_0 + \beta_1 x_i + \varepsilon_i
\end{aligned}

アウトカム  y が2値変数のときはこの方法が使えないので、連続変数  y^{*} を潜在変数として、次のように変換するとしましょう。

{
\begin{eqnarray}
y_{i} = \left\{ \begin{array}{ll} 
  1 & (y^*_i > 0) \\
  0 & (y^*_i \leq 0) 
\end{array}\right.
\end{eqnarray}
}

このときアウトカムが発生する確率は、

 
\begin{aligned}
Pr(y_i = 1 | x_i) &= Pr(y^*_i > 0 | x_i) \\
&= Pr(\beta_0 + \beta_1 x_i + \varepsilon_i > 0 | x_i) \\
&= Pr(\varepsilon_i > -(\beta_0 + \beta_1 x_i) | x_i) 
\end{aligned}

となります。 ここで、誤差   \varepsilon の確率分布が0を中心に左右対称であれば、

 
\begin{aligned}
Pr(\varepsilon_i > -(\beta_0 + \beta_1 x_i) | x_i) = Pr(\varepsilon_i < (\beta_0 + \beta_1 x_i) | x_i) 
\end{aligned}

となるので、以下のようになります。

 
\begin{aligned}
Pr(y_i = 1 | x_i) = Pr(\varepsilon_i < (\beta_0 + \beta_1 x_i) | x_i) 
\end{aligned}

右辺は   \varepsilon のCDFを使えば計算できます。

標準化誤差の分布を仮定する

ここで問題になるのが、誤差   \varepsilon の分布が分からないということです。 仮に誤差   \varepsilon が正規分布に従うと仮定したとしても、分散が分からなければ  \beta_0 + \beta_1 x_i における累積確率がどれくらいなのか分かりません。

そこで、誤差   \varepsilon の標準誤差  \sigma で割って標準化するステップが必要になります。

 
\begin{aligned}
Pr(y_i = 1 | x_i) = Pr \left( \frac{\varepsilon_i}{\sigma} < \frac{\beta_0 + \beta_1 x_i}{\sigma} | x_i \right) 
\end{aligned}

こうしておいて、標準化した誤差   \varepsilon/\sigma が標準ロジスティック分布に従うと考えれば、


\begin{aligned}
Pr(y_i = 1 | x_i) = \frac{1}{1+\exp \left( -\frac{\beta_0 + \beta_1 x_i}{\sigma} \right)}
\end{aligned}

となりますし、標準正規分布に従うと仮定すれば、

 
\begin{aligned}
Pr(y_i = 1 | x_i) = \Phi \left( \frac{\beta_0 + \beta_1 x_i}{\sigma} \right)
\end{aligned}

となります( \Phi(x) は標準正規分布のCDF)。

オッズ比の導出

ロジスティック回帰モデルを使うとオッズは次のようになります。

 
\begin{aligned}
\frac{p_i}{1-p_i}
&= \frac{ \frac{1}{1+\exp \left( -\frac{\beta_0 + \beta_1 x_i}{\sigma} \right)}}{ \frac{\exp \left( -\frac{\beta_0 + \beta_1 x_i}{\sigma} \right)}{1+\exp \left( -\frac{\beta_0 + \beta_1 x_i}{\sigma} \right)}} \\
&= \frac{1}{\exp \left( -\frac{\beta_0 + \beta_1 x_i}{\sigma} \right)} \\
&= \exp \left( \frac{\beta_0 + \beta_1 x_i}{\sigma} \right)
\end{aligned}

さらにx=0のときに対するx=1のときのオッズ比ORは、

 
\begin{aligned}
OR &= \frac{\exp \left( \frac{\beta_0 + \beta_1}{\sigma} \right)}{\exp \left( \frac{\beta_0}{\sigma} \right)} \\
&=  \exp \left( \frac{\beta_1}{\sigma} \right)
\end{aligned}

となります。

ロジスティック回帰モデルでは「 係数βを指数変換したものがその変数に関するオッズ比になる」とふんわり理解していましたが、モデルから推定できるのはβではなくβ/σであり、ORはσに依存してしまうようです。

例えば  \beta_1>0 のとき、説明変数を減らすなどしてσが増加すると、ORは低下することになります。

ロジスティック回帰モデルの解釈に関する注意点

アウトカムの発生割合が低い(<10%)ときは、オッズは発生割合の近似として用いることができます。逆に発生割合が高いときはオッズはリスクを過大評価することになります。

この他に、今回の記事で説明したように、推定ORはサンプルや設定するモデルに依存します。 新たな共変量を加えることにより、従属変数の説明できる程度が増すと、σが低下してORは増加します。

どんなデータセットを使うか、どんな説明変数を含めるか、によって推定されるORは変わってしまうので、違うセッティングでORの大きさを比較しても意味がないです。

おわりに

  • これまでよりプロビット回帰モデルについても理解が深まりました。
  • 数式よりもシミュレーションの方が納得できそうなので、次回やってみたいと思います。
  • Norton先生はORに関する問題点を踏まえた上で、限界効果(marginal effect)の使用を推奨しているそうなので、実装方法を勉強してみます。

参考資料

変数の型と測定尺度の分類

データの要約や可視化を説明しようとすると、まずは変数の型を分類しましょうという話になります。 変数の分類に関して扱っている記事は多いですが、これまでPubmed検索可能な論文まで辿ったことがなかったので勉強してみました。

データ型の分類

参考文献(Mishra et al)では「データ(data)とは測定された事実の集合体*1」であり、状況によって変化しない定数(constant)と変数(variable)に分けられると紹介されています。定数について要約したり分布を可視化することはないので、私たちの興味の対象は変数だけですね。 なのでデータと変数は同じような使われ方をしているんしょう、きっと。この記事では「変数」に統一します。

変数は大きく、「質的」か「量的」かに分けられます。

質的変数(qualitative variable)は特性に関する情報を表したデータです。カテゴリー変数(categorical variable)とも呼ばれます。

量的変数(quantitative variable)は数えたり測ったりして得られたデータです。数値データ(numerical variable)とも呼ばれます。

質的変数の分類

質的変数は自然な順序がある順序変数(ordinal variable)と、順序を恣意的にしか決めることができない名義変数(nominal variable)に分けられます。カテゴリーが2つしかない変数は2値変数(dichotomous variable)と呼ばれ、名義変数の特殊系です*2。 これらの変数の特徴は後ほど説明します。

量的変数の分類

量的変数の分類に関する説明は、参考にするものによって2パターンあります(今回調べてみようと思った最大の理由です)。

1つ目は、数値の連続性に基づいた分類です。分数や小数には分割できず、整数値しか取ることができない離散変数(discrete variable)と、分数や小数へ分割できる連続変数(continuous variable)です*3

ちなみに、離散変数であっても数が大きい場合は連続変数として扱って差し支えありません。例えば神戸市の人口は厳密には離散変数ですが、連続変数と同じ方法で要約する方が自然です。参考文献(Mishra et al)によれば、10を超えるなら連続変数として扱ってよいとのことでした。

2つ目は測定尺度の特性に基づいた分け方です。次の項で説明します。

測定の尺度

測定の尺度は次の特性をもとに分類されます。

  • 同一性(equality)
  • 順序(rank-order)
  • 等間隔性(equality of interval)
  • 比例性(equality of ratio)

尺度は下位から

  • 名義尺度(nominal scale)
  • 順序尺度(ordinal scale)
  • 間隔尺度(interval scale)
  • 比例尺度(ratio scale)

に分類されます。上位尺度は下位尺度の特性を持っているので、例えば比例尺度を順序尺度のように要約することは可能です。

名義尺度

データを特性に基づいて順序のないカテゴリーに分類する尺度です。 例として、血液型や性別、個人識別IDなどが該当します。

この尺度で定義された変数は同じかどうか(同一性, equality)が判断できるだけです(血液型が同じ・違うは言えるが、B型>A型といった順序はつけられない)。

名義尺度のデータは、観察数(各カテゴリーに何人属しているか)や最頻値(最も観察数の多いカテゴリーはどれか)で要約されます。

順序尺度

データをカテゴリーに分類する尺度ですが、名義尺度と違ってカテゴリー間の大小関係(rank-order)を判断できます。 例として、最終学歴やLikertスケールなどが挙げられます。

この尺度では大小関係は判断できますが、値を使って足し算・引き算はできません。カテゴリーの間隔が一定であるとは考えられないからです(差に意味がない)。 例えばガンの病期(I, II, III, IV)は、カテゴリー名として数字が割り振られていますが、ステージIとIIの差がステージIIIとIVの差と同じとは言えないので順序変数です。

順序尺度のデータは中央値(全体の中で順序がちょうど真ん中のデータが属するカテゴリー)・パーセンタイル値で要約されます。

間隔尺度

名義尺度・順序尺度は質的データの尺度でしたが、ここから先は量的データの尺度になります。 順序尺度と違い、間隔尺度のデータになると等間隔性(equality of interval)が備わります。つまり、「単位(=基準となる間隔距離)」が意味を持つようになるので、足し算・引き算ができます(実際には意味のない計算になる場合もあるでしょうが)。このため、平均や標準偏差として要約することができます。

例としては、摂氏温度や西暦が挙げられます。先程の病期の例と違って、「20℃上昇」や「100年後」といった差が意味を持っていることがわかると思います。

比例尺度

比例尺度も間隔尺度と同じく量的データの尺度ですが、比例尺度では「0が絶対的な意味を持つ」という点が異なります。 比例尺度における0は「本当に何もない」を意味していますし、「0よりも小さな値がない」ということです。 例えば、体重は比例尺度データの代表例ですが、体重0kgは「そこに何もない」ということを意味していて、それ以下にはなりません。

これに対し、間隔尺度における0は単なる基準点でしかありません。間隔尺度の例として摂氏温度や西暦を挙げましたが、氷点下も紀元前も存在しています(では絶対温度はどうなのか...。絶対零度よりも低い温度はないので、比例尺度と言えそうです)。

「比例尺度はX倍が意味をもつが、間隔尺度ではX倍に意味がない」という説明をよく見ます。「体重80kgは体重40kgよりも2倍重い」とは言えますが、「西暦2000年は西暦1000年よりも2倍長い・歴史がある」などとは言えないということです。

注意点としては、時間に関連したデータが常に間隔尺度になるわけではないということです。期間(=2時点の間隔の長さ)は0であれば何もないことを意味しますし、「2週間は1週間の2倍の長さである」と言うことができます。

比例尺度は変動係数(=標準偏差/平均)による要約が意味を持ちますが、間隔尺度以下の要約方法を使うことの方が圧倒的に多いです。

おわりに

  • 量的変数の2パターンの分類は、一方が他方を包含したものではないように思うので、上位・下位を考えるのはやめました。
  • 初めて絶対零度に出会ったのは聖闘士星矢でした。

参考資料

  • ニューサウスウェールズ大学(UNSW)のサイトにある解説記事です。下に挙げたStevens先生の文献が引用されていました。

studyonline.unsw.edu.au

  • S.S.Stevens. On the Theory of Scales of Measurement. Science 103,677-680(1946).

  • Mishra P, Pandey CM, Singh U, Gupta A. Scales of measurement and presentation of statistical data. Ann Card Anaesth. 2018:419-422.

*1:ブログ著者訳

*2:2つのカテゴリーにも順序がある!とも言えますが、要約方法は名義変数の説明に合致しているので

*3:Statistical Methods in Medical Researchでもこの分類

混合効果モデルで変化点を探す:Stanを使ったベイズ統計モデリング [R]

以前、segmentedパッケージを使って変化点を探す方法を調べました。

necostat.hatenablog.jp

segment( )はglmオブジェクト(=glm関数で当てはめたモデル)とlmeオブジェクト(=変量効果を含む線形回帰モデル)には対応しているんですが、lme( )は変量効果を含んだ一般化線形モデルの当てはめが出来ません。馴染みのあるglmer( )をsegmented( )に渡せると楽なんですが...(実は方法があるんでしょうか?)。

Stanで実装すればマルチレベルモデルでの変化点検出もできるかもと思ってやってみました。

階層構造のないデータ

まずはsegmented( )のまとめのときと同じく、downデータで年齢についての変化点を探してみます。

library(segmented)
library(rstan)
data(down)

使用したStanコード

次のようなコードを使いました(//より後ろはコメントなので削除可)。

data{
  int I; //total no. of obs.
  int N[I]; //no. of trial
  int n[I]; //no. of success
  real Z[I]; //explanatory variable
}

parameters{
  real<lower=min(Z)> psi; //breakpoint of Z
  real b01; //intercept1
  real b02; //intercept2
  real b1; //baseline slope
  real b2; //difference-in-slope
}

model{
  for(i in 1:I){
    if (Z[i] < psi){
      target += binomial_logit_lpmf(n[i]|N[i], b01 + b1*Z[i]);
    }else{
      target += binomial_logit_lpmf(n[i]|N[i], b02 + (b1+b2)*Z[i]);
    }
  }
}

各ブロックごとに見ていきます。

まずdataブロックでは、モデルに渡す変数として以下のものを定義しています。

  • I:総観察数(データフレームの行数)
  • N:試行数(ここでは出生総数births
  • n:成功数(ここでは発生数cases
  • Z:説明変数(ここでは母体年齢age

parametersブロックでは、変化点(psi)と変化点の前後で描かれる2本の直線の切片と傾きを定義しています。変化点後の直線の傾きを直接与えるのではなく、傾きの変化量(b2)として定義しました(この方がb2=0かどうか判断しやすそうだから)。切片はあまり興味がないのでそのまま定義してます。

modelブロックでは、変化点の前後で異なったモデルを定義しています。つまり、変化点(psi)よりも低い年齢のときは、

 
\begin{aligned}
logit(\theta_i) &= b_{01} + b_1*age_i 
\end{aligned}

を当てはめ、変化点(psi)よりも高い年齢のときは、

 
\begin{aligned}
logit(\theta_i) &= b_{02} + (b_1+b_2)*age_i 
\end{aligned}

を当てはめるようにしています。

bayes_segmented.stan という名前で保存しておきます。

サンプリング実行コード

# Stanに渡すデータ
datalist <- list(
  I = nrow(down),
  N = down$births,
  n = down$cases,
  Z = down$age
)

# モデルをコンパイル
model <- stan_model("bayes_segmented.stan")

# MCMCサンプリング
fit <- sampling(model, data=datalist,
                iter=10000, warmup=5000, thin=10,
                chain=4, cores=4, seed=1234)

結果

一部のパラメータのトレースプロットです。

stan_trace(fit, pars=c("psi","b01","b02","b1","b2"))

一部のパラメータのヒストグラムです。

stan_hist(fit, pars=c("psi","b01","b02","b1","b2"))

パラメータ推定値のサマリーです。

> round(summary(fit)$summary,digit=2)
       mean se_mean   sd   2.5%    25%    50%    75%  97.5%   n_eff Rhat
psi   30.70    0.07 1.65  28.19  29.32  30.61  31.69  34.74  544.12 1.00
b01   -6.83    0.03 0.49  -7.76  -7.16  -6.83  -6.50  -5.88  284.48 1.02
b02  -15.33    0.03 0.69 -16.94 -15.72 -15.26 -14.86 -14.14  654.03 1.00
b1    -0.01    0.00 0.02  -0.05  -0.03  -0.01   0.00   0.03  280.82 1.02
b2     0.27    0.00 0.02   0.22   0.26   0.27   0.29   0.32  297.88 1.02
lp__ -91.09    0.04 1.55 -94.89 -91.87 -90.75 -89.93 -89.12 1336.07 1.00

変化点の平均は30.7歳でした。segmented( )を使ったときの推定値が 31.081なので、まずまず許容範囲でしょうか。 傾き(b1, b2)の推定値もほとんど同じ(-0.01341, 0.27422 )なので、上手く出来てそうです。

階層構造のあるデータ

次に階層構造のあるデータでやってみます。

set.seed(1234)
n_cluster <- 10
b_RE <- rnorm(n=n_cluster, mean=0, sd=2)

data_RE <- NULL
for(i in 1:n_cluster){
  d <- down %>%
    mutate(id = i,
           theta = plogis(qlogis(cases/births) + b_RE[i]),
           cases = rbinom(n=nrow(down), size=births, prob=theta))
  data_RE <- bind_rows(data_RE, d)
}

10個のクラスターそれぞれに、正規分布に従うb_REを変量効果として加えています。平均0なので全体の平均にはあまり影響していないはずです。

> b_RE
 [1]  1.5104121 -0.4452811  2.6536869 -2.5044597 -1.6837192 -0.3739502 -1.1919180  1.5708385  2.9564148  0.8196293

出来上がったデータを確認してみます。

data_RE %>% 
  ggplot(aes(x=age, y=cases/births)) +
  geom_line(aes(colour=as.factor(id), group=id)) +
  theme_bw()

使用したStanコード

階層構造がないときと比べて、以下のデータ、パラメータを追加しています。

  • J:クラスターの数
  • ID:クラスターID
  • RE:各クラスターの変量効果
  • sigma:クラスター変量効果の標準偏差
data{
  int I; //total no. of obs.
  int J; //no. of cluster
  int N[I]; //no. of trial
  int n[I]; //no. of success
  real Z[I]; //explanatory variable
  int ID[I]; //ID of cluster
}

parameters{
  real<lower=min(Z)> psi; //breakpoint of Z
  real b01; //intercept1
  real b02; //intercept2
  real b1; //baseline slope
  real b2; //difference-in-slope
  real RE[J]; //effect of cluster
  real<lower=0> sigma; //SD of RE
}

model{
  RE ~ normal(0,sigma);
  for(i in 1:I){
    if (Z[i] < psi){
      target += binomial_logit_lpmf(n[i]|N[i], b01 + b1*Z[i] + RE[ID[i]]);
    }else{
      target += binomial_logit_lpmf(n[i]|N[i], b02 + (b1+b2)*Z[i] + RE[ID[i]]);
    }
  }
}

bayes_segmented_multilevel.stan という名前で保存しておきます。

サンプリング実行コード

渡すデータが増えた他は、先程とほぼ同じです。

# Stanに渡すデータ
datalist <- list(
  I = nrow(data_RE),
  J = length(unique(data_RE$id)),
  N = data_RE$births,
  n = data_RE$cases,
  Z = data_RE$age,
  ID = data_RE$id
)

# モデルをコンパイル
model <- stan_model("bayes_segmented_multilevel.stan")

# MCMCサンプリング
fit <- sampling(model, data=datalist,
                iter=10000, warmup=5000, thin=10,
                chain=4, cores=4, seed=1234)

結果

一部のパラメータのトレースプロットです。まずまずでしょうか。

stan_trace(fit, pars=c("psi","b01","b02","b1","b2","sigma"))

一部のパラメータのヒストグラムです。psiは30.5〜31.5でだいたい一様ですが、元のデータの年齢が1歳刻みだからでしょう。

stan_hist(fit, pars=c("psi","b01","b02","b1","b2","sigma"))

ちょっと見にくいですが、パラメータ推定値のサマリーを全部載せてしまいます。

> round(summary(fit)$summary,digit=2)
           mean se_mean   sd     2.5%      25%      50%      75%    97.5%   n_eff Rhat
psi       31.01    0.01 0.31    30.52    30.75    30.99    31.26    31.49 1372.54 1.00
b01       -6.51    0.08 0.71    -7.91    -6.99    -6.51    -6.05    -5.08   81.66 1.02
b02      -15.02    0.08 0.72   -16.45   -15.51   -15.02   -14.56   -13.58   81.35 1.02
b1        -0.01    0.00 0.00    -0.02    -0.01    -0.01    -0.01    -0.01 1380.29 1.00
b2         0.27    0.00 0.00     0.27     0.27     0.27     0.28     0.28 1582.65 1.00
RE[1]      1.20    0.08 0.71    -0.22     0.75     1.21     1.68     2.61   80.47 1.02
RE[2]     -0.70    0.08 0.71    -2.14    -1.14    -0.69    -0.22     0.71   79.85 1.02
RE[3]      2.33    0.08 0.71     0.89     1.87     2.33     2.80     3.71   80.18 1.02
RE[4]     -2.73    0.08 0.72    -4.22    -3.18    -2.72    -2.24    -1.32   80.37 1.02
RE[5]     -1.94    0.08 0.71    -3.41    -2.39    -1.93    -1.46    -0.54   83.70 1.02
RE[6]     -0.77    0.08 0.71    -2.19    -1.22    -0.76    -0.29     0.64   79.81 1.02
RE[7]     -1.50    0.08 0.71    -2.94    -1.95    -1.50    -1.02    -0.10   80.41 1.02
RE[8]      1.22    0.08 0.71    -0.21     0.77     1.23     1.70     2.62   80.68 1.02
RE[9]      2.63    0.08 0.71     1.20     2.18     2.64     3.10     4.02   79.79 1.02
RE[10]     0.52    0.08 0.71    -0.91     0.07     0.53     1.00     1.91   80.51 1.02
sigma      2.15    0.02 0.62     1.33     1.73     2.03     2.43     3.72  764.72 1.00
lp__   -1807.01    0.08 2.80 -1813.28 -1808.68 -1806.67 -1805.00 -1802.62 1110.61 1.00

変化点・傾き・REの分散などを比べると、まずまず良い出来でしょうか。

おわりに

  • データとパラメータとの大小関係で場合分けする方法で上手くいきました。
  • 事前に変化点の個数が分かっていないといけないのが弱点です(単調増加に見えるなら1点を見つけたいという状況が多いように思いますが)
  • キャットタワーの爪研ぎ部分の麻紐がとれて、芯材が剥き出しになってしまいました。崩壊する前に買い替えを検討中です。