# Plot the simulated data plt.style.use('ggplot') plt.figure() plt.plot(data) plt.title('data') plt.xlabel('t') savefigs = False # change this if you want to save the plots as PDFs # N fixed, log-error as a function of t # ===================================== nruns = 1000 Ns = [100, 1000] T = 100 results = particles.multiSMC(fk=fk_mod(T), N=Ns, nruns=nruns) for N in Ns: # plot MSE of log-lik estimate vs time ll = np.array( [r['output'].summaries.logLts for r in results if r['N'] == N]) for t in range(T): ll[:, t] -= true_loglik[t] # confidence intervals + most extreme paths plt.figure() pctl = lambda x: np.percentile(ll, x, axis=0) plt.fill_between(np.arange(T), pctl(10), pctl(90), color='gray',
def runner(fk, des: OWA, diag_quantities: List, verbose=False) -> dict: """ Run a Feymann-Kac model fk for des.T times using des.cores cores. :return: A dictionary with keys like cpu, posterior_mean, posterior_variance, no_of_intermediate_dists, etc... The corresponding value of each of these keys is a list of length T tracing what happened for each run. Furthermore, synthetical keys like variance_of_posterior_mean are also included. """ #tested # def of(pf): # res = dict() # for qu in diag_quantities: # res.update({qu.name(): qu.extract(pf)}) # return res of = partial(_runner_of, diag_quantities=diag_quantities) out = dict() if isinstance(fk, FeynmanKacNew): # noinspection PyTypeChecker multiSMC = multiSMCNew(nruns=des.T, nprocs=des.cores, out_func=of, fk=fk, N=des.N, verbose=verbose, max_memory_in_MB=des.max_memory_in_MB) elif isinstance(fk, particles.FeynmanKac): # noinspection PyTypeChecker multiSMC = particles.multiSMC(nruns=des.T, nprocs=des.cores, out_func=of, fk=fk, N=des.N, ESSrmin=1.0) elif isinstance(fk, SMCTwice_signature): # noinspection PyProtectedMember multiSMC = multiSMCTwice(nruns=des.T, nprocs=des.cores, out_func=of, verbose=verbose, **fk._asdict()) else: raise ValueError('Unknown type of fk.') for q in diag_quantities: out.update({q.name() + 's': np.array([d[q.name()] for d in multiSMC])}) mean_cpu_time = np.mean(out['cpus']) for q in diag_quantities: if not (q.exact(des) is None): if np.isnan(q.exact(des)): ref = np.mean(out[q.name() + 's']) else: ref = q.exact(des) SEs = (out[q.name() + 's'] - ref)**2 # squared errors mse_hat = np.mean(SEs) std_mse_hat = 1 / np.sqrt(len(SEs)) * np.std(SEs) out.update({ 'adjusted_error_' + q.name() + '_low': mean_cpu_time * (mse_hat - 1.96 * std_mse_hat), 'adjusted_error_' + q.name() + '_high': mean_cpu_time * (mse_hat + 1.96 * std_mse_hat) }) out['exact_' + q.name()] = q.exact(des) return out
ESSrmin = 0.5 lc = 500 N = 200 move = ssps.MCMCSequenceWF(mcmc=bin.BinaryMetropolis(), len_chain=lc) else: ESSrmin = 0.9 lc = 10 + 1 N = 4_000 move = ssps.MCMCSequence(mcmc=bin.BinaryMetropolis(), len_chain=lc) fk = ssps.AdaptiveTempering(model, ESSrmin=ESSrmin, len_chain=lc, wastefree=waste, move=move) results = particles.multiSMC(fk=fk, N=N, verbose=True, nruns=nruns, nprocs=1) ps = np.array([ np.average(r['output'].X.theta, weights=r['output'].W, axis=0) for r in results ]) ph = ps.mean(axis=0) # pf = particles.SMC(fk=fk, N=1000, verbose=True) # pf.run() # jitted=True, wall time = 1291 s (user 5444) # jitted=mock true, wall time = 1150 s # jitted=False, wall time = 1027 s (user 1487) # IPython CPU timings (estimated):
true_loglik, true_filt_means = {}, {} for d in dims: ssm = kalman.MVLinearGauss_Guarniero_etal(alpha=alpha0, dx=d) _, data = ssm.simulate(T) kf = kalman.Kalman(ssm=ssm, data=data) kf.filter() true_loglik[d] = np.cumsum(kf.logpyt) true_filt_means[d] = [f.mean for f in kf.filt] models['boot_%i' % d] = ssms.Bootstrap(ssm=ssm, data=data) models['guided_%i' % d] = ssms.GuidedPF(ssm=ssm, data=data) # Get results N = 10**4 results = particles.multiSMC(fk=models, qmc=[False, True], N=N, collect=[Moments], nruns=100, nprocs=1) # Format results results_mse = [] for d in dims: for t in range(T): # this returns the estimate of E[X_t(1)|Y_{0:t}] estimate = lambda r: r['output'].summaries.moments[t]['mean'][0] for type_fk in ['guided', 'boot']: for qmc in [False, True]: est = np.array([ estimate(r) for r in results if r['qmc'] == qmc and r['fk'] == type_fk + '_%i' % d ])
# instantiate models models = OrderedDict() true_loglik, true_filt_means = {}, {} for d in dims: ssm = kalman.MVLinearGauss_Guarniero_etal(alpha=alpha0, dx=d) _, data = ssm.simulate(T) kf = kalman.Kalman(ssm=ssm, data=data) kf.filter() true_loglik[d] = np.cumsum(kf.logpyt) true_filt_means[d] = [f.mean for f in kf.filt] models['boot_%i' % d] = ssms.Bootstrap(ssm=ssm, data=data) models['guided_%i' % d] = ssms.GuidedPF(ssm=ssm, data=data) # Get results N = 10**4 results = particles.multiSMC(fk=models, qmc=[False, True], N=N, moments=True, nruns=100, nprocs=1) # Format results results_mse = [] for d in dims: for t in range(T): # this returns the estimate of E[X_t(1)|Y_{0:t}] estimate = lambda r: r['output'].summaries.moments[t]['mean'][0] for type_fk in ['guided', 'boot']: for qmc in [False, True]: est = np.array( [estimate(r) for r in results if r['qmc']==qmc and r['fk']==type_fk+'_%i'%d] ) if type_fk=='guided' and qmc==False: #reference category base_mean = np.mean(est) base_mse = np.var(est) else:
'qmc': False }, 'ar_to_increase_Nx': 0.1, 'wastefree': False, 'len_chain': 6 } fks['smc2'] = ssp.SMC2(**fk_opts) fk_opts['smc_options']['qmc'] = True fks['smc2_qmc'] = ssp.SMC2(**fk_opts) fk_opts['ssm_cls'] = state_space_models.StochVol fks['smc2_sv'] = ssp.SMC2(**fk_opts) # runs runs = particles.multiSMC(fk=fks, N=N, collect=[Moments(mom_func=qtiles)], verbose=True, nprocs=0, nruns=25) # plots ####### savefigs = True # False if you don't want to save plots as pdfs plt.style.use('ggplot') colors = {'smc2': 'gray', 'smc2_qmc': 'black'} lsts = {'smc2': '--', 'smc2_qmc': '-'} prefix = 'smc2_sv_lvg_N%i' % N T = data.shape[0] # Figure 18.2: variance marginal likelihood vs time plt.figure()
def logLt(pf): return pf.logLt if __name__ == '__main__': sigma = 0.18 ng = 100 mu_grid = np.linspace(-2.5, 0., ng) rho_grid = np.linspace(-.999, .999, ng) mus, rhos = np.meshgrid(mu_grid, rho_grid) models = [fkmod(mu=mu, rho=rho, sigma=sigma) for mu, rho in zip(mus.flat, rhos.flat)] results = particles.multiSMC(fk=models, N=10 ** 4, qmc=True, nruns=1, nprocs=0, # multiprocessing! out_func=logLt) ll = np.array([r['output'] for r in results]) ll.shape = (ng, ng) # PLOT # ==== savefigs = True # False if you don't want to save plots as pdfs plt.figure() levels = ll.max() + np.linspace(-20, 0, 21) ctour = plt.contourf(mus, rhos, ll, levels, cmap=cm.gray_r, alpha=.8) # The two lines below are some black magic that ensures that the contour # plot looks well when turned into a pdf (otherwise, the contour lines # do not appear anymore; something to do with aliasing)
pf = particles.SMC(fk=fkmod, N=N, naive_online_smooth=True) pf.run() Ns['naive'] = int(N * avg_cpu['ON2'] / pf.cpu_time) print('rescaling N to %i to match CPU time' % Ns['naive']) long_names[method] += r', N=%i' % Ns[method] print(long_names[method]) args_smc = { 'fk': fkmod, 'nruns': nruns, 'nprocs': 1, 'N': N, attr_names[method]: True, 'out_func': partial(outf, method=attr_names[method]) } runs[method] = particles.multiSMC(**args_smc) avg_cpu[method] = np.mean([r['cpu'] for r in runs[method]]) print('average cpu time (across %i runs): %f' % (nruns, avg_cpu[method])) # Plots # ===== savefigs = True # False if you don't want to save plots as pdfs plt.style.use('ggplot') colors = {'ON2': 'gray', 'naive': 'black'} # IQR (inter-quartile ranges) as a function of time: Figure 11.3 plt.figure() estimates = { method: np.array([r['result'] for r in results]) for method, results in runs.items()
T = 100 model = ssms.Gordon() _, data = model.simulate(T) fk = ssms.Bootstrap(ssm=model, data=data) # Get results Ns = [2**k for k in range(6, 21)] of = lambda pf: { 'll': pf.logLt, 'EXt': [m['mean'] for m in pf.summaries.moments] } results = particles.multiSMC(fk=fk, qmc={ 'smc': False, 'sqmc': True }, N=Ns, moments=True, nruns=200, nprocs=1, out_func=of) drez = { 'smc': [r for r in results if r['qmc'] == 'smc'], 'sqmc': [r for r in results if r['qmc'] == 'sqmc'] } # Plots # ===== savefigs = False # change this to save figs as PDFs plt.rc('text', usetex=True) #to force tex rendering plt.style.use('ggplot')
#################### for alg_name, alg in algos.items(): print('\nRunning ' + alg_name) alg.run() print('CPU time: %.2f min' % (alg.cpu_time / 60)) # Compute variances ################### thin = int(niter / 100) # compute average (of variances) over 100 points thetas = algos['mh'].chain.theta[(burnin - 1)::thin] fks = {k: ssm.Bootstrap(ssm=ReparamLinGauss(**smc_samplers.rec_to_dict(th)), data=data) for k, th in enumerate(thetas)} outf = lambda pf: pf.logLt print('Computing variances of log-lik estimates as a function of N') results = particles.multiSMC(fk=fks, N=Nxs, nruns=4, nprocs=0, out_func=outf) df = pandas.DataFrame(results) df_var = df.groupby(['fk', 'N']).var() # variance as a function of fk and N df_var = df_var.reset_index() df_var_mean = df_var.groupby('N').mean() # mean variance as function of N # Plots ####### savefigs = False plt.style.use('ggplot') def msjd(theta): """Mean square jump distance. """ s = 0. for p in theta.dtype.names:
from particles import state_space_models as ssms from particles.collectors import Moments # instantiate model T = 100 model = ssms.Gordon() _, data = model.simulate(T) fk = ssms.Bootstrap(ssm=model, data=data) if __name__ == "__main__": # Actual computation Ns = [2**k for k in range(6, 21)] of = lambda pf: {'ll': pf.logLt, 'EXt': [m['mean'] for m in pf.summaries.moments]} results = particles.multiSMC(fk=fk, qmc={'smc': False, 'sqmc': True}, N=Ns, collect=[Moments], nruns=200, nprocs=0, out_func=of) drez = {'smc': [r for r in results if r['qmc'] == 'smc'], 'sqmc': [r for r in results if r['qmc'] == 'sqmc'] } # Plots # ===== savefigs = True # False if you don't want to save plots as pdfs plt.rc('text', usetex=True) # to force tex rendering plt.style.use('ggplot') plt.figure() colors = {'smc': 'gray', 'sqmc': 'black'} lsts = {'smc': '--', 'sqmc': '-'} for m in ['smc', 'sqmc']:
for method in methods: col = collectors[method] if method == 'naive': # rescale N to match CPU time pf = particles.SMC(fk=fkmod, N=Ns['naive'], collect=[col]) pf.run() Ns['naive'] = int(Ns['naive'] * avg_cpu['ON2'] / pf.cpu_time) print('rescaling N to %i to match CPU time' % Ns['naive']) long_names[method] += r', N=%i' % Ns[method] print(long_names[method]) runs[method] = particles.multiSMC(fk=fkmod, N=Ns[method], collect=[col], nruns=nruns, nprocs=1, out_func=partial( outf, method=col.summary_name)) avg_cpu[method] = np.mean([r['cpu'] for r in runs[method]]) print('average cpu time (across %i runs): %f' % (nruns, avg_cpu[method])) # Plots # ===== savefigs = True # False if you don't want to save plots as pdfs plt.style.use('ggplot') colors = {'ON2': 'gray', 'naive': 'black'} # IQR (inter-quartile ranges) as a function of time: Figure 11.3 plt.figure()
models['bootstrap'] = ssms.Bootstrap(ssm=my_ssm, data=data) models['guided'] = ssms.GuidedPF(ssm=my_ssm, data=data) models['APF'] = ssms.AuxiliaryPF(ssm=my_ssm, data=data) # Uncomment line below if you want to include the "Boostrap APF" # (APF with proposal set to dist. of X_t|X_{t-1}) in the comparison #models['bootAPF'] = ssm.AuxiliaryBootstrap(ssm=my_ssm, data=data) # Compute "truth" kf = kalman.Kalman(ssm=my_ssm, data=data) kf.filter() true_loglik = np.cumsum(kf.logpyt) true_filt_means = [f.mean for f in kf.filt] # Get results N = 10**3 results = particles.multiSMC(fk=models, N=N, nruns=1000, collect=[Moments]) # PLOTS # ===== plt.style.use('ggplot') savefigs = True # False if you don't want to save plots as pdfs # black and white sb.set_palette(sb.dark_palette("lightgray", n_colors=len(models), reverse=True)) # box-plots for log-likelihood evaluation plt.figure() sb.boxplot(x=[r['fk'] for r in results], y=[r['output'].logLt for r in results]) plt.ylabel('log-likelihood estimate')
data = preds, response # compare with full regression reg = lin.LinearRegression(fit_intercept=False) reg.fit(preds, response) # n, p = 30, 5 # preds = np.random.randn(n, p) # preds[:, 0] = 1. # intercept # noise = np.random.randn(n) # response = np.sum(preds[:, :3], axis=1) + 0.8 * noise # data = preds, response prior = dists.IID(bin.Bernoulli(0.5), npreds) model = bin.BayesianVS(data=data, prior=prior) # gam, l = model.complete_enum() # probs = rs.exp_and_normalise(l) # marg_probs = np.average(gam, weights=probs, axis=0) # print(marg_probs) N = 10**5 P = 1000 M = N // P move = ssps.MCMCSequenceWF(mcmc=bin.BinaryMetropolis(), len_chain=P) fk = ssps.AdaptiveTempering(model, len_chain=P, move=move) results = particles.multiSMC(fk=fk, N=M, verbose=True, nruns=50, nprocs=0) # pf = particles.SMC(fk=fk, N=1000, verbose=True) # pf.run()
x0 = np.zeros(dx) # TODO # models chosen_ssm = NeuralDecoding(a=a0, b=b0, x0=x0, delta=delta0, tau=tau0) _, data = chosen_ssm.simulate(T) models = OrderedDict() models['boot'] = state_space_models.Bootstrap(ssm=chosen_ssm, data=data) models['guided'] = state_space_models.GuidedPF(ssm=chosen_ssm, data=data) # models['apf'] = state_space_models.AuxiliaryPF(ssm=chosen_ssm, data=data) # Uncomment this if you want to include the APF in the comparison N = 10**4 nruns = 50 results = particles.multiSMC(fk=models, N=N, nruns=nruns, nprocs=1, moments=True, store_history=True) ## PLOTS ######### savefigs = True # False if you don't want to save plots as pdfs plt.style.use('ggplot') # arbitrary time t0 = 9 # check Gaussian approximation is accurate plt.figure() mu, Q = chosen_ssm.approx_likelihood(data[t0]) lG = lambda x: models['boot'].logG(t0, None, x)
models['bootstrap'] = ssms.Bootstrap(ssm=my_ssm, data=data) models['guided'] = ssms.GuidedPF(ssm=my_ssm, data=data) models['APF'] = ssms.AuxiliaryPF(ssm=my_ssm, data=data) # Uncomment line below if you want to include the "Boostrap APF" # (APF with proposal set to dist. of X_t|X_{t-1}) in the comparison #models['bootAPF'] = ssm.AuxiliaryBootstrap(ssm=my_ssm, data=data) # Compute "truth" kf = kalman.Kalman(ssm=my_ssm, data=data) kf.filter() true_loglik = np.cumsum(kf.logpyt) true_filt_means = [f.mean for f in kf.filt] # Get results N = 10**3 results = particles.multiSMC(fk=models, N=N, nruns=25, moments=True) # PLOTS # ===== plt.style.use('ggplot') savefigs = False # whether you want to save figs as pdfs # black and white sb.set_palette(sb.dark_palette("lightgray", n_colors=len(models), reverse=True)) # box-plots for log-likelihood evaluation plt.figure() sb.boxplot(x=[r['fk'] for r in results], y=[r['output'].logLt for r in results]) plt.ylabel('log-likelihood estimate')
b0 = random.normal(size=(dy, dx)) b0 = b0 / (linalg.norm(b0, axis=1)[:, np.newaxis]) delta0 = 0.03; tau0 = 1. x0 = np.zeros(dx) # models chosen_ssm = NeuralDecoding(a=a0, b=b0, x0=x0, delta=delta0, tau=tau0) _, data = chosen_ssm.simulate(T) models = OrderedDict() models['boot'] = ssms.Bootstrap(ssm=chosen_ssm, data=data) models['guided'] = ssms.GuidedPF(ssm=chosen_ssm, data=data) # models['apf'] = ssms.AuxiliaryPF(ssm=chosen_ssm, data=data) # Uncomment this if you want to include the APF in the comparison N = 10**4; nruns = 50 results = particles.multiSMC(fk=models, N=N, nruns=nruns, nprocs=1, collect=[Moments], store_history=True) ## PLOTS ######### savefigs = True # False if you don't want to save plots as pdfs plt.style.use('ggplot') # arbitrary time t0 = 9 # check Gaussian approximation is accurate plt.figure() mu, Q = chosen_ssm.approx_likelihood(data[t0]) lG = lambda x: models['boot'].logG(t0, None, x) lGmax = lG(mu[np.newaxis, :]) for i in range(6):
def fkmod(**kwargs): return ssm.Bootstrap(ssm=ssm.StochVol(**kwargs), data=data) sigma = 0.18 ng = 100 mu_grid = np.linspace(-2.5, 0., ng) rho_grid = np.linspace(-.999, .999, ng) mus, rhos = np.meshgrid(mu_grid, rho_grid) models = [ fkmod(mu=mu, rho=rho, sigma=sigma) for mu, rho in zip(mus.flat, rhos.flat) ] results = particles.multiSMC( fk=models, N=10**4, qmc=True, nprocs=0, # multiprocessing, yeah! out_func=lambda pf: pf.logLt) ll = np.array([r['out'] for r in results]) ll.shape = (ng, ng) # PLOT # ==== savefigs = False # change to True to save figs as pdf plt.figure() levels = ll.max() + np.linspace(-20, 0, 21) ctour = plt.contourf(mus, rhos, ll, levels, cmap=cm.gray_r, alpha=.8) # The two lines below are some black magic that ensures that the contour # plot looks well when turned into a pdf (otherwise, the contour lines
}, 'smc_options': { 'qmc': False }, 'ar_to_increase_Nx': 0.1 } fks['smc2'] = ssp.SMC2(**fk_opts) fk_opts['smc_options']['qmc'] = True fks['smc2_qmc'] = ssp.SMC2(**fk_opts) fk_opts['ssm_cls'] = state_space_models.StochVol fks['smc2_sv'] = ssp.SMC2(**fk_opts) if __name__ == '__main__': runs = particles.multiSMC(fk=fks, N=N, moments=qtiles, verbose=True, nprocs=0, nruns=25) # plots ####### savefigs = True # False if you don't want to save plots as pdfs plt.style.use('ggplot') colors = {'smc2': 'gray', 'smc2_qmc': 'black'} lsts = {'smc2': '--', 'smc2_qmc': '-'} prefix = 'smc2_sv_lvg_N%i' % N T = data.shape[0] # Figure 18.2: variance marginal likelihood vs time plt.figure()
raw_data = np.loadtxt('../../datasets/GBP_vs_USD_9798.txt', skiprows=2, usecols=(3, ), comments='(C)') T = 201 data = 100. * np.diff(np.log(raw_data[:(T + 1)])) my_ssm = ssm.StochVol(mu=2 * np.log(.5992), sigma=0.178, rho=0.9702) # FK models models = OrderedDict() models['bootstrap'] = ssm.Bootstrap(ssm=my_ssm, data=data) models['guided'] = ssm.GuidedPF(ssm=my_ssm, data=data) models['apf'] = ssm.AuxiliaryPF(ssm=my_ssm, data=data) # Get results results = particles.multiSMC(fk=models, N=10**3, nruns=250, moments=True) # Golden standard bigN = 10**5 bigpf = particles.SMC(fk=models['bootstrap'], N=bigN, qmc=True, moments=True) print('One SQMC run with N=%i' % bigN) bigpf.run() # PLOTS # ===== plt.style.use('ggplot') savefig = False # True if you want to save figs as pdfs # box-plots for log-likelihood evaluation plt.figure() sb.boxplot(x=[r['fk'] for r in results],
################################### ng = 50 rhos = np.linspace(0., 1., ng) sig2s = np.linspace(1e-2, 25., ng) # for sigma=0., returns Nan ijs = list(itertools.product(range(ng), range(ng))) fks = { ij: ssms.Bootstrap(ssm=NeuroXp(rho=rhos[ij[0]], sig2=sig2s[ij[1]]), data=data) for ij in ijs } outf = lambda pf: pf.logLt nruns = 5 print('computing log-likelihood on a grid') results = particles.multiSMC(fk=fks, N=100, qmc=True, nruns=nruns, nprocs=0, out_func=outf) save_results({'results': results}) # EM #### def EM_step(rho, sig2, N=100): paths, loglik = smoothing_trajectories(rho, sig2, N=N) num = np.mean(sum(x * xp for x, xp in zip(paths[1:], paths[:-1]))) den = np.mean(sum(x**2 for x in paths[:-1])) new_rho = num / den ssq = sum((x - new_rho * xp)**2 for x, xp in zip(paths[1:], paths[:-1])) ssq += paths[0]**2 new_sig2 = np.mean(ssq) / T
ssm = kalman.LinearGauss(sigmaX=sigmaX, sigmaY=sigmaY, rho=rho) true_states, data = ssm.simulate(T) # computes true log-likelihood kf = kalman.Kalman(ssm=ssm, data=data) kf.filter() true_loglik = np.sum(kf.logpyt) # FK model fk_model = state_space_models.GuidedPF(ssm=ssm, data=data) # Run SMC algorithm for different values of ESS_min alphas = list(np.linspace(0., .1, 11)) + list(np.linspace(0.15, 1., 18)) results = particles.multiSMC(fk=fk_model, N=N, ESSrmin=alphas, nruns=200, nprocs=1) # PLOTS #====== plt.style.use('ggplot') savefigs = True # False if you don't want to save plots as pdfs # inter-quartile range of log-likelihood estimate as a function of ESSmin plt.figure() quartiles = np.zeros((2, len(alphas))) for i, q in enumerate([25, 75]): for j, alpha in enumerate(alphas): ll = [r['output'].logLt for r in results if r['ESSrmin'] == alpha] quartiles[i, j] = np.percentile(np.array(ll), q)
from particles import state_space_models as ssms from particles.collectors import Moments # Data and parameter values from Pitt & Shephard T = 201 data = dts.GBP_vs_USD_9798().data[:T] my_ssm = ssms.StochVol(mu=2 * np.log(.5992), sigma=0.178, rho=0.9702) # FK models models = OrderedDict() models['bootstrap'] = ssms.Bootstrap(ssm=my_ssm, data=data) models['guided'] = ssms.GuidedPF(ssm=my_ssm, data=data) models['apf'] = ssms.AuxiliaryPF(ssm=my_ssm, data=data) # Get results results = particles.multiSMC(fk=models, N=10**3, nruns=250, collect=[Moments]) # Golden standard bigN = 10**5 bigpf = particles.SMC(fk=models['bootstrap'], N=bigN, qmc=True, collect=[Moments]) print('One SQMC run with N=%i' % bigN) bigpf.run() # PLOTS # ===== plt.style.use('ggplot') savefigs = True # False if you don't want to save plots as pdfs # box-plots for log-likelihood evaluation plt.figure()