StatModeling Memorandum

StatModeling Memorandum

StanとRとPythonでベイズ統計モデリングします. たまに書評.

階層ベイズモデルとWAIC

この記事では階層ベイズモデルの場合のWAICとは何か、またその場合のWAICの高速な算出方法について書きます。

背景

以下の2つの資料を参照してください。[1]に二種類の実装が載っています。[2]に明快な理論的補足が載っています。

モデル1

資料[1]にあるモデルを扱います。すなわち、

f:id:StatModeling:20201106183418p:plain

ここで N は人数、 n は人のインデックスです。 r[n] は個人差を表す値になります。このモデルにおいては r[n] を解析的に積分消去することができて、負の二項分布を使う以下のモデル式と等価になります。

f:id:StatModeling:20201106183423p:plain

ここでは予測として(WAICとして)2通り考えてみましょう。 以降では事後分布による平均を  \mathbb{E}[\,] 、分散を  \mathbb{V}[\,] と書くことにします。

(1)  r[n] を持つ n が、追加で新しく1つのサンプルを得る場合

この場合には新しいデータ y の予測分布は以下になります。

f:id:StatModeling:20201106183428p:plain

WAICは n ごとに算出され、以下になります。

f:id:StatModeling:20201106183432p:plain

(2) 別の新しい人が新しく1つのサンプルを得る場合

この場合には次のモデルを考えていることに相当します。

f:id:StatModeling:20201106183436p:plain

そして、新しいデータ y の予測分布は以下になります。

f:id:StatModeling:20201106183439p:plain

WAICは以下になります。

f:id:StatModeling:20201106183443p:plain

ソースコード

 n ごとにWAICを算出することや、WAIC内の和(シグマ)はR側で処理します。

(1)のStanコード

(2)に対応する負の二項分布を使ったStanコード

(2)のStanコード

数値積分をR側かStan側のどちらかで実行する必要があります。資料[1]ではR側で行っており、これが多大な時間がかかる原因となっています。ここでは合成シンプソン公式(とlog_sum_exp関数)を使ってStan側で数値積分をして高速化します。

これはこちらのコードをメモ化によって高速化したものになっています。どちらのコードでも6~17行目でシンプソンの公式を使って数値積分をしています。

Rコード

結果

waic1_byG waic2 waic3
2.332 3.244 2.841 ... 2.987 3.14 3.143

計算時間は(1)の場合は、Surface Pro 3で1chainあたり5秒ぐらいです。(3)の場合でもメモ化がバッチリ効いて1chainあたり12秒ぐらいです。

waic1_byGにおいて、r[n]の大きなnr[n]の小さなnと比べて、ガンマ分布の裾部分の確率密度に由来する可能性が高く、(1)の予測が悪くなる(WAICが大きくなる)ことが予想されるでしょう。ここでは図示しませんが調べるとそうなっています。

waic2waic3は理論的に一致するはずですが、Stanコードの違いがMCMCサンプルの違いになり、その影響でわずかにズレます。

なお、資料[1]のp.47-48のソースコードだと(1)の場合のWAICを n ごとに算出したあとに、それらの和をとって N で割った値になります。WAICの和は「各 n が、追加でそれぞれ新しく1つのサンプルを得る場合」の予測に対応します。それを N で割った値が対応する予測はよく分かりません。

また、WAICはMCMCサンプルによって値が変わるので、乱数の種の影響をわずかにうけることに注意です。

モデル2

資料[2]にあるモデルと似たモデルを扱います。すなわち、

f:id:StatModeling:20201106183448p:plain

ここで G はクラス数(グループ数)、 g はそのインデックスです。 N は人数、 n はそのインデックスです。 N2G[n]  n が所属している g を返します。 ここでは予測として(WAICとして)3通り考えてみましょう。

(1) あるクラス g に、新しく1人が加わる場合

この場合には新しいデータ y の予測分布は以下になります。

f:id:StatModeling:20201106183453p:plain

WAICは g ごとに算出され、以下になります。

f:id:StatModeling:20201106183457p:plain

ここで G2N[g] はクラス g に含まれる n のインデックスすべてです。

(2) 別の新しいクラスがまるごとできる場合

この場合には新しいクラス全体のデータ y^n の予測分布は以下になります。

f:id:StatModeling:20201106183501p:plain

 (\,)^n の記法は資料[2]を参照してください。

WAICは以下になります。

f:id:StatModeling:20201106183505p:plain

(3) 別の新しいクラスができて、新しく1人が加わる場合

この場合には新しいデータ y の予測分布は以下になります。

f:id:StatModeling:20201106183509p:plain

WAICは以下になります。

f:id:StatModeling:20201106183513p:plain

ソースコード

(1)のStanコード

(2)のStanコード

グループ差や個人差が正規分布から生成される場合には、-5SDから+5SDぐらいまでを数値積分すればかなりよい近似になります。

(3)のStanコード

これはこちらのコードYによって変わらない部分をはじめに計算して保持しておいて、Yによって変わる部分だけをループで計算することで高速化したものになっています。

Rコード

結果

waic1_byG waic2 waic3
2.537 2.390 2.750 ... 2.496 142.1 3.679

計算時間は(1)(2)(3)の場合がそれぞれ、1chainあたり0.4秒・1秒・12秒ぐらいです。こちらはメモ化ほど高速化が効きませんが、それでも高速化しない場合と比べると1.5倍ぐらい早くなっています。

waic1_byGにおいて、クラスあたりの人数(NbyG)の多いクラスの方がWAICは小さくなるかなと思ったのですが、そこまできれいな関係ではありませんでした。ただし、人数が5人のクラスはWAICは目に見えて高くなっています。

あわせて読みたい

statmodeling.hatenablog.com statmodeling.hatenablog.com

拡散方程式の解と粒子数の時間変化

拡散現象は幅広く観測されます。この記事では拡散方程式の解と粒子数の時間変化のグラフを備忘録として残します。

拡散方程式は以下です。導出方法はWebにあふれているので検索してください。

f:id:StatModeling:20201106184256p:plain

ここで t は経過時間、 p は位置を表す座標と経過時間で決まる確率分布、 D は拡散係数です。

1次元の場合

ラプラシアン x の2階微分になるので以下になります。

f:id:StatModeling:20201106184300p:plain

初期値を \delta 関数(≒位置 x = 0 にちょぴっとある溶液をスポイトで入れた)とすると、解は以下になります。

f:id:StatModeling:20201106184303p:plain

標準偏差 \sqrt{2 D t} 正規分布になります。経過時間 t のルートでしか幅が広がりません。ここで、 t = 0 に溶液を入れた瞬間に x = 10 などにおいて密度関数の値が非ゼロになってしまっている(粒子が瞬間移動している)のは、拡散係数の定義(仮定)に由来します。モデルは近似ですのでこういうことあります。

 t = 0  n 個(単位はmolとか)の粒子をスポイトで入れたとすると、位置 x , 経過時間 t における粒子数は、分布に n を掛けて以下になります(★式とします)。

f:id:StatModeling:20201106184307p:plain

次に、 t = 0 から t = T までスポイトでぶちゅーと入れることを考えます。微小時間あたり n 個の粒子が入るとします。この場合に位置 x における合計の粒子数の時間変化 N(x,t) はどうなるでしょうか?

まず t \lt T の場合を考えます。 t 時間経つと粒子が拡散して位置 x において(★)式となるので、合計の粒子数は「入れたてホヤホヤ( t = 0 )で x に来た粒子」と「ちょっと前に入れて x に来た粒子」と、…、「はじめにぶちゅーと入れて t 時間経って x に来た粒子」の和(積分)になります。数式で表すと以下の積分になります(WolframAlpha使いました)。

f:id:StatModeling:20201106184311p:plain

ここで \Phi は標準正規分布の累積分布関数です。

次に t \gt T の場合を考えます。この場合は t - T 時間前にスポイトを抜いてますので、入れたてホヤホヤなどは積分の範囲に入らず、「スポイト抜く直前に入れて t - T 時間経って x に来た粒子」と、…、「はじめにぶちゅーと入れて t 時間経って x に来た粒子」の和(積分)になります。数式で表すと以下になります。

f:id:StatModeling:20201106184314p:plain

仮に n = 1, x = 1, T = 1 と固定し、 D の値をいろいろ変えて、 t \lt T  t \gt T の場合をあわせた関数をプロットすると以下になります。

f:id:StatModeling:20201106184244p:plain

こういう時系列を僕は幾度となく見てきた覚えがあります。今度から背後にあるメカニズムとして拡散現象も考えてみようと思います。同様に2次元円対称と3次元球対称の場合の拡散方程式とその解も求めておきます。

2次元円対称の場合

拡散方程式は2次元極座標のラプラシアンを知っていれば簡単で以下になります。

f:id:StatModeling:20201106184318p:plain

初期値を \delta 関数とすると、解は以下になります。

f:id:StatModeling:20201106184322p:plain

f:id:StatModeling:20201106184326p:plain

残念ながら t に関する積分が指数積分exponential integral)となっていて解析的に N(r,t) を表すことができません。そこで数値積分します。

1次元の場合と同じように、 n = 1, r = 1, T = 1 と固定し、 D の値をいろいろ変えてプロットすると以下になります。

f:id:StatModeling:20201106184249p:plain

3次元球対称の場合

拡散方程式は3次元極座標のラプラシアンを知っていれば簡単で以下になります。

f:id:StatModeling:20201106184330p:plain

初期値を \delta 関数とすると、解は以下になります。

f:id:StatModeling:20201106184334p:plain

f:id:StatModeling:20201106184338p:plain

 N(r,t)  t \lt T の場合に以下になり、

f:id:StatModeling:20201106184341p:plain

 t \gt T の場合に以下になります。

f:id:StatModeling:20201106184345p:plain

1次元の場合と同じように、 n = 1, r = 1, T = 1 と固定し、 D の値をいろいろ変えてプロットすると以下になります。

f:id:StatModeling:20201106184252p:plain

参考文献

今回参考にした書籍は以下です。特に1~3章がオススメです。

Random Walks in Biology

Random Walks in Biology

  • 作者:Berg, Howard C.
  • 発売日: 1993/09/27
  • メディア: ペーパーバック

2章に拡散方程式の導出と3次元球対称の場合の解が載っています。その他にも、例えば3章では3次元球対称の場合に r = b からランダムウォークをスタートして、 r = a \ (a \lt b) にたどり着くか、 r = c \ (c \gt b) にたどり着くかを計算しています。到達時間の期待値や到達確率の期待値などを簡潔に導いています。石島先生の補足ページ『「生物学におけるランダムウォーク」を理解する』で補いながら読むとよいでしょう。

underdispersion(過小分散)な場合のポアソン分布の代替

overdispersion(過分散)なポアソン分布は個体差&ポアソン分布で説明するのがシンプルで解釈しやすくて、個人的には好みです。ただ、個体差を考慮するモデルではunderdispersion(過小分散)の場合に対応できません。そのような場合には「ほぼ確定的な値が存在し、そこから外れるメカニズムをきちんと組み入れたモデル」がよさそうと思うのですが、まだ思案中です。

この記事では、overdispersion(過分散)な場合のポアソン分布の代替として、Rから簡単に使える4つの分布を紹介したいと思います。

分布の紹介とRからの使い方

超幾何分布(Hypergeometric distribution)

関数形は以下です( N,K,n,y は非負の整数、以降の分布でも yの値域は同じ)。

 K  N と比べて小さくて、 n が大きい時にPoisson分布になります。平均と分散は以下です。

合計 N 個のボールが入った壺があって、アタリのボールが K 個入っているとします。そして、ボールを1個ずつ取り出します。ただし、ボールは壺に戻しません。 n 個取り出したあとの、アタリのボールの個数 y の従う分布になっています。Rではプリインストールで関数が用意されています。

dhyper(x, m, n, k)

引数はWikipediaと少し異なります。xが確率変数の値、mがあたりのボールの個数( K に対応)、nがはずれのボールの個数( N-K に対応)、kが試行回数( n に対応)です。いくつか分布を描くと以下になります(記法はWikipediaに揃えました)。

一般化ポアソン分布(generalized Poisson distribution, Lagrangian Poisson distribution)

Wikipediaのページは見つかりませんでした。関数形は以下です( 0 \leq \theta  -1 \leq \lambda \leq 1)。

 \lambda \lt 0の時にunderdispersionです。平均と分散は以下です。

詳しくは以下の論文を読むとよさそうだけど、有料なのでサラリーマンには入手が厳しいです。このあたりの説明を読むと待ち行列と密接な関係がありそうですが分かりません。

  • [2] Consul, P. C., & Jam, G. C. (1973a) A generalization of the Poisson distribution. Technometrics, 15, 791-799
  • [3] Consul, P. C., & Jam, G. C. (1973b) On some interesting properties of the generalized Poisson distribution. Biometrische Zeitschrift, 15, 495-500.
  • [4] Consul, P. C. (1989) Generalized Poisson Distributions: Properties and Applications. New York: Marcel Dekker, Inc.

Rでは{RMKdiscrete}パッケージにあるdLGP関数を使います。

dLGP(x, theta, lambda)

いくつかunderdispersionの分布を描くと以下になります。

Conway-Maxwell-Poisson分布(Conway-Maxwell-Poisson distribution)

関数形は以下です( 0 \leq \lambda  0 \leq \nu)。

和をとって正規化する必要があります。 1 \lt \nuの時にunderdispersionです。平均と分散は陽に表せず定義通りの式になるようです。

原論文が古くて入手が難しいです。Wikipediaの記述を読むと待ち行列と密接な関係がありそうですが分かりません。

  • [6] Conway, R. W.; Maxwell, W. L. (1962) A queuing model with state dependent service rates. Journal of Industrial Engineering, 12: 132–136

Rでは{CompGLM}パッケージにあるdcomp関数を使います。

dcomp(x, lam, nu)

いくつかunderdispersionの分布を描くと以下になります。

Double Poisson分布(double Poisson distribution)

Wikipediaのページは見つかりませんでした。関数形は以下です( 0 \lt \mu  0 \lt \sigma)。

和をとって正規化する必要があります。 \sigma \lt 1の時にunderdispersionです。平均と分散は以下です(非常によい近似です)。

詳しくは以下の原論文([7]と[8])を読むとよいです(あのEfronです!)。一読したところ、exponential familyの拡張としてdouble exponential familyという分布族を定義して、そこにポアソン分布の確率質量関数を代入して整理すると出てくるようです。2次元の分割表にも関係しているようです。でも論文が難解で分かりませんでした。詳しい人いましたら教えてください。

  • [7] Efron, B., (1986) Double exponential families and their use in generalized linear Regression. Journal of the American Statistical Association 81 (395), 709-721. (link, preprint)
  • [8] Diaconis, P. & Efron, B. (1985) Rejoinder: Testing for Independence in a Two-Way Table: New Interpretations of the Chi-Square Statistic, Annals of Statistics, 13, 845–913. (link)
  • [9] Zou, Y., Geedipally, S.R. & Lord, D. (2013) Evaluating the Double Poisson Generalized Linear Model. Accident Analysis & Prevention, 59, 497–505 (link)

Rでは{gamlss.dist}パッケージにあるdDPO関数を使います(link)。

dDPO(x, mu, sigma)

いくつかunderdispersionの分布を描くと以下になります。

Stanを使って推定

デモデータは以下です。[10]のFig.1のAから逆算しました(厳密にはずれているかもしれません)。

  • [10] Kitazawa M. S., Fujimoto K. (2014) A Developmental basis for stochasticity in floral organ numbers Frontiers in Plant Science, 5, 545 (link)
  • [11] Kitazawa M. S., Fujimoto K. (2016) Relationship between the species-representative phenotype and intraspecific variation in Ranunculaceae floral organ and Asteraceae flower numbers. Annals of Botany. 117(5), 925-935 (link)

ある植物の個体ごとに花びらの数をカウントし、個体数を集計したものです。この後の論文([11])を読むと分かりますが、同じ種類の植物でも調査の場所によって分布がかなり異なるようです。もちろん植物の種類によっても分布は変わります。かなり面白いです。基本的にはoverdispersionの場合が多そうですが、ここではunderdispersionのデータを取り上げます。

本来は論文中に記述があるように、花びらの発生過程を考慮して分布を導くのがベストと思います。途中でerf関数が出てきますので、考察の基点は論文と異なりますが、分子の拡散現象と密接に関係しているのかなと思いました(次回の記事参照)。しかし、この記事ではそこまで深堀りしないで、単に上で紹介した超幾何分布を除く3つの分布をあてはめてみようとおもいます。

Stanコードだけ載せます。なお、どの分布も1chainあたり1秒以内に収束しました。

一般化ポアソン分布

推定結果はlambdaが境界値である-1にべったり張り付いていたので、モデルはダメそうです。この分布はデータのような激しいunderdispersionを表現できないのが原因と思います。

Conway-Maxwell-Poisson分布

上の式のままだと \lambda の値が大きくなりすぎてMCMCが非効率になります。そこで、[9]に記述がある以下の再パラメータ化をしました。

正規化項を別途計算しないといけないので少し複雑になっています。推定結果はmunuの中央値と95%ベイズ信頼区間がそれぞれ、5.65 [5.61, 5.68]と34.3 [31.6, 37.4]ほどになります。lambdaに直すと5.65^34.3ほどの値になりますので、データのような激しいunderdispersionにあてはめるのは厳しいのかもしれません。

なお、本来は確率質量関数を表すユーザ定義関数のsuffixは_log_likではなく_lpmfとするのが行儀よいですが、現在のStanのバージョンにはバグがあって、target +=と併せて使うことができません。次期バージョンでは直ります。

Double Poisson分布

正規化項を別途計算しないといけないので少し複雑になっています。推定結果はmusigmaの中央値と95%ベイズ信頼区間がそれぞれ、5.15 [5.12, 5.18]と0.03 [0.03, 0.03]ほどになります。個人的には、平均と分散をバラバラに変化させたい場合に、かなり自然にポアソン分布を2パラメータに拡張した分布になっているように思いました。

リアルデータ強い…