Up

単回帰分析

 

下図のデータdata.csvの単回帰分析を行う。

図1

 

すなわち、データにおいての関係を次式のモデル(1)で表すことを考える。

ここで、は誤差(残差)を表し、平均が0の正規分布に従うものとする。

は、平均0,分散の正規分布を表し、記号は、左辺の確率変数が右辺の分布に従うことを表す。

単回帰モデルによるベイズ分析を行うためのStanスクリプトをリスト1に示す。

 

リスト1 単回帰分析のStanスクリプト(simple_regression.stan

data {

    int N;

    real X[N];

    real Y[N];

}

parameters {

    real a;

    real b;

    real<lower = 0> sgm;

}

model {

    a ~ normal(0, 100);

    b ~ normal(0, 100);

    sgm ~ exponential(0.001);

    for (i in 1:N)

        Y[i] ~ normal(a + b*X[i], sgm);

}      

 

スクリプトファイルおよびデータファイルは、圧縮ファイルfilesSRegression.zipにまとめている。ダウンロード・展開すれば自由に利用できる。

Stanについては、岡本安晴(2019で説明している。

リスト1のStanスクリプトファイルを使って、図1のデータを分析するPythonスクリプトをリスト2に示す。

 

リスト2 単回帰分析のPythonスクリプト例(SimpleRegression.py

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import pystan

import seaborn as sb

 

 

df = pd.read_csv('data.csv')

#print(df)

data = df.values

#print('data =\n', data)

X = data.T[1]

Y = data.T[2]

for x, y in zip(X, Y):

    print(x, y)

   

sm = pystan.StanModel(file = 'simple_regression.stan')

print('Compiling end.')

 

Data = {'N':len(X), 'X':X, 'Y':Y}

fit = sm.sampling(data = Data, n_jobs = 1)

print(fit)

 

a_hat = np.median(fit['a'])

b_hat = np.median(fit['b'])

sb.kdeplot(fit['a'])

plt.title('a: median = {0:.2f}'.format(a_hat), fontsize = 18)

plt.savefig('Fig_a.png')

plt.show()

 

sb.kdeplot(fit['b'])

plt.title('b: median = {0:.2f}'.format(b_hat), fontsize = 18)

plt.savefig('Fig_b.png')

plt.show()

 

plt.plot(fit['b'], fit['a'], 'o')

plt.xlabel('b', fontsize = 20)

plt.ylabel('a', fontsize = 20)

plt.savefig('Fig_scatter_ab.png')

plt.show()

 

plt.plot(X, Y, 'o', label = 'Data')

plt.plot([min(X), max(X)], [a_hat + b_hat * min(X), a_hat + b_hat * max(X)],

        label = 'Regression Line')

plt.xlabel('X', fontsize = 16)

plt.ylabel('Y', fontsize = 16)

plt.legend(fontsize = 14)

plt.savefig('FigSRegress.png')

plt.show()

 

実行すると、以下の出力を得る。

図2 aの事後分布

 

図3 bの事後分布

 

図4 (b,a)の散布図

 

図5 回帰直線

 

中心化(Centering

モデル(1)の定数が独立変数の平均値における値を示すようにするために、独立変数の中心化を行う。

この中心化されたZを独立変数として回帰分析を行うPythonスクリプトをリスト3に示す。

 

リスト3 中心化された独立変数による単回帰分析(SRegression_centered.py

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import pystan

import seaborn as sb

 

 

df = pd.read_csv('data.csv')

data = df.values

X = data.T[1]

Y = data.T[2]

for x, y in zip(X, Y):

    print(x, y)

 

Z = X - np.mean(X)

plt.plot(Z, Y, 'o')

plt.xlabel('Z', fontsize = 14)

plt.ylabel('Y', fontsize = 14)

plt.show()

 

sm = pystan.StanModel(file = 'simple_regression.stan')

print('Compiling end.')

 

Data = {'N':len(Z), 'X':Z, 'Y':Y}

fit = sm.sampling(data = Data, n_jobs = 1)

print(fit)

 

a_hat = np.median(fit['a'])

b_hat = np.median(fit['b'])

sb.kdeplot(fit['a'])

plt.title('a: median = {0:.2f}'.format(a_hat))

plt.savefig('FigZ_a.png')

plt.show()

 

sb.kdeplot(fit['b'])

plt.title('b: median = {0:.2f}'.format(b_hat))

plt.savefig('FigZ_b.png')

plt.show()

 

plt.plot(fit['b'], fit['a'], 'o')

plt.xlabel('b', fontsize = 16)

plt.ylabel('a', fontsize = 16)

plt.savefig('FigZ_ab.png')

plt.show()

 

plt.plot(Z, Y, 'o')

plt.plot([min(Z), max(Z)], [a_hat + b_hat * min(Z), a_hat + b_hat * max(Z)],

        label = 'Regression Line')

plt.plot(0, a_hat, 's', c = 'r', label = (r'(0, $\hat{a}$)')  + ('\n$\hata$={0:.2f}'.format(a_hat)))

plt.xlabel(r'Z = X - $\bar{X}$', fontsize = 16)

plt.ylabel('Y', fontsize = 16)

plt.legend(fontsize = 14)

plt.savefig('FigZ_regress.png')

plt.show()

 

リスト3のスクリプトを実行すると、以下の出力を得る。

図6 aの事後分布

 

図7 bの事後分布

 

図8 (b,a)の散布図

 

図9 回帰直線

 

 

Up