Home

拙著「Pythonデータ分析の第15章「PyMCによるポアッソン回帰モデル分析」更新

 

スクリプトをリスト1に示すように更新した。スクリプトファイルは、圧縮ファイルc15file.zipとして用意した。ダウンロード展開すれば自由に利用できる。

スクリプトの実行は、Python 3.10/Anaconda/Ubuntu/WSL/Windowsで行った。すなわち、WindowsWSL (Windows Subsystem for Linux)をインストールするとUbuntuもインストールされるので、そのUbuntuAnacondaをインストールしてPython 3.10仮想環境を用意した。Python 3.10仮想環境においてコマンド

 

conda install pymc3

 

によりPyMC3をインストールした。詳しくは、このウェブサイトを参照されたい。

 

リスト1のスクリプトをPython 3.10仮想環境において実行した。

 

(py310) ・・・/c15file$ python PssnRegPyMC3.py

 

スクリプトを実行すると、MCMCサンプリングが始まり、終了後、トレースグラフが表示される(図1)。

図1

 

図1のフォームを閉じると、図2のグラフが表示される。

図2

 

主効果、a2a3b2b3の事後分布のグラフである。拙著の表8.2.2において、セル(小学生の時に知った、心理学臨床心理学)を基準に主効果などが表されているが(拙著の表12.2)、a3b3の事後分布が正の領域に位置していることは、「高校生のとき」および「心理学>臨床心理学」の条件での度数が多いことに対応している。

図2のフォームを閉じると、図3のグラフが表示される。

図3

 

交互作用g32の事後分布は負の領域に寄っており、g33の分布はほぼ負の領域にある。主効果のみで表される度数に比べて、セル(高校生、その他)および(高校生、心理学>臨床心理学)の度数が少ないことが表されている。

図3のフォームを閉じると、図4のグラフが表示される。

図4

 

ポアッソン分布(拙著p.203

におけるパラメータの推定値(事後分布の中央値)とデータ値の散布図である。ポアッソン分布の平均値は、そのパラメータに等しいことに注意。

図4のフォームを閉じると、端末に次のメッセージが表示されて、スクリプトの実行終了となる。

 

summary.txt was saved.

 

出力ファイルの内容は、以下のようである。

 

Summary...

           mean     sd  hdi_3%  hdi_97%  mcse_mean  mcse_sd  ess_bulk  ess_tail  r_hat

mu       -0.383  1.105  -2.464    1.527      0.027    0.021    1927.0    1750.0    1.0

a2        1.294  1.250  -0.993    3.744      0.029    0.023    2009.0    1938.0    1.0

a3        2.083  1.181   0.096    4.466      0.028    0.022    1993.0    2013.0    1.0

b2       -0.207  1.667  -3.399    2.972      0.034    0.024    2454.0    2771.0    1.0

b3        2.626  1.151   0.716    4.951      0.028    0.021    1911.0    1832.0    1.0

g22      -0.277  1.931  -3.823    3.495      0.037    0.026    2731.0    3772.0    1.0

g23      -1.281  1.323  -3.874    1.121      0.030    0.024    2064.0    2353.0    1.0

g32      -1.059  1.900  -4.775    2.478      0.036    0.026    2801.0    3528.0    1.0

g33      -3.062  1.335  -5.698   -0.746      0.030    0.023    2142.0    2124.0    1.0

Lmbd[0]   1.094  1.015   0.004    2.960      0.019    0.013    1927.0    1750.0    1.0

Lmbd[1]   0.995  0.991   0.000    2.802      0.012    0.008    4533.0    3470.0    1.0

Lmbd[2]   9.917  3.135   4.416   15.648      0.027    0.020   12453.0    9673.0    1.0

Lmbd[3]   2.964  1.716   0.441    6.127      0.017    0.012    8779.0    6773.0    1.0

Lmbd[4]   1.997  1.400   0.074    4.516      0.012    0.009   12448.0    9437.0    1.0

Lmbd[5]  10.042  3.146   4.580   16.057      0.028    0.020   12732.0    9698.0    1.0

Lmbd[6]   5.969  2.454   1.671   10.363      0.022    0.016   12411.0    9630.0    1.0

Lmbd[7]   2.011  1.416   0.030    4.496      0.012    0.009   12534.0    8864.0    1.0

Lmbd[8]   4.032  2.032   0.790    7.700      0.018    0.013   12339.0    9818.0    1.0

 

95%CI for a3 = [0.13184, 4.73770]

 

P(a3 > 0.0) = 0.983

P(b3 > 0.0) = 0.999

P(g33 < 0.0) = 0.997

 

 

 

リスト1.ポアッソン回帰モデル(PssnRegPyMC3.py

 

import matplotlib.pyplot as plt

import seaborn as sb

import numpy as np

import pymc3 as pm

 

RawData = [[1,  1, 0, 0, 1, 0, 0],

           [1,  1, 0, 0, 0, 1, 0],

           [10, 1, 0, 0, 0, 0, 1],

           [3,  0, 1, 0, 1, 0, 0],

           [2,  0, 1, 0, 0, 1, 0],

           [10, 0, 1, 0, 0, 0, 1],

           [6,  0, 0, 1, 1, 0, 0],

           [2,  0, 0, 1, 0, 1, 0],

           [4,  0, 0, 1, 0, 0, 1]]

 

F = []

Xr1 = []

Xr2 = []

Xr3 = []

Xc1 = []

Xc2 = []

Xc3 = []

for v in RawData:

    F.append(v[0])

    Xr1.append(v[1])

    Xr2.append(v[2])

    Xr3.append(v[3])

    Xc1.append(v[4])

    Xc2.append(v[5])

    Xc3.append(v[6])

 

for i in range(9):

    print(' ', F[i], '  ', Xr1[i], '  ', Xr2[i], '  ', Xr3[i],

          '  ', Xc1[i], '  ', Xc2[i], '  ', Xc3[i])

 

with pm.Model() as PoiModel:

    mu = pm.Normal('mu', mu = 0.0, sd = 10.0)

    a2 = pm.Normal('a2', mu = 0.0, sd = 10.0)

    a3 = pm.Normal('a3', mu = 0.0, sd = 10.0)

    b2 = pm.Normal('b2', mu = 0.0, sd = 10.0)

    b3 = pm.Normal('b3', mu = 0.0, sd = 10.0)

    g22 = pm.Normal('g22', mu = 0.0, sd = 10.0)

    g23 = pm.Normal('g23', mu = 0.0, sd = 10.0)

    g32 = pm.Normal('g32', mu = 0.0, sd = 10.0)

    g33 = pm.Normal('g33', mu = 0.0, sd = 10.0)

    LogLmbd = mu + a2 * Xr2 + a3 * Xr3 + b2 * Xc2 + b3 * Xc3 \

                                    + g22 * Xr2 * Xc2 + g23 * Xr2 * Xc3 \

                                    + g32 * Xr3 * Xc2 + g33 * Xr3 * Xc3

    #Lmbd = np.exp(LogLmbd)

    Lmbd = pm.Deterministic('Lmbd', np.exp(LogLmbd))

 

    F_obs = pm.Poisson('F_obs', mu = Lmbd, observed = F)

    trace = pm.sample(draws = 3000, tune = 3000, target_accept = 0.95)

 

    pm.plot_trace(trace, var_names = ['a2', 'a3', 'b2', 'b3'])

    plt.show()

 

    summary = pm.summary(trace)

    print(summary)

    f = open('summary.txt', 'w')

    f.write('Summary...\n{}'.format(summary))

 

    smpl_a3 = trace['a3']

    a3_p2p5 = np.percentile(smpl_a3, 2.5)

    a3_p97p5 = np.percentile(smpl_a3, 97.5)

    print('\n95%CI for a3 = [{0:.5f}, {1:.5f}]'.format(a3_p2p5, a3_p97p5))

    f.write('\n\n95%CI for a3 = [{0:.5f}, {1:.5f}]\n'.format(a3_p2p5, a3_p97p5))

 

    cnt_a3_pos = (smpl_a3 > 0.0).sum()

    print('\nP(a3 > 0.0) = {0:.3f}'.format(cnt_a3_pos / len(smpl_a3)))

    f.write('\nP(a3 > 0.0) = {0:.3f}\n'.format(cnt_a3_pos / len(smpl_a3)))

 

    sb.kdeplot(trace['a2'], label = 'a2')

    sb.kdeplot(trace['a3'], label = 'a3')

    sb.kdeplot(trace['b2'], label = 'b2')

    sb.kdeplot(trace['b3'], label = 'b3')

    plt.legend()

    plt.show()

           

    smpl_b3 = trace['b3']

    cnt_b3_pos = (smpl_b3 > 0.0).sum()

    print('P(b3 > 0.0) = {0:.3f}'.format(cnt_b3_pos / len(smpl_b3)))

    f.write('P(b3 > 0.0) = {0:.3f}\n'.format(cnt_b3_pos / len(smpl_b3)))

           

    smpl_g33 = trace['g33']

    cnt_g33_neg = (smpl_g33 < 0.0).sum()

    print('P(g33 < 0.0) = {0:.3f}'.format(cnt_g33_neg / len(smpl_g33)))

    f.write('P(g33 < 0.0) = {0:.3f}\n'.format(cnt_g33_neg / len(smpl_g33)))

 

    sb.kdeplot(trace['g22'], label = 'g22')

    sb.kdeplot(trace['g23'], label = 'g23')

    sb.kdeplot(trace['g32'], label = 'g32')

    sb.kdeplot(trace['g33'], label = 'g33')

    plt.legend()

    plt.show()

 

    N= 9

    lmbd_hat = np.empty(N)

    for i in range(N):

        lmbd_hat[i] = np.median(trace['Lmbd'][:,i])

        plt.plot(lmbd_hat[i], F[i], 'o', c='b')

    min_lmbd_hat = np.min(lmbd_hat)

    max_lmbd_hat = np.max(lmbd_hat)

    plt.plot([min_lmbd_hat, max_lmbd_hat], [min_lmbd_hat, max_lmbd_hat],

         label = '$F = \hat{\lambda}$')

    plt.xlabel('$\hat{\lambda}$', fontsize = 16)

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

    plt.legend(fontsize = 16)

    plt.tight_layout()

    plt.show()

         

    f.close()

 

 

 

Home