Up

Comparison of Point Estimates in Bayesian Analyisi

Means, medians, and modes of posterior distributions

Yasuharu Okamoto

 

When we want to estimate values for parameters in a model, there are several methods. Methods of moments or maximum likelihood estimates (MLEs) are popular ones. If we use a Bayesian method, we must estimate the value for a parameter from the posterior distribution. Means, medians, and modes are popular statistics, which represent the position of the distribution. Different researches recommend different statistics. Means are recommended by Lambert (2018). But, Gelman et al. (2021) criticized means as unstable, and recommend medians. Furthermore, Gelman et al. (2021) say the posterior mode, which provides the best overall fit to data and prior distribution (p. 107).

Okamoto (2022) compared the three statistics and concluded that the mode is best, as shown in the following.

 

Okamoto (in press) discussed the three models, a binomial model, a univariate normal distribution, and a bivariate normal distribution. The script files, which were edited versions of the scripts used in the calculations for Okamoto (in press), were archived in the file PointEstimates.zip. This file PointEstimates.zip can be freely downloaded and used on users responsibility

.

In the case of a binomial model,

the posterior distribution for the uniform prior distribution is obtained as a beta distribution. As shown in Figure 1, the mode seems to be the best.

Figure 1

 

The graph in Figure 1 was drawn by the Python script in Listing 1.

 

To compare the three estimates, biases and RMSEs (root mean square error) were calculated for sample sizes N=100 and N=200. Figures 2, 3 and 4 show the results for true value . These figures were drawn by the script in Listing 2.

Figure 2

 

Figure 3

 

Figure 4

 

 

In the case of a normal distribution, the following model was set:

 

Run the script in Listing 3, we get the results in the file ResultsCheck.txt as follows:

 

*/n_samples

  20

*/Biases_mu_mean

 -0.007041961545885269

*/Biases_mu_median

 -0.006976374519543286

*/Biases_mu_map

 -0.007209074323586536

*/SEBiases_mu_mean

 0.007150514505840424

*/SEBiases_mu_median

 0.0071495556400130765

*/SEBiases_mu_map

 0.0071892461915072006

*/Biases_sgm_mean

 0.05242901233745667

*/Biases_sgm_median

 0.027014065601938864

*/Biases_sgm_map

 -0.014603021898702995

*/SEBiases_sgm_mean

 0.0053799409384119945

*/SEBiases_sgm_median

 0.005250154481094522

*/SEBiases_sgm_map

 0.005062170454121036

*/rms_mu_mean

 0.22611571609012457

*/rms_mu_median

 0.22608339060008384

*/rms_mu_map

 0.22734455413293206

*/se_rms_mu_mean

 0.04788157166709367

*/se_rms_mu_median

 0.04786410713297506

*/se_rms_mu_map

 0.04789616874476579

*/rms_sgm_mean

 1.066077692640595

*/rms_sgm_median

 1.0403338160886175

*/rms_sgm_map

 0.9983021329177043

(*/se_rms_sgm_mean

 0.1074652838233129

*/se_rms_sgm_median

 0.10488630620335115

*/se_rms_sgm_map

 0.10089430461605017

 

Actual results vary from the results shown in Table 1 of Okamoto(in press). The differences between these values and the values in Table 1 of Okamoto (in press) can be accepted when considering the values SE.

 

 

In the case of a bivariate normal distribution, the following model was set:

 

When we run the script in Listing 5, we get the results in the file ResultsN50.txt like the following:

 

*/bias_mean

 0.009920408994082704 0.03211452354398249 0.028884218740121793 -0.0026328761413996504 -0.026355866314786165 -0.012562849096223934 -0.011020725687830983

*/SE_bias_mean

 0.002166293613514624 0.006352606295812506 0.010099708755636351 0.009203343499895711 0.009020196954548528 0.006314623678249787 0.0022096789585528158

*/bias_median

 0.006090627925731067 0.024341765670074733 0.024130178778043306 -0.0028000087042905856 -0.021459953799896535 -0.004869294532790663 -0.007182361311745917

*/SE_bias_median

 0.0021051499843991453 0.00635456231224322 0.010251353698944778 0.00938546793307021 0.00915324564903438 0.006312780165466433 0.0021495696801992837

*/bias_MAP

 -0.0009005450272513482 0.008310915545777241 0.014341217060853001 -0.0029016450822541505 -0.011427571378569002 0.010712035601780039 -0.0003035151757588828

*/SE_bias_MAP

 0.0020021970253489233 0.0063518630703183025 0.01063789456229552 0.009772134749041317 0.009408831241654925 0.0062622276474516075 0.002017314661103084

*/RMSE_mean

 0.032129227979843716 0.09519510683657403 0.14537234044003708 0.12985583090725422 0.1299463672284583 0.0899602420227911 0.03306221307717857

*/SE_RMSE_mean

 0.011974161331843314 0.030981311084084282 0.044360908885495584 0.04001050562758937 0.04044402305213406 0.028420072573137268 0.012871139613899383

*/RMSE_median

 0.03031493663915568 0.09288828521289981 0.14661250222055833 0.1324279226785622 0.13089357850366642 0.08918574728806637 0.031162407259530567

*/SE_RMSE_median

 0.011252491414637482 0.030074829818920106 0.04466027762934707 0.04078827914170566 0.040889195247272775 0.028106586876200927 0.012099536376119631

*/RMSE_MAP

 0.028258817634165195 0.08998865509362647 0.1507496794350532 0.1378834596219362 0.1332189338985517 0.08898669132699984 0.02845934383291899

*/SE_RMSE_MAP

 0.010333327247190044 0.028340088036870655 0.04603693301893274 0.04251454110788044 0.04156855256467426 0.027453424591980552 0.01051948475436297

 

Values in each line denote the values for parameter values  to 0.9. These values are not exactly the same as in Tables 2 and 3. These discrepancies are due to the method of the simulation, in which random number generator is used, so the results vary from simulation to simulation. The values of SEs show that the discrepancies between the above values and values in Tables 2 and 3 are within variations due to a random number generator.

 

 

 

References

Gelman, A., Hill, J., & Vehtari, A. (2021). Regression and other stories. Cambridge University Press.

Lambert, B. (2018). A students guide to Bayesian statistics. SAGE.

Okamoto, Y. (2022). Some comparisons of point estimates of parameters by Bayesian analysis with respect to RMSE and bias: A report from the point of view of experimental psychology. The Japanese Journal of Psychonomic Science, vol. 41, No. 1. https://doi.org/10.14947/psychono.41.1

 

 

 

Listing 1. The script for drawing the graph in Figure 1.

import numpy as np

import scipy.stats as ss

import matplotlib.pyplot as plt

import scipy.optimize as so

 

 

class Func_med:

    def __init__(self, f):

        self.f = f

    def v(self, t):

        #return self.f(t[0]) - 0.5

        return self.f(t) - 0.5

 

 

X = 1

N = 100

 

d_func = ss.beta(X+1, N-X+1)

 

t_range = np.linspace(0, 0.05)

t_v = d_func.pdf(t_range)

 

mean_v = (X+1) / (N+2)

mode_v = X / N

print('mean = ', mean_v)

print('mode = ', mode_v)

 

d_func = ss.beta(X+1, N-X+1)

func_med = Func_med(d_func.cdf)

f_med = func_med.v

median_v = so.bisect(f_med, 0.0, 1.0)

 

plt.title('Beta(θ|2,100)', fontsize = 16)

plt.plot([0, 0.05], [0.0, 0.0], color = 'k', ls = '-', lw = 1)

plt.plot(t_range, t_v, color = 'k', lw = 2)

plt.plot([mean_v, mean_v], [0, d_func.pdf(mean_v)], c = 'k', lw = 1.5,

         ls = '-.', label = f'mean:{mean_v:.4f}')

plt.plot([median_v, median_v], [0, d_func.pdf(median_v)], c = 'k', lw = 1.5,

         linestyle = (0, (5,1,2,1,2,1)), label = f'median:{median_v:.4f}')

plt.plot([mode_v, mode_v], [0, d_func.pdf(mode_v)], c = 'k',

         ls = '--', lw = 1.5, label = f'mode:{mode_v:.4f}')

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

plt.xticks(fontsize = 14)

plt.yticks([])

plt.legend(fontsize = 14)

plt.tight_layout()

plt.savefig('Figure1.png')

plt.show()

 

 

Listing 2.  The script for Figures 2, 3 and 4.

import numpy as np

import scipy.stats as ss

import matplotlib.pyplot as plt

import scipy.optimize as so

 

X = 1

N = 100

 

d_func = ss.beta(X+1, N-X+1)

 

t_range = np.linspace(0, 0.05)

t_v = d_func.pdf(t_range)

 

mean_v = (X+1) / (N+2)

mode_v = X / N

print('mean = ', mean_v)

print('mode = ', mode_v)

 

 

class Func_med:

    def __init__(self, f):

        self.f = f

    def v(self, t):

        return self.f(t) - 0.5

 

N = 100

 

p_true_range = [v/100 for v in range(1, 100)]

 

print(p_true_range)

 

bias_mean = []

bias_median = []

bias_mode = []

RMSE_mean = []

RMSE_median = []

RMSE_mode = []

RMSER_mean = []

RMSER_median = []

RMSER_mode = []

 

for p_true in p_true_range:

    print(p_true, end = '\r')

    v_sum_mean = 0.0

    v_sum_mode = 0.0

    v_sum_med = 0.0

    ssum_mean = 0.0

    ssum_mode = 0.0

    ssum_med = 0.0

    for X in range(0, N + 1):

        p = ss.binom.pmf(X, N, p_true)

        #print('p =', p)

        v_sum_mean += p * (X + 1) / (N + 2)

        v_sum_mode += p * X / N

        ssum_mean += p * ((X +1) / (N+2) - p_true) ** 2

        ssum_mode += p * ((X / N) - p_true) ** 2

 

       

        d_func = ss.beta(X+1, N-X+1)

        func_med = Func_med(d_func.cdf)

        f_med = func_med.v

        v_med = so.bisect(f_med, 0.0, 1.0)

        v_sum_med += p * v_med

        ssum_med += p * (v_med - p_true) ** 2

       

    bias_mean.append(v_sum_mean - p_true)

    bias_median.append(v_sum_med - p_true)

    bias_mode.append(v_sum_mode - p_true)

    RMSE_mean.append(ssum_mean ** 0.5)

    RMSE_median.append(ssum_med ** 0.5)

    RMSE_mode.append(ssum_mode ** 0.5)

    RMSER_mean.append((ssum_mean ** 0.5) / p_true)

    RMSER_median.append((ssum_med ** 0.5) / p_true)

    RMSER_mode.append((ssum_mode ** 0.5) / p_true)

 

 

N2 = 200

 

p_true_range = [v/100 for v in range(1, 100)]

 

print(p_true_range)

 

bias_mean2 = []

bias_median2 = []

bias_mode2 = []

RMSE_mean2 = []

RMSE_median2 = []

RMSE_mode2 = []

RMSER_mean2 = []

RMSER_median2 = []

RMSER_mode2 = []

 

for p_true in p_true_range:

    print(f'{p_true} for N2', end = '\r')

    v_sum_mean = 0.0

    v_sum_mode = 0.0

    v_sum_med = 0.0

    ssum_mean = 0.0

    ssum_mode = 0.0

    ssum_med = 0.0

    for X in range(0, N2 + 1):

        p = ss.binom.pmf(X, N2, p_true)

        v_sum_mean += p * (X + 1) / (N2 + 2)

        v_sum_mode += p * X / N2

        ssum_mean += p * ((X +1) / (N2+2) - p_true) ** 2

        ssum_mode += p * ((X / N2) - p_true) ** 2

 

       

        d_func = ss.beta(X+1, N2-X+1)

        func_med = Func_med(d_func.cdf)

        f_med = func_med.v

        v_med = so.bisect(f_med, 0.0, 1.0)

        v_sum_med += p * v_med

        ssum_med += p * (v_med - p_true) ** 2

       

    bias_mean2.append(v_sum_mean - p_true)

    bias_median2.append(v_sum_med - p_true)

    bias_mode2.append(v_sum_mode - p_true)

    RMSE_mean2.append(ssum_mean ** 0.5)

    RMSE_median2.append(ssum_med ** 0.5)

    RMSE_mode2.append(ssum_mode ** 0.5)

    RMSER_mean2.append((ssum_mean ** 0.5) / p_true)

    RMSER_median2.append((ssum_med ** 0.5) / p_true)

    RMSER_mode2.append((ssum_mode ** 0.5) / p_true)

 

plt.title('Bias', fontsize = 16)

plt.plot(p_true_range, bias_mean, c = 'k', ls = (0,(4,1)), lw = 2, label = 'mean(N=100)')

plt.plot(p_true_range, bias_median, c = 'k', ls = (0,(4,1,2,1)), lw = 2, label = 'median(N=100)')

plt.plot(p_true_range, bias_mean2, c = 'k', ls = (0,(4,1)), lw = 1, label = 'mean(N=200)')

plt.plot(p_true_range, bias_median2, c = 'k', ls = (0,(4,1,2,1)), lw = 1, label = 'median(N=200)')

plt.plot(p_true_range, bias_mode, c = 'k', ls = (0,(1,2)), lw = 2, label = 'MAP(N=100)')

plt.plot(p_true_range, bias_mode2, c = 'k', ls = (2,(2,2)), lw = 1, label = 'MAP(N=200)')

plt.xticks(fontsize = 14)

plt.xlabel(r'$\theta_0$', fontsize = 16)

plt.legend()

plt.tight_layout()

plt.savefig('Figure_2.png')

plt.show()

 

plt.title('RMS Error', fontsize = 16)

 

plt.plot(p_true_range, RMSE_mode, c = 'k', ls = (0,(1,2)), lw = 2, label = 'MAP(N=100)')

plt.plot(p_true_range, RMSE_median, c = 'k', ls = (0,(4,1,2,1)), lw = 2, label = 'median(N=100)')

plt.plot(p_true_range, RMSE_mean, c = 'k', ls = (0,(4,1)), lw = 2, label = 'mean(N=100)')

plt.plot(p_true_range, RMSE_mode2, c = 'k', ls = (2,(2,2)), lw = 1, label = 'MAP(N=200)')

plt.plot(p_true_range, RMSE_median2, c = 'k', ls = (0,(4,1,2,1)), lw = 1, label = 'median(N=200)')

plt.plot(p_true_range, RMSE_mean2, c = 'k', ls = (0,(4,1)), lw = 1, label = 'mean(N=200)')

plt.legend(fontsize = 12)

plt.xlabel(r'$θ_0$', fontsize = 13)

plt.tight_layout()

plt.savefig('Figure_3.png')

plt.show()

 

plt.title(r'RMS Error / $θ_0$', fontsize = 16)

 

plt.plot(p_true_range[:20], RMSER_mean[:20], c = 'k', ls = (0,(4,1)), lw = 2, label = 'mean(N=100)')

plt.plot(p_true_range[:20], RMSER_median[:20], c = 'k', ls = (0,(4,1,2,1)), lw = 2, label = 'median(N=100)')

plt.plot(p_true_range[:20], RMSER_mode[:20], c = 'k', ls = (0,(1,2)), lw = 2, label = 'MAP(N=100)')

plt.plot(p_true_range[:20], RMSER_mean2[:20], c = 'k', ls = (0,(4,1)), lw = 1, label = 'mean(N=200)')

plt.plot(p_true_range[:20], RMSER_median2[:20], c = 'k', ls = (0,(4,1,2,1)), lw = 1, label = 'median(N=200)')

plt.plot(p_true_range[:20], RMSER_mode2[:20], c = 'k', ls = (2,(2,2)), lw = 1, label = 'MAP(N=200)')

plt.xlabel(r'$\theta_0$', fontsize = 14)

plt.legend(fontsize = 14)

plt.tight_layout()

plt.savefig('Figure4.png')

plt.show()

 

 

Listing 3. The script for simulation of a univariate normal distribution, which uses Stan script in Listing 4.

import pystan

import numpy as np

import scipy.stats as ss

import matplotlib.pyplot as plt

import seaborn as sb

import pickle

import random

import tkinter as tk

 

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

 

with open('sm.pkl', 'wb') as f:

    pickle.dump(sm, f)

 

n_simu =  1000 

 

fout = open(f'ResultsCheck.txt', 'w')

 

Biases_mu_mean = []

Biases_mu_median = []

Biases_mu_map = []

SEBiases_mu_mean = []

SEBiases_mu_median = []

SEBiases_mu_map = []

Biases_sgm_mean = []

Biases_sgm_median = []

Biases_sgm_map = []

SEBiases_sgm_mean = []

SEBiases_sgm_median = []

SEBiases_sgm_map = []

 

rms_mu_mean = []

rms_mu_median = []

rms_mu_map = []

se_rms_mu_mean = []

se_rms_mu_median = []

se_rms_mu_map = []

 

rms_sgm_mean = []

rms_sgm_median = []

rms_sgm_map = []

se_rms_sgm_mean = []

se_rms_sgm_median = []

se_rms_sgm_map = []

 

n_samples = 20

 

mu_means = []

mu_medians = []

mu_maps = []

sgm_means = []

sgm_medians = []

sgm_maps = []

 

root = tk.Tk()

root.attributes('-topmost', True)

cnvs = tk.Canvas(root, bg = '#ffffff', width = 400, height = 200)

cnvs.pack()

cnvs.create_text(200, 100, text = 'Simulation started.',font = ('Gothic', 48), tags = 'mytext')

cnvs.update()

 

for trial in range(n_simu):

    cnvs.itemconfig('mytext', text = '{0}/{1}'.format(trial+1, n_simu))

    cnvs.update()

 

    X = ss.norm().rvs(size = n_samples)

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

    with open('sm.pkl', 'rb') as f:

        sm = pickle.load(f)

    fit = sm.sampling(data = Data, control=dict(adapt_delta=0.97, max_treedepth = 30), n_jobs = 1)

 

    Smpl_mu = fit['mu']

    Mean_E = Smpl_mu.mean()

    mu_means.append(Mean_E)

    Med_E = np.percentile(Smpl_mu, 50)

    mu_medians.append(Med_E)

    L_mu = np.percentile(Smpl_mu, 2.5)

    U_mu = np.percentile(Smpl_mu, 97.5)

    n_points = 10000

    coord = np.linspace(L_mu, U_mu, n_points)

    est_pdf = ss.gaussian_kde(Smpl_mu).pdf(coord)

    map_idx = np.argmax(est_pdf)

    MAP_E = coord[map_idx]

    mu_maps.append(MAP_E)

 

    Smpl_sgm = fit['sgm']

    Mean_E = Smpl_sgm.mean()

    sgm_means.append(Mean_E)

    Med_E = np.percentile(Smpl_sgm, 50)

    sgm_medians.append(Med_E)

    L_sgm = 0.0 # Smpl_sgm.min()

    U_sgm = np.percentile(Smpl_sgm, 99)

    n_points = 10000

    coord = np.linspace(L_sgm, U_sgm, n_points)

    est_pdf = ss.gaussian_kde(Smpl_sgm).pdf(coord)

    map_idx = np.argmax(est_pdf)

    MAP_E = coord[map_idx]

    sgm_maps.append(MAP_E)

 

root.destroy()

 

mu_means = np.array(mu_means)

mu_medians = np.array(mu_medians)

mu_maps = np.array(mu_maps)

mu_mean_bias = mu_means.mean() - 0.0

mu_median_bias = mu_medians.mean() - 0.0

mu_map_bias = mu_maps.mean() - 0

mu_mean_se = ss.sem(mu_means)

mu_median_se = ss.sem(mu_medians)

mu_map_se = ss.sem(mu_maps)

 

Biases_mu_mean.append(mu_mean_bias)

Biases_mu_median.append(mu_median_bias)

Biases_mu_map.append(mu_map_bias)

SEBiases_mu_mean.append(mu_mean_se)

SEBiases_mu_median.append(mu_median_se)

SEBiases_mu_map.append(mu_map_se)

 

mss_mu_means = ((mu_means - 0.0) ** 2).mean()

rms_mu_mean.append(mss_mu_means ** 0.5)

t_sem = ss.sem((mu_means - 0.0) ** 2)

se_rms_mu_mean.append(t_sem ** 0.5)

 

mss_mu_medians = ((mu_medians - 0.0) ** 2).mean()

rms_mu_median.append(mss_mu_medians ** 0.5)

t_sem = ss.sem((mu_medians - 0.0) ** 2)

se_rms_mu_median.append(t_sem ** 0.5)

 

mss_mu_maps = ((mu_maps - 0.0) ** 2).mean()

rms_mu_map.append(mss_mu_maps ** 0.5)

t_sem = ss.sem((mu_maps - 0.0) ** 2)

se_rms_mu_map.append(t_sem ** 0.5)

 

sgm_means = np.array(sgm_means)

sgm_medians = np.array(sgm_medians)

sgm_maps = np.array(sgm_maps)

sgm_mean_bias = sgm_means.mean() - 1.0

sgm_median_bias = sgm_medians.mean() - 1.0

sgm_map_bias = sgm_maps.mean() - 1.0

sgm_mean_se = ss.sem(sgm_means)

sgm_median_se = ss.sem(sgm_medians)

sgm_map_se = ss.sem(sgm_maps)

 

Biases_sgm_mean.append(sgm_mean_bias)

Biases_sgm_median.append(sgm_median_bias)

Biases_sgm_map.append(sgm_map_bias)

SEBiases_sgm_mean.append(sgm_mean_se)

SEBiases_sgm_median.append(sgm_median_se)

SEBiases_sgm_map.append(sgm_map_se)

 

mss_sgm_means = ((sgm_means - 0.0) ** 2).mean()

rms_sgm_mean.append(mss_sgm_means ** 0.5)

t_sem = ss.sem((sgm_means - 0.0) ** 2)

se_rms_sgm_mean.append(t_sem ** 0.5)

 

mss_sgm_medians = ((sgm_medians - 0.0) ** 2).mean()

rms_sgm_median.append(mss_sgm_medians ** 0.5)

t_sem = ss.sem((sgm_medians - 0.0) ** 2)

se_rms_sgm_median.append(t_sem ** 0.5)

 

mss_sgm_maps = ((sgm_maps - 0.0) ** 2).mean()

rms_sgm_map.append(mss_sgm_maps ** 0.5)

t_sem = ss.sem((sgm_maps - 0.0) ** 2)

se_rms_sgm_map.append(t_sem ** 0.5)

 

fout.write('*/n_samples\n')

fout.write(f'  {n_samples}')

fout.write('\n')

fout.write('*/Biases_mu_mean\n')

for v in Biases_mu_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/Biases_mu_median\n')

for v in Biases_mu_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/Biases_mu_map\n')

for v in Biases_mu_map:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SEBiases_mu_mean\n')

for v in SEBiases_mu_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SEBiases_mu_median\n')

for v in SEBiases_mu_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SEBiases_mu_map\n')

for v in SEBiases_mu_map:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/Biases_sgm_mean\n')

for v in Biases_sgm_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/Biases_sgm_median\n')

for v in Biases_sgm_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/Biases_sgm_map\n')

for v in Biases_sgm_map:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SEBiases_sgm_mean\n')

for v in SEBiases_sgm_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SEBiases_sgm_median\n')

for v in SEBiases_sgm_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SEBiases_sgm_map\n')

for v in SEBiases_sgm_map:

    fout.write(f' {v}')

fout.write('\n')

 

fout.write('*/rms_mu_mean\n')

for v in rms_mu_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/rms_mu_median\n')

for v in rms_mu_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/rms_mu_map\n')

for v in rms_mu_map:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/se_rms_mu_mean\n')

for v in se_rms_mu_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/se_rms_mu_median\n')

for v in se_rms_mu_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/se_rms_mu_map\n')

for v in se_rms_mu_map:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/rms_sgm_mean\n')

for v in rms_sgm_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/rms_sgm_median\n')

for v in rms_sgm_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/rms_sgm_map\n')

for v in rms_sgm_map:

    fout.write(f' {v}')

fout.write('\n')

fout.write('(*/se_rms_sgm_mean\n')

for v in se_rms_sgm_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/se_rms_sgm_median\n')

for v in se_rms_sgm_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/se_rms_sgm_map\n')

for v in se_rms_sgm_map:

    fout.write(f' {v}')

fout.write('\n')

 

fout.close()

 

 

Listing 4. A Stan script for a univariate normal distribution.

data {

    int N;

    real X[N];

}

parameters {

    real mu;

    real<lower = 0.0> sgm;

}

model {

    mu ~ normal(0.0, 1000.0);

    sgm ~ exponential(0.001);

    for (i in 1:N) {

        X[i] ~ normal(mu, sgm);

    }

}

 

 

 

Listing 5. Simulation for a bivariate normal distribution, which uses the Stan script in Listing 6.

import pystan

import numpy as np

import scipy.stats as ss

import matplotlib.pyplot as plt

import seaborn as sb

import pickle

import random

import tkinter as tk

 

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

 

with open('sm.pkl', 'wb') as f:

    pickle.dump(sm, f)

 

n_samples = 50

n_simu =  200

rhos = [-0.9, -0.6, -0.3, 0.0, 0.3, 0.6, 0.9]

 

 

bias_mean = []

bias_median = []

bias_MAP = []

SE_bias_mean = []

SE_bias_median = []

SE_bias_MAP = []

RMSE_mean = []

RMSE_median = []

RMSE_MAP = []

SE_RMSE_mean = []

SE_RMSE_median = []

SE_RMSE_MAP = []

 

 

root = tk.Tk()

root.attributes('-topmost', True)

cnvs = tk.Canvas(root, bg = '#ffffff', width = 400, height = 300)

cnvs.pack()

cnvs.create_text(200, 150, text = 'Simulation started.',font = ('Gothic', 32), tags = 'mytext')

cnvs.update()

 

for rho_true in rhos:

    #print('rho =', rho_true)   

    s_bias_mean = 0.0

    s_bias_median = 0.0

    s_bias_MAP = 0.0

    se_s_bias_mean = []

    se_s_bias_median = []

    se_s_bias_MAP = []

    ss_mean = 0.0

    ss_median = 0.0

    ss_MAP = 0.0

    se_ss_mean = []

    se_ss_median = []

    se_ss_MAP = []

    Means = []

    Medians = []

    MAPs = []

    for trial in range(n_simu):

       

        cnvs.itemconfig('mytext', text = f'rho = {rho_true}\ntrial = {trial+1}/{n_simu}')

        cnvs.update()

       

        X = 0

        u = np.random.normal(size = n_samples)

        v = np.random.normal(size = n_samples)

        random.shuffle(u)

        random.shuffle(v)

        t = u * ((1.0 - (rho_true**2))**0.5) + v * rho_true

        X = np.vstack([t, v]).T

       

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

        sm = 0

        with open('sm.pkl', 'rb') as f:

            sm = pickle.load(f)

        fit = 0

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

 

        Smpl_rho = fit['rho']

        Mean_E = Smpl_rho.mean()

        Med_E = np.percentile(Smpl_rho, 50)

        coord = np.linspace(-1.0, 1.0, 20000)

        est_pdf = ss.gaussian_kde(Smpl_rho).pdf(coord)

        map_idx = np.argmax(est_pdf)

        MAP_E = coord[map_idx]

       

        Means.append(Mean_E)

        Medians.append(Med_E)

        MAPs.append(MAP_E)

 

        s_bias_mean += Mean_E - rho_true

        s_bias_median += Med_E - rho_true

        s_bias_MAP += MAP_E - rho_true

        se_s_bias_mean.append(Mean_E - rho_true)

        se_s_bias_median.append(Med_E - rho_true)

        se_s_bias_MAP.append(MAP_E - rho_true)

        ss_mean += (Mean_E - rho_true) ** 2

        ss_median += (Med_E - rho_true) ** 2

        ss_MAP += (MAP_E - rho_true) ** 2

        se_ss_mean.append((Mean_E - rho_true) ** 2)

        se_ss_median.append((Med_E - rho_true) ** 2)

        se_ss_MAP.append((MAP_E - rho_true) ** 2)

       

    bias_mean.append(s_bias_mean / n_simu)

    bias_median.append(s_bias_median / n_simu)

    bias_MAP.append(s_bias_MAP / n_simu)

    SE_bias_mean.append(ss.sem(se_s_bias_mean))

    SE_bias_median.append(ss.sem(se_s_bias_median))

    SE_bias_MAP.append(ss.sem(se_s_bias_MAP))

    RMSE_mean.append((ss_mean / n_simu) ** 0.5)

    RMSE_median.append((ss_median / n_simu) ** 0.5)

    RMSE_MAP.append((ss_MAP / n_simu) ** 0.5)

    SE_RMSE_mean.append(ss.sem(se_ss_mean) ** 0.5)

    SE_RMSE_median.append(ss.sem(se_ss_median) ** 0.5)

    SE_RMSE_MAP.append(ss.sem(se_ss_MAP) ** 0.5)

 

root.destroy()

 

fout = open(f'ResultsN{n_samples}.txt', 'w')

 

print()

print('bias_mean =', bias_mean)

print('bias_edian =', bias_median)

print('bias_MAP =', bias_MAP)

print('RMSE_mean =', RMSE_mean)

print('RMSE_median =', RMSE_median)

print('RMSE_MAP =', RMSE_MAP)

 

fout.write('*/bias_mean\n')

for v in bias_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SE_bias_mean\n')

for v in SE_bias_mean:

    fout.write(f' {v}')

fout.write('\n')

 

fout.write('*/bias_median\n')

for v in bias_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SE_bias_median\n')

for v in SE_bias_median:

    fout.write(f' {v}')

fout.write('\n')

 

fout.write('*/bias_MAP\n')

for v in bias_MAP:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SE_bias_MAP\n')

for v in SE_bias_MAP:

    fout.write(f' {v}')

fout.write('\n')

 

fout.write('*/RMSE_mean\n')

for v in RMSE_mean:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SE_RMSE_mean\n')

for v in SE_RMSE_mean:

    fout.write(f' {v}')

fout.write('\n')

 

fout.write('*/RMSE_median\n')

for v in RMSE_median:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SE_RMSE_median\n')

for v in SE_RMSE_median:

    fout.write(f' {v}')

fout.write('\n')

 

fout.write('*/RMSE_MAP\n')

for v in RMSE_MAP:

    fout.write(f' {v}')

fout.write('\n')

fout.write('*/SE_RMSE_MAP\n')

for v in SE_RMSE_MAP:

    fout.write(f' {v}')

fout.write('\n')

 

fout.close()

 

 

Listing 6. A Stan script for a bivariate normal distribution

data {

    int N;

    vector[2] X[N];

}

parameters {

    real<lower = -1.0, upper = 1.0> rho;

    real mu1;

    real mu2;

    real<lower = 0.0> sgm1;

    real<lower = 0.0> sgm2;

}

transformed parameters {

    vector[2] mu;

    cov_matrix[2] cov;

    mu[1] = mu1;

    mu[2] = mu2;

    cov[1][1] = sgm1 * sgm1;

    cov[1][2] = rho * sgm1 * sgm2;

    cov[2][1] = rho * sgm1 * sgm2;

    cov[2][2] = sgm2 * sgm2;

}

model {

    rho ~ uniform(-1.0, 1.0);

    mu1 ~ normal(0.0, 1000.0);

    mu2 ~ normal(0.0, 1000.0);

    sgm1 ~ exponential(0.001);

    sgm2 ~ exponential(0.001);

    for (i in 1:N) {

        X[i] ~ multi_normal(mu, cov);

    }

}

 

 

Up