def mmi_model_Mood_LTA_gamma_wo_RT_p0_beta(subj_input_dir,subj_out_dir,sid): # import some useful libraries import numpy as np # numerical analysis linear algebra import pandas as pd # efficient tables #import matplotlib.pyplot as plt # plotting from scipy import stats from RunDEMC.density import kdensity from RunDEMC import Model, Param, dists, calc_bpic, joint_plot from mmi_mood_LTA_gamma_wo_RT_p0_beta import MMIModel, load_mmi_data from joblib import Parallel, delayed import pickle from pathlib import Path try: import scoop from scoop import futures except ImportError: print("Error loading scoop, reverting to joblib.") scoop = None # ## Load and examine data subj_input_dir=Path(subj_input_dir) subj_out_dir=Path(subj_out_dir) pattern=f'*{sid}*.xlsx' input_file=list(subj_input_dir.glob(pattern)) print(input_file[0]) dat = load_mmi_data(input_file[0]) # In[4]: #dat.at[2, 'Choice']=='Gamble' # In[5]: # find the minimum RT for the param range min_RT = dat.loc[dat.RT>0, 'RT'].min() print('Min RT:', min_RT) # ## Use RunDEMC to fit the model to a participant's data # define model evaluation functions for RunDEMC def eval_mod(params, param_names, bdat=None): # use global dat if none based in if bdat is None: bdat = dat # turn param list into dict mod_params = {x: params[n] for n, x in enumerate(param_names)} # try: # print(mod_params['lambda']) # except: # print("Problems") if mod_params['lambda']<0 or mod_params['lambda']>=1 : return np.log(0), np.log(0) if mod_params['gamma']<0 or mod_params['gamma']>=np.inf : return np.log(0), np.log(0) # if mod_params['beta']<0 or mod_params['beta']>1 : # return np.log(0), np.log(0) # if mod_params['p0']<0 or mod_params['p0']>1 : # return np.log(0), np.log(0) if mod_params['w_LTA']<0 or mod_params['w_LTA']>=np.inf : return np.log(0), np.log(0) if mod_params['w_RPE']<0 or mod_params['w_RPE']>=np.inf : return np.log(0), np.log(0) if mod_params['b']<=-np.inf or mod_params['b']>=np.inf : return np.log(0), np.log(0) if mod_params['s_v']<=0 or mod_params['s_v']>=np.inf : return np.log(0), np.log(0) if mod_params['c']<0 or mod_params['c']>=np.inf : return np.log(0), np.log(0) ## calculate the log_likes and mood_log_likes mod_res = MMIModel(params=mod_params, ignore_non_resp=True).proc_trials(bdat.copy()) ll = mod_res.log_like.sum() mood_ll = mod_res.mood_log_like.sum() return ll,mood_ll # this is the required def for RunDEMC def eval_fun(pop, *args): bdat = args[0] pnames = args[1] if scoop and scoop.IS_RUNNING: res_tups = list(futures.map(eval_mod, [indiv for indiv in pop], [pnames]*len(pop), [bdat]*len(pop))) else: res_tups= Parallel(n_jobs=-1)(delayed(eval_mod)(indiv,pnames, bdat) for indiv in pop) likes = np.array([rt[0] for rt in res_tups]) mood_likes = np.array([rt[1] for rt in res_tups]) return likes, mood_likes def get_best_fit(m, burnin=250, verbose=True): best_ind = m.weights[burnin:].argmax() if verbose: print("Weight:", m.weights[burnin:].ravel()[best_ind]) indiv = [m.particles[burnin:,:,i].ravel()[best_ind] for i in range(m.particles.shape[-1])] pp = {} for p,v in zip(m.param_names,indiv): pp[p] = v if verbose: print('"%s": %f,'%(p,v)) return pp # ### Base model # In[20]: # set up model params params = [Param(name='gamma', display_name=r'$\gamma$', prior=dists.gamma(1.5, 0.5), ), Param(name='c', display_name=r'$c$', prior=dists.gamma(1.5, 0.5), ), # Param(name='beta', # display_name=r'$\beta$', # prior=dists.normal(0, 1.4), # transform=dists.invlogit # ), # Param(name='w', # display_name=r'$w$', # prior=dists.normal(0, 1.4), # transform=dists.invlogit # ), # Param(name='a', # display_name=r'$a$', # prior=dists.gamma(2.0, 0.5), # ), # Param(name='t0', # display_name=r'$t_0$', # prior=dists.normal(0, 1.4), # transform=lambda x: dists.invlogit(x)*min_RT, # ), # Param(name='p0', # display_name=r'$p_0$', # prior=dists.normal(0, 1.4), # transform=dists.invlogit # ), Param(name='lambda', display_name=r'$lambda', prior=dists.normal(0, 1.4), transform=dists.invlogit ), # Param(name='lambda', # display_name=r'$lambda', # prior=dists.beta(0.5, 0.5) # ), Param(name='w_LTA', display_name=r'w_{LTA}', prior=dists.normal(0, 1), transform=np.exp, inv_transform=np.log), # Param(name='w_EG', # display_name=r'w_{EG}', # prior=dists.normal(0, 1), # transform=np.exp, # inv_transform=np.log), Param(name='w_RPE', display_name=r'w_{RPE}', prior=dists.normal(0, 1), transform=np.exp, inv_transform=np.log), Param(name='b', display_name=r'b', prior=dists.normal(0, 3)), Param(name='s_v', display_name=r's_v', prior=dists.exp(3)) ] # grab the param names pnames = [p.name for p in params] m = Model('mmi', params=params, like_fun=eval_fun, like_args=(dat, pnames), init_multiplier=3, # num_chains=gsize, verbose=True) # do some burnin times = m.sample(150, burnin=True) # now map the posterior times = m.sample(650, burnin=False) # show the chains are mixing and converging #plt.plot(m.weights[30:], alpha=.3); pickle_name=subj_out_dir / f'mWgt_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(m.weights, pickle_out) pickle_out.close() #print("Best fitting params:") #pp = get_best_fit(m, burnin=250, verbose=True) print("Best fitting params:") pp = get_best_fit(m, burnin=250, verbose=True) pickle_name=subj_out_dir / f'mBFprm_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(pp, pickle_out) pickle_out.close() # In[42]: #### BPIC calculations burnin=250 log_like_prior = m.weights - m.log_likes #print(log_like_prior) weight_mood = m.posts + log_like_prior #m.posts is log_like_Mood #print(weight_mood) print("Mood_BPIC :",calc_bpic(weight_mood[burnin:])['bpic']) Mood_BPIC=calc_bpic(weight_mood[burnin:])['bpic'] pickle_name=subj_out_dir / f'Mood_BPIC_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(Mood_BPIC, pickle_out) pickle_out.close() log_like_RT = m.log_likes - m.posts weight_RT = log_like_RT + log_like_prior print("RT_BPIC :",calc_bpic(weight_RT[burnin:])['bpic']) RT_BPIC=calc_bpic(weight_RT[burnin:])['bpic'] pickle_name=subj_out_dir / f'RT_BPIC_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(RT_BPIC, pickle_out) pickle_out.close() print(calc_bpic(m.weights[burnin:])['bpic']) mBPIC=calc_bpic(m.weights[burnin:])['bpic'] pickle_name=subj_out_dir / f'Total_BPIC_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(mBPIC, pickle_out) pickle_out.close() # In[46]: # plot the param distributions (note, we did not get full posteriors, yet) # plt.figure(figsize=(12,10)) # burnin=30 # for i in range(len(m.param_names)): # plt.subplot(3,4,i+1) # plt.hist(m.particles[burnin:, :, i].flatten(), bins='auto', alpha=.5, density=True); # plt.title(m.param_names[i]) # In[ ]: pickle_name=subj_out_dir / f'mParticles_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(m.particles, pickle_out) pickle_out.close() pickle_name=subj_out_dir / f'mParams_{sid}.pickle' print(pickle_name) pickle_out = open(pickle_name,"wb") pickle.dump(m.param_names, pickle_out) pickle_out.close()
weights = np.log(dists.normal(mean=0.0, std=pop[:, 3]).pdf(sse)) # see if return both weights and predicted vals if save_posts: return weights, pred else: return weights # set up the data xData = np.array([5.357, 9.861, 5.457, 5.936, 6.161, 6.731]) yData = np.array([0.376, 7.104, 0.489, 1.049, 1.327, 2.077]) # set up the parameters params = [ Param(name='a', prior=dists.uniform(-100, 100)), Param(name='b', prior=dists.uniform(-100, 100)), Param(name='c', prior=dists.uniform(-100, 100)), Param( name='delta', display_name=r'$\mathbf{\delta}$', prior=dists.exp(20), init_prior=dists.uniform(0, 10), ), ] # set up mod mod = Model(name='fun', params=params, like_fun=eval_fun, like_args=(xData, yData),
ddat = {} for c in ['+', '=', '~']: ind = (dat.condition == c) & (dat.rt < max_rt) d = { 'rt': np.log(np.array(dat[ind].rt) + log_shift), 'resp': np.array(~dat[ind]['correct'], dtype=np.int) } ddat[c] = d # store minimum RT min_rt = dat[(dat['rt'] >= 0.)]['rt'].min() # define priors params = [ Param(name='r', display_name=r'$r$', prior=dists.normal(-2.0, 1.0), transform=lambda x: dists.invlogit(x) * (20. - 0.) + (0.)), Param(name='p', display_name=r'$p$', prior=dists.normal(-0.8, 1.2), transform=lambda x: dists.invlogit(x) * (20. - 0.) + (0.)), Param(name='sd0', display_name=r'$\sigma_0$', prior=dists.normal(-1.0, 1.2), transform=lambda x: dists.invlogit(x) * (30. - 0.1) + (0.1)), Param(name='K', display_name=r'$K$', prior=dists.normal(0.0, 1.4), transform=dists.invlogit), Param(name='L', display_name=r'$L$',
left_coherence = data.at[i, 'left_coherence'] right_coherence = data.at[i, 'right_coherence'] if left_coherence > right_coherence: data.at[i, 'coherence'] = str(right_coherence) + ', ' + str( left_coherence) elif right_coherence >= left_coherence: data.at[i, 'coherence'] = str(left_coherence) + ', ' + str( right_coherence) # loop through each participant for s in data.subj.unique(): subj_ind = data['subj'] == s min_rt = data[subj_ind]['rt'].min() # set up the params params = [ Param(name='a', prior=dists.trunc_normal(5.0, 20.0, lower=0.0, upper=50.0)), Param(name='b', prior=dists.normal(0.0, 5.0)), Param(name='c', prior=dists.trunc_normal(5.0, 10.0, lower=0.0, upper=30.0)), Param(name='kappa', prior=dists.normal(0.0, 1.4), transform=dists.invlogit), Param(name='beta', prior=dists.normal(0.0, 1.4), transform=dists.invlogit), Param(name='alpha', prior=dists.trunc_normal(2.5, 10.0, lower=0.0, upper=30.0)), Param(name='t0', prior=dists.uniform(0., min_rt)) ] pnames = [p.name for p in params] # instantiate model object
nchains = 25 hyper_mu = HyperParam(name='mu', mu=0.0, sigma=10.0, alpha=4, beta=10, nchains=nchains) hyper_sd = HyperParam(name='sd', mu=np.log(1.0), sigma=1.0, alpha=4, beta=10, nchains=nchains) hparams = [hyper_mu, hyper_sd] params = [Param(name='mu', prior=hyper_mu,), # init_prior=dists.uniform(-20,20)), # init_prior=dists.uniform(0,20)), Param(name='sd', prior=hyper_sd,), ] # set up abc models = [DEMC(params, eval_fun, eval_args=(subj_num,), num_groups=1, group_size=nchains, proposal_gen=DE(gamma_best=None, rand_base=True), migration_prob=0.0, initial_zeros_ok=False, use_priors=True, save_posts=False, verbose=False) for subj_num in range(nsubj)] hier = Hierarchy(hparams, models)
def eval_fun(abc, pop, *args): res = Parallel(n_jobs=n_jobs)(delayed(eval_prop)(indiv, args[0]) for indiv in pop) weights = np.asarray(res) if abc._save_posts: return weights, None else: return weights # set up the parameters params = [ Param(name='mu', prior=dists.uniform(-20, 20)), Param(name='sd', prior=dists.uniform(0, 20)), ] burnin = 50 iterations = 500 # set up abc do_true = True abc_true = DEMC(params, eval_fun, eval_args=(do_true, ), num_groups=1, group_size=25, proposal_gen=DE(gamma_best=None, rand_base=True), migration_prob=0.0,
pdf will randomly pick from hyperparam chains and provide the pdf from the supplied distribution. log_prior: convenience method for looping over params for a proposal and calling each param's pdf to get the log_like for that param. """ from RunDEMC import Model, HyperPrior, Hierarchy, Param, dists # set up the hyper priors h_alpha = HyperPrior(name='h_alpha', dist=dists.normal, params=[ Param(name='mu', prior=dists.normal(1, .5)), Param(name='sigma', prior=dists.invgamma(4, 10)) ]) h_beta = HyperPrior(name='h_beta', dist=dists.normal, params=[ Param(name='mu', prior=dists.normal(1, .5)), Param(name='sigma', prior=dists.invgamma(4, 10)) ]) # set up lower level (i.e., subject) def subj_like(pop, *args): return np.log(dists.beta(pop[:, 0], pop[:, 1]).pdf(args[0]))
for d in dat[sub] ]) for s in dat.keys(): # Append a new model, note the use of the hyperpriors params = [ # sig_b is the sigmoid transition point #Param(name='sig_b', # prior=dists.uniform(0., 15.0), # change to number of tau stars # ), # new item strength Param( name='alpha', display_name=r'$\alpha$', prior=dists.uniform(0, 10.0), #init_prior=dists.trunc_normal(mean=.25,std=.5,lower=0,upper=5) ), Param( name='nu', display_name=r'$\nu$', prior=dists.uniform(0, 10.0), #init_prior=dists.trunc_normal(mean=.25,std=.5,lower=0,upper=5) ), # threshold Param( name='a', display_name=r'$a$', prior=dists.uniform(0, 10.0), #init_prior=dists.trunc_normal(mean=.25,std=.5,lower=0,upper=5) ),
] r_r = list(set(list(balloon_frame['range']))) ranges = [] for r in gg: if r == r_r[0]: ranges.append(0) elif r == r_r[1]: ranges.append(1) else: ranges.append(2) ranges = np.asarray(ranges, dtype=np.int16) # priors params = [ Param(name='alpha', display_name=r'$\alpha$', prior=dists.trunc_normal(mean=0.5, std=5.0, lower=0, upper=1.)), Param(name='beta', display_name=r'$\beta$', prior=dists.trunc_normal(mean=5., std=5., lower=-10., upper=10.)), Param(name='gamma', display_name=r'$\gamma$', prior=dists.trunc_normal(mean=1.0, std=5., lower=0., upper=2.)), Param(name='gamma_n',
# get the subject's RTs RTs = data_sub['resp_rt'] # select RTs greater than 350 ms RTs_x = RTs[RTs > .35] # get minimum RT (that is greater than 350 ms) -- this is needed for t0 prior min_RT = np.min(RTs_x) print('*** subject ', s) # get name of output file out_file = 'cab_' + s[:-4] + '.tgz' # define model parameters and priors params = [ Param(name='lambda', display_name=r'$\lambda$', prior=dists.trunc_normal(.5, 2, 0, 5)), # Param(name='alpha', display_name=r'$\alpha$', prior=dists.trunc_normal(1., 4, 0, 10)), Param(name='omega', display_name=r'$\omega$', prior=dists.normal(mean=0, std=1.4), transform=dists.invlogit), Param( name='delta', display_name=r'$\delta$', prior=dists.trunc_normal(1., 10, 0, 20.0), ), Param(name='sigma',
# all proposals log_like = -0.5 * np.sum(np.log(2 * np.pi * sigma[:, np.newaxis]**2) + (ydata - y_model)**2 / sigma[:, np.newaxis]**2, axis=1) return log_like # set up the parameters gsize = None # None will let model figure out a good number # Fixed slope across participants # Using a custom uniform prior beta = Param(name='beta', display_name=r'$\beta$', prior=dists.CustomDist( pdf=lambda x: np.exp(-1.5 * np.log(1 + x**2)), rvs=dists.laplace(0, 5).rvs)) # Fixed noise across subjects # Using a custom Jeffreys' prior sigma = Param(name='sigma', display_name=r'$\sigma$', prior=dists.CustomDist(pdf=lambda x: np.exp(-np.log(x)), rvs=dists.dists.invgamma(1, 1).rvs)) # Hyperprior over intercept using a normal distribution halpha = HyperPrior('alpha', dists.normal, params=[ Param(name='mu', prior=dists.uniform(-50, 50)), Param(name='sig', prior=dists.invgamma(1, 1))