Example #1
0
def subject_likelihood(likelihood_arglist):
    """
    First handle the different cases of what we need to fit and save parameters. They just set
    the appropriate values of fine_sigma, reward, and punishment depending on the model type
    and print what is being evaluated by the optimization algorithm."""
    log_parameters, model_params = likelihood_arglist

    curr_params = deepcopy(model_params)
    # fine_sigma and punishment are fit, reward fixed at 1
    sigma = np.array((np.exp(log_parameters[0]), np.exp(log_parameters[1])))
    reward = np.exp(log_parameters[2])
    punishment = np.exp(log_parameters[3])
    alpha = np.exp(log_parameters[4])
    print('sigmas = {:.2f}, {:.2f}'.format(*sigma),
          '; reward = {:.2f}'.format(reward),
          '; punishment = {:.2f}'.format(punishment),
          '; alpha = {:.2f}'.format(alpha))

    curr_params['sigma'] = sigma
    curr_params['reward'] = reward
    curr_params['punishment'] = -punishment
    curr_params['alpha'] = alpha

    bellutil = BellmanUtil(**curr_params)
    curr_params['rho'] = bellutil.rho
    curr_params['decisions'] = bellutil.decisions

    obs = ObserverSim(**curr_params)
    curr_params['fractions'] = obs.fractions

    likelihood_data = DataLikelihoods(**curr_params)
    likelihood_data.increment_likelihood(**curr_params)
    print(likelihood_data.likelihood)
    return likelihood_data.likelihood
Example #2
0
def comparisons(arglist):
    fine_sigma, i = arglist[0]
    reward, j = arglist[1]
    print(i, j)
    model_params['fine_sigma'] = fine_sigma
    model_params['reward'] = reward
    finegr = FineGrained(**model_params)
    coarse_stats = finegr.coarse_stats
    model_params['mu'] = coarse_stats[1, :, 0]
    model_params['sigma'] = coarse_stats[1, :, 1]
    model_params['N'] = model_params['N_values'][1]
    bellutil = BellmanUtil(**model_params)
    model_params['decisions'] = bellutil.decisions

    sim_params = deepcopy(model_params)
    sim_params['simulate'] = True
    fp_params = deepcopy(model_params)

    fpobs = ObserverSim(**fp_params)
    simobs = ObserverSim(**sim_params)

    sim_likelihood = DataLikelihoods(subject_num)
    fp_likelihood = DataLikelihoods(subject_num)

    fp_likelihood.increment_likelihood(fpobs.fractions, **fp_params)
    sim_likelihood.increment_likelihood_legacy(simobs.dist_matrix,
                                               simobs.rts_matrix, **sim_params)

    fp_value = fp_likelihood.likelihood
    sim_value = sim_likelihood.likelihood
    return (fp_value, sim_value, i, j)
Example #3
0
def likelihood_inner_loop(curr_params):
    bellutil = BellmanUtil(**curr_params)
    curr_params['decisions'] = bellutil.decisions

    obs = ObserverSim(**curr_params)
    curr_params['fractions'] = obs.fractions
    return curr_params
def run_model(model_params):
    finegr = FineGrained(**model_params)
    model_params['coarse_stats'] = finegr.coarse_stats

    N_values = model_params['N_values']
    dist_computed_params = []
    for i, N in enumerate(N_values):
        curr_params = deepcopy(model_params)
        curr_params['N'] = N
        curr_params['mu'] = model_params['coarse_stats'][i, :, 0]
        curr_params['sigma'] = model_params['coarse_stats'][i, :, 1]
        bellutil = BellmanUtil(**curr_params)
        curr_params['decisions'] = bellutil.decisions
        obs = ObserverSim(**curr_params)
        curr_params['fractions'] = obs.fractions
        dist_computed_params.append(curr_params)

    return dist_computed_params
Example #5
0
    def __init__(self, log_params, model_type, T, t_w, dt, size, lapse):
        '''
        log_params is either a float (fine sigma) or a 2x1 array with fine sigma and other param
        model type is formated as tuple with first argument denoting parameters to fits;
            options are:
                sig; fits just a fine grained sigma
                sig_reward; fits fine grained sigma and reward per subject, punishment set to 0
                sig_punish; fit fine grain sigma and punishment, reward set to 0
        the second argument denoting the reward scheme used in backwards induction
            options are:
                sym; symetric reward matrix in reward and punishment
                epsilon_punish; reward for correct fixed at 1 for both pres/abs correct response
                asym_reward; reward for correct absent fixed at 1
        and the third argument denoting the model used to bootstrap coarse_stats
            options are:
                const: constant mapping over all fine_sigma
                'sqrt': sqrt scaling of N weighting of fine_sigma
        sig_reward_sqrt; fits fine grained sigma and reward per subject with sqrt in d mapping

        inits is a tuple specifying (total time T, intertrival interval t_w, time step dt,
                                     size of grid, lapse rate)
        '''
        self.model_type = model_type
        self.T, self.t_w, self.dt, self.size, self.lapse = T, t_w, dt, size, lapse
        self.N_array = np.array([8, 12, 16])

        self.bell_func = BellmanUtil(self.T, self.t_w, self.size, self.dt)
        self.g_values = self.bell_func.g_values

        if model_type[0] == 'sig':
            self.fine_sigma = np.exp(log_params)
            self.reward = 1
            self.punishment = 0
        elif model_type[0] == 'sig_reward':
            self.fine_sigma = np.exp(log_params[0])
            self.reward = np.exp(log_params[1])
            self.punishment = 0
        elif model_type[0] == 'epsilon_punish':
            self.fine_sigma = np.exp(log_params[0])
            self.reward = 1
            self.punishment = np.exp(log_params[1])
        else:
            raise Exception("Invalid entry in first argument of model_type")

        print('finesig =', self.fine_sigma, 'reward =', self.reward,
              'punish =', self.punishment)
        self.stats = FineGrained(self.fine_sigma, model_type[2],
                                 int(1e5)).coarse_stats

        self.rho_vec = np.zeros(self.stats.shape[0])
        self.decision_vec = np.zeros(
            (self.size, int(self.T / self.dt), self.stats.shape[0]))
        self.trans_vec = np.zeros((self.size, self.size, self.stats.shape[0]))
        for i in range(self.stats.shape[0]):
            mu = self.stats[i, :, 0]
            sigma = self.stats[i, :, 1]
            prob_grid = self.bell_func.trans_probs(sigma, mu)
            self.trans_vec[:, :, i] = prob_grid
            rho = self.bell_func.solve_rho(self.reward, self.punishment,
                                           model_type[1], sigma, mu, prob_grid)
            self.rho_vec[i] = rho
            self.decision_vec[:, :, i] = self.bell_func.back_induct(
                self.reward, self.punishment, rho, sigma, mu, prob_grid,
                model_type[1])[1]
Example #6
0
class OptDDM:
    def __init__(self, log_params, model_type, T, t_w, dt, size, lapse):
        '''
        log_params is either a float (fine sigma) or a 2x1 array with fine sigma and other param
        model type is formated as tuple with first argument denoting parameters to fits;
            options are:
                sig; fits just a fine grained sigma
                sig_reward; fits fine grained sigma and reward per subject, punishment set to 0
                sig_punish; fit fine grain sigma and punishment, reward set to 0
        the second argument denoting the reward scheme used in backwards induction
            options are:
                sym; symetric reward matrix in reward and punishment
                epsilon_punish; reward for correct fixed at 1 for both pres/abs correct response
                asym_reward; reward for correct absent fixed at 1
        and the third argument denoting the model used to bootstrap coarse_stats
            options are:
                const: constant mapping over all fine_sigma
                'sqrt': sqrt scaling of N weighting of fine_sigma
        sig_reward_sqrt; fits fine grained sigma and reward per subject with sqrt in d mapping

        inits is a tuple specifying (total time T, intertrival interval t_w, time step dt,
                                     size of grid, lapse rate)
        '''
        self.model_type = model_type
        self.T, self.t_w, self.dt, self.size, self.lapse = T, t_w, dt, size, lapse
        self.N_array = np.array([8, 12, 16])

        self.bell_func = BellmanUtil(self.T, self.t_w, self.size, self.dt)
        self.g_values = self.bell_func.g_values

        if model_type[0] == 'sig':
            self.fine_sigma = np.exp(log_params)
            self.reward = 1
            self.punishment = 0
        elif model_type[0] == 'sig_reward':
            self.fine_sigma = np.exp(log_params[0])
            self.reward = np.exp(log_params[1])
            self.punishment = 0
        elif model_type[0] == 'epsilon_punish':
            self.fine_sigma = np.exp(log_params[0])
            self.reward = 1
            self.punishment = np.exp(log_params[1])
        else:
            raise Exception("Invalid entry in first argument of model_type")

        print('finesig =', self.fine_sigma, 'reward =', self.reward,
              'punish =', self.punishment)
        self.stats = FineGrained(self.fine_sigma, model_type[2],
                                 int(1e5)).coarse_stats

        self.rho_vec = np.zeros(self.stats.shape[0])
        self.decision_vec = np.zeros(
            (self.size, int(self.T / self.dt), self.stats.shape[0]))
        self.trans_vec = np.zeros((self.size, self.size, self.stats.shape[0]))
        for i in range(self.stats.shape[0]):
            mu = self.stats[i, :, 0]
            sigma = self.stats[i, :, 1]
            prob_grid = self.bell_func.trans_probs(sigma, mu)
            self.trans_vec[:, :, i] = prob_grid
            rho = self.bell_func.solve_rho(self.reward, self.punishment,
                                           model_type[1], sigma, mu, prob_grid)
            self.rho_vec[i] = rho
            self.decision_vec[:, :, i] = self.bell_func.back_induct(
                self.reward, self.punishment, rho, sigma, mu, prob_grid,
                model_type[1])[1]

    # def show_bounds(self):
    #     for i in range(self.stats.shape[0]):
    #         decision = self.decision_vec[:, :, i]
    #         plt.figure()
    #         plt.title('N = {}'.format(self.N_array[i]))
    #         plt.imshow(decision)
    #
    # def show_trans_probs(self):
    #     for i in range(self.stats.shape[0]):
    #         probs = self.trans_vec[:, :, i]
    #         plt.figure()
    #         plt.title(str(self.N_array[i]))
    #         plt.imshow(probs)

    def simulate_observer(self, N, C):
        N_index = list(self.N_array).index(N)
        dt = self.dt
        T = self.T
        g_values = self.g_values
        if C != 1 and C != 0:
            raise ValueError('condition C must be 0 (abs) or 1 (pres)')
        decisions = self.decision_vec[:, :, N_index]
        mu = self.stats[N_index, :, 0]
        sigma = self.stats[N_index, :, 1]

        dec_vec = decisions[:, 0]
        abs_bound = g_values[np.amax(np.where(dec_vec == 1)[0])]
        pres_bound = g_values[np.where(dec_vec == 2)[0][0]]

        D_t = 0
        t = 0

        g_trajectory = np.ones(int(T / dt)) * 0.5
        D_trajectory = np.zeros(int(T / dt))

        while t < T:
            D_t = D_t + norm.rvs(mu[C] * dt, sigma[C] * dt)

            g_t = self.bell_func.D_to_g(D_t)
            D_trajectory[int(t / dt)] = D_t
            g_trajectory[int(t / dt)] = g_t
            t += dt

            if g_t < abs_bound:
                return (0, t, g_trajectory, D_trajectory)

            if g_t > pres_bound:
                return (1, t, g_trajectory, D_trajectory)

        return (np.NaN, T, g_trajectory, D_trajectory)

    def get_rt(self, N, condition, numsims=5000):
        C = condition
        if C != 1 and C != 0:
            raise Exception('condition must be 0 (abs) or 1 (pres)')

        observer_outputs = []
        for i in range(numsims):
            observer_outputs.append(self.simulate_observer(N, C))
        response_info = np.array([(x[0], x[1]) for x in observer_outputs])
        return response_info

    def get_kde_dist(self, abs_rts, pres_rts, plot=False, ax=None):
        # 2x2 matrix of distributions, i (row) is the underlying condition C
        # and j (column) is the response
        dist = []
        sorted_rts = []
        perturb = norm.rvs(0, 0.01)
        sim_rt = [abs_rts, pres_rts]
        for i in range(2):
            cur_rt = sim_rt[i]
            for j in range(2):
                if not np.any(cur_rt[:, 0] == j):
                    # case where there are none of the responses given in the model simulation
                    dist.append(uniform)
                    sorted_rts.append([])
                else:
                    i_j_sim_rt_marked = np.array(
                        cur_rt[np.where(cur_rt[:, 0] == j)[0]])
                    i_j_sim_rt = i_j_sim_rt_marked[:, 1]
                    # if they are all the same or of size 1, perturb to allow kde
                    if np.var(i_j_sim_rt) == 0 or i_j_sim_rt.size == 1:
                        # if they are all the same, perturb to allow kde
                        i_j_sim_rt = np.append(i_j_sim_rt,
                                               i_j_sim_rt[0] + perturb)
                    # if plot and i == j:
                    #     if i == 0:
                    #         sns.kdeplot(i_j_sim_rt, bw=0.1, shade=True, color='purple',
                    #                     label='Sim: con. = {0}, resp. = {1}'.format(i, j), ax=ax)
                    #     else:
                    #         sns.kdeplot(i_j_sim_rt, bw=0.1, shade=True, color='yellow',
                    #                     label='Sim: con. = {0}, resp. = {1}'.format(i, j), ax=ax)
                    sorted_rts.append([i_j_sim_rt])
                    dist.append(gaussian_kde(i_j_sim_rt, bw_method=0.1))

        return np.reshape(dist, (2, 2)), np.reshape(sorted_rts, (2, 2))

    def get_single_N_likelihood(self, data, dist_matrix, sorted_rt, reward):
        temp = np.mean(np.array(data['rt']))

        abs_0_sim_rt_dist = dist_matrix[0, 0]
        num_abs_0 = len(sorted_rt[0, 0])

        pres_1_sim_rt_dist = dist_matrix[1, 1]
        num_pres_1 = len(sorted_rt[1, 1])

        abs_1_sim_rt_dist = dist_matrix[0, 1]
        num_abs_1 = len(sorted_rt[0, 1])

        pres_0_sim_rt_dist = dist_matrix[1, 0]
        num_pres_0 = len(sorted_rt[1, 0])

        total_pres = num_pres_0 + num_pres_1
        total_abs = num_abs_0 + num_abs_1

        pres_rts_0 = data.query('resp == 2 & target == \'Present\'').rt.values
        pres_rts_1 = data.query('resp == 1 & target == \'Present\'').rt.values

        abs_rts_0 = data.query('resp == 2 & target == \'Absent\'').rt.values
        abs_rts_1 = data.query('resp == 1 & target == \'Absent\'').rt.values

        # frac_pres_inc = len(pres_rts_0) / (len(pres_rts_0) + len(pres_rts_1))
        # frac_pres_corr = len(pres_rts_1) / (len(pres_rts_0) + len(pres_rts_1))
        log_like_pres = np.concatenate(
            (np.log(num_pres_0 / total_pres) +
             np.log(pres_0_sim_rt_dist.pdf(pres_rts_0)),
             np.log(num_pres_1 / total_pres) +
             np.log(pres_1_sim_rt_dist.pdf(pres_rts_1))))

        # frac_abs_inc = len(abs_rts_1) / (len(abs_rts_0) + len(abs_rts_1))
        # frac_abs_corr = len(abs_rts_0) / (len(abs_rts_0) + len(abs_rts_1))
        log_like_abs = np.concatenate(
            (np.log(num_abs_0 / total_abs) +
             np.log(abs_0_sim_rt_dist.pdf(abs_rts_0)),
             np.log(num_abs_1 / total_abs) +
             np.log(abs_1_sim_rt_dist.pdf(abs_rts_1))))

        log_like_all = np.concatenate((log_like_pres, log_like_abs))

        likelihood_pertrial = (1 - self.lapse) * np.exp(log_like_all) + \
            (self.lapse / 2) * np.exp(-reward / temp)
        return -np.sum(np.log(likelihood_pertrial))

    def get_data_likelihood(self, sub_data):
        likelihood = 0
        data = [
            sub_data.query('setsize == 8'),
            sub_data.query('setsize == 12'),
            sub_data.query('setsize == 16')
        ]

        for i in range(self.stats.shape[0]):
            N = self.N_array[i]
            abs_rt = self.get_rt(N, 0)
            pres_rt = self.get_rt(N, 1)
            dist_matrix = self.get_kde_dist(abs_rt, pres_rt)[0]
            sorted_rt = self.get_kde_dist(abs_rt, pres_rt)[1]
            likelihood += self.get_single_N_likelihood(data[i], dist_matrix,
                                                       sorted_rt, self.reward)

        return likelihood
        'alpha': 1.,
        'fine_model': 'const',
        'reward_scheme': 'asym_reward',
    }

    finegr = FineGrained(**model_params)
    model_params['coarse_stats'] = finegr.coarse_stats

    N_values = model_params['N_values']
    dist_computed_params = []
    for i, N in enumerate(N_values):
        curr_params = deepcopy(model_params)
        curr_params['N'] = N
        curr_params['mu'] = model_params['coarse_stats'][i, :, 0]
        curr_params['sigma'] = model_params['coarse_stats'][i, :, 1]
        bellutil = BellmanUtil(**curr_params)
        curr_params['decisions'] = bellutil.decisions
        obs = ObserverSim(**curr_params)
        curr_params['fractions'] = obs.fractions
        dist_computed_params.append(curr_params)

    data_eval = DataLikelihoods(**model_params)
    for single_N_params in dist_computed_params:
        data_eval.increment_likelihood(**single_N_params)

    print(data_eval.likelihood)

    T = model_params['T']
    dt = model_params['dt']
    fig, axes = plt.subplots(3, 1)
    t_values = np.arange(0, T, dt) + (dt / 2)
Example #8
0
    def __init__(self, model_params, tot_samples=70):
        curr_params = deepcopy(model_params)
        bellutil = BellmanUtil(**curr_params)
        curr_params['rho'] = bellutil.rho
        curr_params['decisions'] = bellutil.decisions
        decisions = bellutil.decisions

        for i, column in enumerate(decisions.T):
            try:
                upperbound = (column == 2).nonzero()[0][0]
                lowerbound = (column == 1).nonzero()[0][-1]
            except IndexError:
                raise (ValueError, 'Non-existant bounds at some timestep')
            column[upperbound:] = 2
            column[:lowerbound] = 1
            decisions[:, i] = column

        condN = tot_samples // 2
        dt = model_params['dt']
        T = model_params['T']
        t_d = model_params['t_delay']
        t_max = model_params['t_max'] - t_d
        maxind = int(t_max / dt) - 1
        t_values = np.arange(0, T, dt)
        g_values = model_params['g_values']

        ev_values = np.zeros((2, tot_samples // 2, t_values.shape[0]))
        ev_values[0, :, :] = np.random.normal(loc=0,
                                              scale=model_params['sigma'][0],
                                              size=ev_values.shape[1:])
        ev_values[1, :, :] = np.random.normal(loc=1,
                                              scale=model_params['sigma'][1],
                                              size=ev_values.shape[1:])

        g_traces = np.zeros_like(ev_values)
        for C in (0, 1):
            for sample in range(condN):
                for samplen in range(t_values.shape[0]):
                    g_traces[C, sample, samplen] = self.g_t(
                        ev_values[C, sample, :samplen + 1], model_params['mu'],
                        model_params['sigma'])
        binned_traces = np.digitize(g_traces, g_values, right=True)
        binned_traces[binned_traces ==
                      g_values.shape[0]] = g_values.shape[0] - 1

        response_times = np.zeros(ev_values.shape[:-1])
        response_idents = np.zeros(ev_values.shape[:-1])
        for C in (0, 1):
            for sample in range(condN):
                i = 0
                while i <= maxind:
                    currdec = decisions[binned_traces[C, sample, i], i]
                    if currdec == 1:
                        response_times[C, sample] = t_values[i] + t_d
                        response_idents[C, sample] = 0
                        break
                    elif currdec == 2:
                        response_times[C, sample] = t_values[i] + t_d
                        response_idents[C, sample] = 1
                        break
                    elif (currdec == 0) and (i == maxind):
                        response_times[C, sample] = t_max + t_d
                        response_idents[C, sample] = 2
                    i += 1

        self.response_times = response_times
        self.response_idents = response_idents
        self.model_params = curr_params
Example #9
0
    def __init__(self,
                 subject_num,
                 T,
                 dt,
                 t_w,
                 t_max,
                 size,
                 lapse,
                 mu,
                 N_values,
                 g_values,
                 experiment,
                 N,
                 reward_scheme,
                 tested_params,
                 likelihoods_returned,
                 t_delay,
                 opt_regime=None,
                 **kwargs):
        model_params = {
            'T': 10,
            'dt': 0.05,
            't_w': 0.5,
            't_delay': 0.2,
            't_max': 5.,
            'size': size,
            'lapse': 1e-6,
            'mu': np.array((0, 1)),
            'N': int(N),
            'N_values': (8, 12, 16),
            'g_values': np.linspace(1e-4, 1 - 1e-4, size),
            'subject_num': int(subject_num),
            'reward_scheme': 'asym_reward',
            'experiment': experiment
        }

        curr_params = deepcopy(model_params)
        self.opt_params = tested_params[np.argmin(likelihoods_returned)]
        opt_likelihood = np.amin(likelihoods_returned)
        curr_params['sigma'] = np.exp(self.opt_params[:2])
        curr_params['reward'] = np.exp(self.opt_params[2])
        curr_params['punishment'] = -np.exp(self.opt_params[3])
        curr_params['alpha'] = np.exp(self.opt_params[4])

        # If we don't have the decisions, rho, and reaction times for opt params, compute them
        if not opt_regime:
            bellutil = BellmanUtil(**curr_params)
            rho = bellutil.rho
            decisions = bellutil.decisions

            obs = ObserverSim(decisions=decisions, **curr_params)
            fractions = obs.fractions
            opt_regime = {
                'rho': rho,
                'decisions': decisions,
                'fractions': fractions
            }

        curr_params['opt_regime'] = opt_regime
        curr_params['rho'] = opt_regime['rho']
        curr_params['decisions'] = opt_regime['decisions']
        curr_params['fractions'] = opt_regime['fractions']
        likelihood_data = DataLikelihoods(**curr_params)
        likelihood_data.increment_likelihood(**curr_params)
        if not np.abs(likelihood_data.likelihood - opt_likelihood) < 1e-3:
            warnings.warn(
                'Diff between computed likelihood and opt is greater than 0.0001'
            )
            print(likelihood_data.likelihood - opt_likelihood)

        self.model_params = curr_params
        self.opt_regim = opt_regime
        self.N_data = likelihood_data.sub_data.query('setsize == {}'.format(N))