ベルヌーイ分布モデルで体験するベイズ推定
この記事で扱う内容
本稿は、統計モデリングの基本中の基本であるベルヌーイ分布モデルを題材に、初学者が統計モデリングにおけるベイズ推定の有用性を体感することを目的としています。統計モデリングでは、観測データはある確率分布(以降は"真の確率分布"と呼ぶことにします。)に従い観測される確率変数であると仮定し、観測データの生成過程を確率モデルの組み合わせで表現することを考えます。中でもベルヌーイ分布は、「バク転が成功するか失敗するか」「コインを投げて表が出るか裏が出るか」「ホークスが今日の試合に勝つか負けるか」などの同時には起こり得ない2つの事象を表現する際に使用される確率モデルです。本稿では、ベイズ推論について概要を簡単に説明した後、ベルヌーイ分布モデルのベイズ的解釈について述べます。その後、Pythonによる簡単なデモンストレーションを行い、観測データが増加するにつれてパラメタの事後分布が真の分布に収束していく様子を確認します。
ベイズ推定の概要
まずは、統計モデリングとベイズ推定の一般論を確認しましょう。全体感重視なざっくり目の説明なので、式変形などの細部を詰めたい人は末記のリンクや標準的な数理統計学の教科書を参照してください。
統計モデリングとは
統計モデリングとは一言で言えば、確率変数 を生成する真の確率分布 をモデル設計者が恣意的に設計した確率分布 により近似的に表現するための営みのことです。モデル設計者は、真の確率分布 の近似モデル を確率モデルの組み合わせとして構成し、真の確率分布 から得られた観測データ を利用してモデルのパラメタ に関する推論を行います。ここでパラメタ とはモデルの表式に陽に現れる変量のことであり、パラメタの値がモデル分布の形状を決定します。つまり同じ確率分布のクラスであっても、パラメタの値が異なれば分布の形状は全く異なるのです。例えば、下の図の3種のヒストグラムは全てポアソン分布と呼ばれる確率分布から生成されたものですが、パラメタの値が異なるために分布の形状が異なっています。
以上を踏まえれば、モデル設計者はモデルの確率分布のクラスを定めることに加えて、モデル が真の分布 に少しでも近づくようにパラメタ に関して何らかの推論を行う必要があることは想像に難くないでしょう。 即ち、統計モデリングを正当に行うためには、「モデル の確率分布クラスの選定」と「モデルのパラメタ に関する推論」の2つの関門を突破する必要があるということが分かります。 *1
パラメタの推定手法としてのベイズ推定の利点
前節では、統計モデリングの課題は「モデル の確率分布クラスの選定」と「モデルのパラメタ に関する推論」の2部に分けられることを見ました。本稿の主要テーマであるベイズ推定は「モデルのパラメタ に関する推論」を行うためのメジャーな手法の1つです。この節では、パラメタ推定におけるベイズ推定の特徴を他の類似手法と比較しながら見ていきます。
さて、モデル を表す確率分布のクラスを"適切に"仮定することが出来たとしましょう。次にモデル設計者が乗り越えなくてはならない関門は、モデル ができる限り真の分布 の特徴を捉えることが出来るようにパラメタ に関して妥当な推論を行うことです。パラメタに関する推論の方針は大別すると3パターンあり、1つ目はデータ既知の下で尤度関数 を最大化するパラメタを点推定する最尤推定、2つ目はデータ既知の下でパラメタの事後分布 を最大化するパラメタを点推定するMAP推定、そして3つ目は尤度関数 のパラメタの事後分布 に関する期待値を予測分布 とするベイズ推定です。以降では、各手法の特徴を簡単に見ていきます。
最尤法とMAP推定は目的関数を最大化するという意味で"最適な"パラメタ が一意に定める点推定法であり、モデル を真の確率分布 の近似分布とします。目的関数の最大化という基準でパラメタを点推定する方針は一見合理的に思われますが、ここで言う"最適"なパラメタとはあくまで「観測データに対して最も適合する」という意味での"最適解"に過ぎず、未知のデータに対する汎化性能を保証するものではありません。実際、最尤推定やMAP推定はモデルのパラメタ数や観測データの次元数が増大するにつれて過学習を起こしてしまうリスクが著しく大きくなることが知られており、実用上はパラメタを点推定することに対して慎重になるべきです。一方で、3つ目のベイズ推定は"最適な"パラメタを一意に定めることはせずに、事後分布 や予測分布 といった確率分分布の形式で推論結果を得ます。従って、ベイズ推定ではパラメタに関する推論の"不確実性"を定量的に表現することが出来るという利点があります。また、予測分布 の計算にはパラメタの定義域上の確率分布である事後分布 の情報を最大限に活用するため、"最適解"以外の情報を捨て去ってしまう最尤法やMAP推定と比較して、過学習を起こしにくいという利点もあります。予測分布の具体的な計算手順については、次項の具体例を見ながら確認していきます。
datachemeng.comwww.hellocybernetics.tech
ベルヌーイ分布モデルのベイズ的解釈
まずは、ベルヌーイ分布モデルの概要を確認します。その後、ベルヌーイ分布モデルのベイズ的解釈において、事前分布にベータ分布を用いればパラメタの事後分布と予測分布が解析的に計算できることを確認します。
ベルヌーイ分布モデルとは
例えば、確率でバク転を成功できる人が 回バク転を実施した時、 「バク転が成功した時に、失敗した時に 」となる確率変数の実現値 の系列を観測データとして記録していくことを考えます。この観測データを用いて、バク転の成功確率 に関して何らかの知見を得たいとします。ここでモデル設計者が、に対して「回目の試行に対応する確率変数は確率で 、確率で となる」*2との仮説を立てたとしましょう。すると確率変数の確率分布関数は以下のように表現することが出来ます。
このように、離散2値変数 上の確率分布であり、分布のパラメタ の値に応じて と の生成確率が定まるような分布をベルヌーイ分布と呼びます。上記の例のように、ベルヌーイ分布を用いて現象をモデリングすることをベルヌーイ分布モデルと呼ぶことにします。
さて、バク転の成功確率 はベルヌーイ分布モデルのパラメタなので、観測データ を用いて1)最尤推定やMAP推定によりパラメタを点推定する 2)ベイズ推定によりパラメタの事後分布と予測分布を計算する などの方針で、バク転の成功確率 に関して知見を得る事が出来ると期待できます。今回はベイズモデリングに焦点を当てるため、後者のアプローチによるパラメタ推定を考えたいと思います。
ガンマ分布を事前分布に用いた場合の事後分布と予測分布
一般に、ベイズモデリングを行う際は、真のデータ生成分布 の近似表現として個々の観測データの生成モデル を仮定し、全体の観測データ は真のデータ生成分布 からのランダムなサンプリングとして得られていると考えます。ベイズの定理によれば、全体の観測データの生成モデル は 尤度関数 と事前分布 の積に分解出来るので、モデル設計者は尤度関数 と事前分布 の確率分布のクラスを仮定する必要があります。今回は「バク転が成功するか否か」という2値の離散データのモデリングを考えるので、各データのモデル としては全て同一のベルヌーイ分布 と仮定するのが一般的でしょう。それでは、パラメタの事前分布 の確率分布クラスについてはどのような基準に基づいて設定すれば良いのでしょうか?結論から言うと、パラメタの事前分布 としては、 なる実数を生成する分布であるベータ分布 *3を選択することが多いです。これはベータ分布がベルヌーイ分布の共役事前分布であることに由来します。共役事前分布とは事後分布と事前分布が同じ確率分布クラスになるような事前分布のことです。事前分布と事後分布の確率分布が一致していると、事後分布や予測分布を導出するための計算が煩雑になりにくいという利点があるため、特別な理由がない限りは事前分布は尤度関数の共役事前分布を選択することが多いようです。以降では例によって、尤度関数 としてベルヌーイ分布、事前分布 としてベータ分布を仮定して議論を進めることにします。事前分布の選択に関しては少々乱暴な議論に思えるかもしれませんが、観測データが増加するにつれて事前分布が予測に与える影響は少なくなっていくので、計算効率を優先したモデル設計を行う方が結果としてうまくいくことが多いです。
少し前置きが長くなりましたが、ここからはベルヌーイ-ベータモデルの事後分布と予測分布を導出していこうと思います。以下では、観測データが独立に得られていると仮定します。 まずは、パラメタの事後分布に関してベイズの定理と積の法則を用いて式変形を行います。
パラメータの事後分布に対して、ベイズの定理と積の法則を適用することで(2)式を得ます。なお、分布の形状に影響を与えるのはパラメタに依存する部分のみなので、2行目から3行目で正規化係数 を省略しています。ここまでの変形は観測データ の独立性のみを仮定しており、モデル の設計によらず成立します。以降は簡単のために(2)式に対数をとって計算を進めていくことにします。
と を代入して変形すれば(3)式を得ます。ハイパーパラメタ は、モデル設計者が定義域内で適切に定めた"定数"*4であり、規格化因子 *5もまたハイパーパラメタの関数として定まる"定数"です。 の対数を取ったものを計算してみると以下のようになります。
(3)式と(4)式を比較すると、
となることが分かり、パラメタの事後分布が事前分布と同じくベータ分布になることを解析的に導出することが出来ました。ただし、新しいベータ分布のパラメタ と は観測データ に依存する形でベイズ更新されているので、分布の形状は事前分布とは異なることに注意してください。*6 次に、予測分布 を導出していきます。 観測データ が所与である場合の予測分布 は、*7 ベイズ更新後のモデル の確率変数 に関する周辺分布なので、モデルのパラメタ を積分除去することにより導出することが出来ます。
1行目から2行目はベイズの定理を用いて変形しています。2行目の式は、まさに尤度関数の事後分布に関する期待値の定義そのものになっていますね。ここで(7)式の積分の部分はベータ分布の定義式を当てはめれば、
となるので、予測分布は
と書くことができます。ここでは、規格化因子の具体的な表示が、
となることを用いました。予測分布の標識はかなり複雑に見えますが、ガンマ関数 が満たす等式
を用いて分解すれば、 は次のように簡潔な形で書くことができます。
についても同様にして、
と簡潔に書くことができます。(12)式、(13)式を1つの式にまとめると、
となり、予測分布はベルヌーイ分布となることを解析的に導くことができました。予測分布のパラメタは と の有理式になっていますが、各々は(6)式の形で書けるのでした。ここで、 はバク転の成功回数を意味することに注意すれば、バク転の成功回数が多ければ多いほど、 の値もそれに比例して大きくなることが分かります。一方で、はバク転の失敗回数を意味するので、バク転の失敗回数が多ければ多いほど、 の値もそれに比例して大きくなります。従って予測分布のパラメタは、事前分布のハイパーパラメタであると をオフセットとする観測データ 中のバク転の成功確率を表していると解釈できます。これは、「被験者がバク転を成功すればするほど、将来もバク転を成功する確率が高いであろう」と期待することに他ならず、直感的にも推論の妥当性が理解できるでしょう。
この節では、ベルヌーイ-ベータモデルのパラメタの事後分布と予測分布を解析的に導出し、その直感的な意味について考察しました。一般には、モデルが複雑になればなるほどパラメタの事後分布と予測分布を解析的に求めることが困難になります。そのような場合には、事後分布や予測分布の導出はMCMC(Markov Chain Monte Carlo)や変分推論などの近似手法に頼ることになります。解析解が求まらない場合の近似手法については、以下のリンクを参照して下さい。
machine-learning.hatenablog.com
machine-learning.hatenablog.com
Pythonによる数値実験
最後に、Pythonによる数値実験を行います。以下のソースコードはAnaconda+TensorFlow Probabilityの環境で動作します。残念ながらTensorFlow ProbabilityはPython3.7系以降にまだ対応していないので、環境構築が面倒な人はGoogle Colaboratoryを使うことをお勧めします。
事後分布が最尤推定解付近に収束していく様子
下図では、観測データ数が増加していくにつれて事後分布の分散が小さくなっていく様子をプロットしています。データ数0の場合は事前分布を表しています。データ数が増えるにつれて、徐々に分布の中心が最尤推定解付近に収束すると同時に分散も小さくなっていくことが分かります。ソースコードも示しますので、ハイパーパラメタやバク転の試行回数の値を変更して、色々と試してみるとより理解が深まると思います。
%matplotlib inline
from IPython.core.pylabtools import figsize
import numpy as np
from matplotlib import pyplot as plt
figsize(15, 12)
import scipy.stats as stats
"""事前分布"""
dist = stats.beta
a = 1.0
b = 10.0
"""バク転の試行回数"""
n_trials = [0,10, 20, 30, 100, 200, 300, 500, 700, 1000]
"""バク転の成功確率は50パーセントとし、
ベルヌーイ分布からサンプリングして観測データを作成する
これは真の分布なので本来は未知である"""
mu = 0.5
data = stats.bernoulli.rvs(mu, size=n_trials[-1])
x = np.linspace(0, 1, 100)
for k, N in enumerate(n_trials):
sx = plt.subplot(len(n_trials)//2, 2, k+1)
plt.xlabel("$p$, probability of success") if k in [0, len(n_trials)-1] else None
plt.setp(sx.get_yticklabels(), visible=False)
"""N回目までのバク転の成功回数"""
success = data[:N].sum()
"""パラメタの事後分布"""
posterior = dist.pdf(x, success+a, N-success+b)
plt.plot(x, posterior, label= '%d trial, \n %d success'%(N, success))
plt.fill_between(x, 0, posterior, color='#348ABD', alpha=0.4)
plt.vlines(mu, 0, 4, color='k', linestyles='--', lw=1)
leg = plt.legend()
leg.get_frame().set_alpha(0.4)
plt.autoscale(tight=True)
plt.suptitle('Baysian updating of posterior probabilities', y=1.02, fontsize=14)
plt.tight_layout()
真の分布と予測分布間のKL ダイバージェンス
次に、真の分布 と予測分布 間のKL ダイバージェンスを観測データ に対してプロットしてみます。 KLダイバージェンスは2つの確率分布間の"距離"を測る尺度であり、値が0に近いほど2つの確率分布が良く似ていると言えます。KLダイバージェンスの概要については以下のリンクを参考にしてください。
下図を見ると観測データ数が増加するにつれたKLダイバージェンスが0に漸近していく様子が分かりますね。今回は非常に単純なモデルということもあり、観測データ数が100を超えたあたりからは、予測分布が真の分布をほぼ表現できているといえます。
from math import log
"""真の分布のエントロピー"""
entropy = -mu*log(mu)-(1-mu)*log(1-mu)
KL = []
for N in range(n_trials[-1]):
"""N回目までのバク転の成功回数"""
success = data[:N].sum()
""""予測分布のパラメタ"""
mu_hat = (success+a)/(N+a+b)
"""KL ダイバージェンス"""
KL.append(-entropy-mu*log(mu_hat)-(1-mu)*log(1-mu_hat))
x = np.arange(n_trials[-1])
plt.plot(x, KL, color='#348ABD', alpha=0.9)
plt.xlim(0, 1000)
p = plt.hlines([0], 0, 1000, "red", linestyles='dashed')
plt.title('KL divergence between of q(X) and p(X|D)', fontsize=20)
plt.xlabel("# of trials", fontsize=20)
plt.ylabel("KL divergence", fontsize=20)
参考文献
- ベイズ推論による機械学習入門 著 須山敦志
- Probabilistic-Programming-and-Bayesian-Methods-for-Hackers by Cameron Davidson-Pilon
*1:モデルのパラメタ は観測データ を用いて推定すべき対象なので確率変数として扱います。以降はモデルを表記する際は のようにパラメタ を引数に明記することにします。
*2:確率変数が従う確率分布のパラメタがの値に依存しないことが、各 が同分布からサンプリングされていると仮定することに対応します。
*3:とは正の実数であり、パラメタの分布のパラメタということでハイパーパラメタと呼ばれています。この値はモデル設計者が適切に値を決める必要があります。
*4:今回のモデルにおいては観測データ を用いて推定を行う対象としない、即ち確率変数ではないという意味で"定数"と表現しています。
*5:具体的な式は式(10)で与えられます。
*6: と は確率変数 に依存するので確率変数です。
*7:観測データが所与でない場合も、パラメタの事前分布を用いて予測分布を計算することは可能です。