Pulkit Goyal and Joel Vasama
Some Suggestions
from functools import lru_cache
from tqdm import tqdm
❌ Accuracy Maximisation
❌ Probility Matching ❌ Sample Based Rule
+ Epsilon-Greedy Error Model
@epsilon_greedy
def softmax(s1, s2, *std): # Softmax Rule
return 1/(1 + np.e**(s1 - s2))
epsilon_greedy = lambda choice_function: lambda e: lambda *args, **kwargs: choice_function(*args, **kwargs) * (1 - e) + 0.5 * e
# Bayesian Information Criterion
# > BIC = p.ln(t.k) - 2.LL
bic = lambda P, N, LL: P*np.log(N) - 2*LL
@lru_cache
def fit_model(participant_id,
Model,
model_params,
choice_function=softmax(0),
conditions=()):
...
def optimise(Model,
model_search_space=(),
search_algorithm=lambda *args, **kwargs: optimize.brute(*args, **kwargs, full_output=True, finish=None),
error_search_space=(0, 1, 0.1),
choice_function=softmax,
xic=bic,
conditions={}):
...
# Gradient Descent
bics_rw_slow_2, optimal_model_params_rw_slow_2, optimal_error_rw_slow_2 = optimise(
RescorlaWagner,
model_search_space=((0, 1.1, 0.1),),
error_search_space=(0, 1, 0.1),
conditions={'slow': 1, 'num_features': 2}
search_algorithm=lambda *args, **kwargs: optimize.brute(*args, **kwargs, full_output=True, finish=None),
)
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 19/19 [04:05<00:00, 12.94s/it]
# Grid Search
bics_rw_slow_2_nm, optimal_model_params_rw_slow_2_nm, optimal_error_rw_slow_2_nm = optimise(
RescorlaWagner,
model_search_space=(0.5,),
error_search_space=0.1,
conditions={'slow': 1, 'num_features': 2},
search_algorithm=lambda *args, **kwargs: [optimize.minimize(*args, **kwargs, bounds=((0, 1), (0, 1)), method='Nelder-Mead')[key] for key in ['x', 'fun']]
)
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 19/19 [04:32<00:00, 14.34s/it]
np.mean(abs(bics_rw_slow_2_nm - bics_rw_slow_2))
0.4230812774305918
fig, ax = plt.subplots(1, 2, figsize=(8, 4))
boxplots([par_correct], ['Accuracy'], ax[0])
boxplots([par_RT], ['Reaction Time'], ax[1])
fig.suptitle('Outlier Detection');
smf.ols(formula='correct ~ trial', ...).fit()
smf.ols(formula='correct ~ task', ...).fit()
smf.ols(formula='correct ~ num_features', ...).fit()
smf.ols(formula='correct ~ num_features * C(slow) * decision_time', ...).fit()
st.pearsonr(par_correct, par_RT);
Look at the resulting parameters and try to answer the following questions
bics_rw_slow, optimal_model_params_rw_slow, optimal_error_rw_slow = optimise(RescorlaWagner, ((0, 1, 0.1),), conditions={'slow': 1})
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 19/19 [10:08<00:00, 32.03s/it]
bics_rw_fast, optimal_model_params_rw_fast, optimal_error_rw_fast = optimise(RescorlaWagner, ((0, 1, 0.1),), conditions={'slow': 0})
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 19/19 [10:09<00:00, 32.07s/it]
Compare learning rate in slow vs fast tasks.
st.ttest_rel(optimal_model_params_rw_slow[:18, 0], optimal_model_params_rw_fast[:18, 0])
Compare $\epsilon$-error parameter in slow vs fast tasks.
st.ttest_rel(optimal_error_rw_slow[:18], optimal_error_rw_fast[:18])
st.ttest_rel(optimal_error_rw_slow_2[:18], optimal_error_rw_fast_2[:18])
bics_kf_slow, optimal_model_params_kf_slow, optimal_error_kf_slow = optimise(KalmanFilter, ((0.1, 1, 0.1), (0.1, 1, 0.1)), conditions={'slow': 1})
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 19/19 [1:23:57<00:00, 265.11s/it]
bics_kf_fast, optimal_model_params_kf_fast, optimal_error_kf_fast = optimise(KalmanFilter, ((0.1, 1, 0.1), (0.1, 1, 0.1)), conditions={'slow': 0})
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 19/19 [1:23:01<00:00, 262.18s/it]
Compare $\sigma_y$ in slow vs fast tasks.
st.ttest_rel(optimal_model_params_kf_slow[:18, 0], optimal_model_params_kf_fast[:18, 0])
Compare $\epsilon$-error parameter in slow vs fast tasks.
st.ttest_rel(optimal_error_kf_slow[:18], optimal_error_kf_fast[:18])
# bics_rm = np.array([bic(0, NUM_TRIALS*data['global_task'].nunique(), NUM_TRIALS*data['global_task'].nunique()*np.log(0.5))] * NUM_PARTICIPANTS)
bics_rm_slow = np.array([bic(0, NUM_TRIALS*data[data['slow'] == 1]['global_task'].nunique(), NUM_TRIALS*data[data['slow'] == 1]['global_task'].nunique()*np.log(0.5))] * NUM_PARTICIPANTS)
bics_rm_fast = np.array([bic(0, NUM_TRIALS*data[data['slow'] == 0]['global_task'].nunique(), NUM_TRIALS*data[data['slow'] == 0]['global_task'].nunique()*np.log(0.5))] * NUM_PARTICIPANTS)
Participant 18
¶Parameters | $\sigma_y$ | $\sigma_w$ |
---|---|---|
Actual | 0.1 | 1.0 |
Recovered | 0.1 | 0.9 |
smf.mixedlm(formula='learning_rate ~ num_features', groups='participant_id', ...).fit()
smf.mixedlm(formula='learning_rate ~ num_features', groups='participant_id', ...).fit()
fig, ax = plt.subplots(1,2, figsize=(16, 4), sharey=True)
fig.suptitle(r'Optimal Error Weight in $\epsilon$-Greedy Error Model Across Participants (Slow Tasks)')
ax[0].bar(PARTICIPANTS - 0.23, optimal_error_rw_slow_2, 0.23, label='2', alpha=0.8)
ax[0].bar(PARTICIPANTS, optimal_error_rw_slow_3, 0.23, label='3', alpha=0.8)
ax[0].bar(PARTICIPANTS + 0.23, optimal_error_rw_slow_4, 0.23, label='4', alpha=0.8)
ax[0].set_xticks(PARTICIPANTS)
ax[0].legend()
ax[0].set_xlabel('Participant ID')
ax[0].set_ylabel('Optimal Error Weight')
boxplots([optimal_error_rw_slow_2, optimal_error_rw_slow_3, optimal_error_rw_slow_4], ('2', '3', '4'), ax[1])
ax[1].set_xlabel('Number of Features')
plt.tight_layout()
smf.mixedlm(formula='epsilon_error ~ num_features', groups='participant_id', ...).fit()
group1 | group2 | meandiff | p-adj | lower | upper | reject |
---|---|---|---|---|---|---|
2 | 3 | 0.2889 | 0.0055 | 0.075 | 0.5028 | True |
2 | 4 | 0.2389 | 0.0252 | 0.025 | 0.4528 | True |
3 | 4 | -0.05 | 0.8396 | -0.2639 | 0.1639 | False |
smf.mixedlm(formula='epsilon_error ~ num_features', groups='participant_id', ...).fit()
Binz, M., Gershman, S.J., Schulz, E. and Endres, D., 2022. Heuristics from bounded meta-learned inference. Psychological review.
Schulz, E., Speekenbrink, M. and Krause, A., 2018. A tutorial on Gaussian process regression: Modelling, exploring, and exploiting functions. Journal of Mathematical Psychology, 85, pp.1-16.
Wu, C.M., Schulz, E., Gerbaulet, K., Pleskac, T.J. & Speekenbrink, M. (2019). Under pressure: The influence of time limits on human exploration. Proceedings of the 41st Annual Conference of the Cognitive Science Society.
Thank You!