Up

相関係数のベイズ推定

 

相関係数のベイズ推定を、2変量正規分布を適用して行うスクリプトをPyMC3で書いてみた。

データは、

 

Data = [[179, 121], [185, 89], [181, 106], [210, 100], [202, 104],

        [197, 91], [227, 107], [208, 101], [188, 99], [189, 112],

        [240, 111], [203, 103], [202, 85], [190, 95], [221, 96],

        [150, 83], [205, 103], [177, 90], [221, 92], [172, 86],

        [190, 87], [218, 101], [205, 100], [208, 120], [224, 98]]

 

である。

上のデータに対するPyMC3を用いたMCMCサンプリングのPythonスクリプトを以下のように用意した。完全なスクリプトはこのウェブサイトの後ろにリスト1として示した。

 

with pm.Model() as two_v_n:

    μ = pm.Normal('μ', mu = 0.0, sigma = 1000, shape = 2)

    σ1 = pm.HalfNormal('σ1', sigma = 1000)

    σ2 = pm.HalfNormal('σ2', sigma = 1000)

    ρ = pm.Uniform('ρ', lower = -1.0, upper = 1.0)

    cov_ = pm.math.stack([[σ1**2, ρ*σ1*σ2], [ρ*σ1*σ2, σ2**2]])

    cov = pm.Deterministic('cov', cov_)

    Y = pm.MvNormal('Y', mu = μ, cov = cov, observed = Data)

   

    trace = pm.sample(3000, chains = 4)

 

リスト1を実行すると、PyMC3によるMCMCサンプリングが行われ、結果が以下のように図示される。実行は、Ubuntu上で行った。

サンプリングのトレースは下図(図1)のようである。

図1

 

図1は、スクリプト

 

az.plot_trace(trace)

 

によって描かれたものである。サンプリングに問題はないと思われる。

相関係数ρの事後分布を、次のスクリプトで描いた。

 

az.plot_posterior(trace['ρ'], ref_val = 0.0)

plt.title('ρ', fontsize = 20)

 

図2に示すグラフが描かれる。相関係数の平均値はρ=0.31で、94% HPDは[-0.045, 0.62]であることが示されている。ref_val = 0.0で指定された値より相関係数ρの値が小さい、すなわち負の値の確率は5.4%である。

図2

 

なお、PyMC3の説明は、<岡本安晴「いまさら聞けないPythonでデータ分析」丸善出版>で行っている。

 

 

リスト1 2変量正規分布による相関係数のベイズ推定

 

import pymc3 as pm

import arviz as az

import numpy as np

import matplotlib.pyplot as plt

 

Data = [[179, 121], [185, 89], [181, 106], [210, 100], [202, 104],

        [197, 91], [227, 107], [208, 101], [188, 99], [189, 112],

        [240, 111], [203, 103], [202, 85], [190, 95], [221, 96],

        [150, 83], [205, 103], [177, 90], [221, 92], [172, 86],

        [190, 87], [218, 101], [205, 100], [208, 120], [224, 98]]

 

with pm.Model() as two_v_n:

    μ = pm.Normal('μ', mu = 0.0, sigma = 1000, shape = 2)

    σ1 = pm.HalfNormal('σ1', sigma = 1000)

    σ2 = pm.HalfNormal('σ2', sigma = 1000)

    ρ = pm.Uniform('ρ', lower = -1.0, upper = 1.0)

    cov_ = pm.math.stack([[σ1**2, ρ*σ1*σ2], [ρ*σ1*σ2, σ2**2]])

    cov = pm.Deterministic('cov', cov_)

    Y = pm.MvNormal('Y', mu = μ, cov = cov, observed = Data)

   

    trace = pm.sample(3000, chains = 4)

   

print(az.summary(trace))

 

az.plot_trace(trace)

plt.savefig('FigTrace.png')

plt.show()

 

az.plot_posterior(trace['ρ'], ref_val = 0.0)

plt.title('ρ', fontsize = 20)

plt.savefig('FigRho.png')

plt.show()

 

 

Up