Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Stroop Model to synthetic models #13

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
da5aecb
Add Stroop Model to synthetic models
TheLemonPig Aug 18, 2023
067cc58
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
1523dac
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
9d43cd9
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
90b7313
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
60d6d8c
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
c24fcee
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
bbd1574
Update pyproject.toml
TheLemonPig Aug 30, 2023
f72ac13
Merge branch 'main' into feat/add-stroop-model
TheLemonPig Aug 30, 2023
82f34f1
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
9d2fe71
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
161ea58
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
02de4b8
Update pyproject.toml
TheLemonPig Aug 30, 2023
2a5cc3d
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
9045fb2
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
d590c33
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
1185959
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
4f9016c
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
b1c6471
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
0e32513
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Aug 30, 2023
2a81873
Merge branch 'main' into feat/add-stroop-model
TheLemonPig Aug 31, 2023
7f3d3ed
Update tests/test_bundled_models.py
TheLemonPig Aug 31, 2023
df52f7a
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
musslick Sep 3, 2023
d5e0e71
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
musslick Sep 3, 2023
a3e4c40
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
musslick Sep 3, 2023
7754e56
Merge branch 'main' into feat/add-stroop-model
TheLemonPig Sep 5, 2023
37d9bda
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
1296cf9
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
8e5c293
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
86d78e3
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
004dc4b
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
0b5c29b
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
3be927e
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
5f8171d
Update src/autora/experiment_runner/synthetic/psychology/stroop_model.py
TheLemonPig Sep 5, 2023
bf52efb
Merge branch 'main' into feat/add-stroop-model
younesStrittmatter Jul 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 267 additions & 0 deletions src/autora/experiment_runner/synthetic/psychology/stroop_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
from functools import partial
from typing import Optional, Union

import numpy as np
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
import pandas as pd

from autora.experiment_runner.synthetic.utilities import SyntheticExperimentCollection
from autora.variable import DV, IV, ValueType, VariableCollection


def stroop_model(
name="Stroop Model",
resolution=10,
temperature=1.0,
random_state: Optional[int] = None,
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
musslick marked this conversation as resolved.
Show resolved Hide resolved
):
"""
Stroop Model

Args:
name: name of the experiment
resolution: number of allowed values for stimulus
temperature: choice temperature
random_state: integer used to seed the random number generator
musslick marked this conversation as resolved.
Show resolved Hide resolved
"""

params = dict(
name=name,
resolution=resolution,
temperature=temperature,
random_state=random_state,
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
)

color_green = IV(
name="color_green",
allowed_values=np.linspace(0, 1, resolution),
value_range=(0, 1),
units="intensity",
variable_label="Color Green",
type=ValueType.REAL,
)

color_red = IV(
name="color_red",
allowed_values=np.linspace(0, 1, resolution),
value_range=(0, 1),
units="intensity",
variable_label="Color Red",
type=ValueType.REAL,
)

word_green = IV(
name="word_green",
allowed_values=np.linspace(0, 1, resolution),
value_range=(0, 1),
units="intensity",
variable_label="Word GREEN",
type=ValueType.REAL,
)

word_red = IV(
name="word_red",
allowed_values=np.linspace(0, 1, resolution),
value_range=(0, 1),
units="intensity",
variable_label="Word RED",
type=ValueType.REAL,
)

task_color = IV(
name="task_color",
allowed_values=[0, 1],
value_range=(0, 1),
units="intensity",
variable_label="Color Naming Task",
type=ValueType.REAL,
)

task_word = IV(
name="task_word",
allowed_values=[0, 1],
value_range=(0, 1),
units="intensity",
variable_label="Word Reading Task",
type=ValueType.REAL,
)

response_green = DV(
name="performance",
value_range=(0, 1),
units="percentage",
variable_label="P(Green Response)",
type=ValueType.PROBABILITY,
)

variables = VariableCollection(
independent_variables=[
color_green,
color_red,
word_green,
word_red,
task_color,
task_word,
],
dependent_variables=[response_green],
)

rng = np.random.default_rng(random_state)
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved

class StroopModel:
def __init__(self, choice_temperature, std=0.):
self.choice_temperature = choice_temperature
self.std = std

# define affine transformations
self.input_color_hidden_color = self.init_linear(2, 2)
self.input_word_hidden_word = self.init_linear(2, 2)
self.hidden_color_output = self.init_linear(2, 2)
self.hidden_word_output = self.init_linear(2, 2)
self.task_hidden_color = self.init_linear(2, 2)
self.task_hidden_word = self.init_linear(2, 2)

self.bias = -4

self.init_weights()

def init_linear(self, in_features, out_features):
return rng.random.rand(out_features, in_features) * 0.01

def init_weights(self):
self.input_color_hidden_color = self.init_linear(2, 2)
self.hidden_color_output = self.init_linear(2, 2)
self.input_word_hidden_word = self.init_linear(2, 2)
self.hidden_word_output = self.init_linear(2, 2)
self.task_hidden_color = self.init_linear(2, 2)
self.task_hidden_word = self.init_linear(2, 2)

def sigmoid(self, x):
return 1 / (1 + np.exp(-x))


TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
def forward(self, input):
input = np.array(input)
if len(input.shape) <= 1:
input = input.reshape(1, len(input))

color = np.zeros((input.shape[0], 2))
word = np.zeros((input.shape[0], 2))
task = np.zeros((input.shape[0], 2))

color[:, 0:2] = input[:, 0:2]
word[:, 0:2] = input[:, 2:4]
task[:, 0:2] = input[:, 4:6]

color_hidden = self.sigmoid(
np.dot(self.input_color_hidden_color, color.T)
+ np.dot(self.task_hidden_color, task.T)
+ self.bias
).T

word_hidden = self.sigmoid(
np.dot(self.input_word_hidden_word, word.T)
+ np.dot(self.task_hidden_word, task.T)
+ self.bias
).T

output = np.dot(self.hidden_color_output, color_hidden.T) + np.dot(
self.hidden_word_output, word_hidden.T
)

if self.std > 0:
output += rng.random.randn(*output.shape) * self.std

output_softmaxed = np.exp(output * 1 / self.choice_temperature) / (
np.exp(output[0] * 1 / self.choice_temperature)
+ np.exp(output[1] * 1 / self.choice_temperature)
)

return output_softmaxed

def experiment_runner(
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
conditions: Union[pd.DataFrame, np.ndarray, np.recarray],
observation_noise: float = 0.01,
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
):
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
X = np.array(conditions)
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
Y = np.zeros((X.shape[0], 1))

# Stroop Model according to
# Cohen, J. D., Dunbar, K. M., McClelland, J. L., & Rohrer, D. (1990). On the control of automatic processes: a parallel distributed processing account of the Stroop effect. Psychological review, 97(3), 332.
model = StroopModel(temperature, std=observation_noise)
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved

for idx, x in enumerate(X):
# compute regular output
output_net = model(x).detach().numpy()
p_choose_A = output_net[0][0]

Y[idx] = p_choose_A

return Y

ground_truth = partial(experiment_runner, observation_noise=0.0)
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved

def domain():
s1_values = variables.independent_variables[0].allowed_values
s2_values = variables.independent_variables[1].allowed_values
X = np.array(np.meshgrid(s1_values, s2_values)).T.reshape(-1, 2)
# remove all combinations where s1 > s2
X = X[X[:, 0] <= X[:, 1]]
return X

def plotter(
model=None,
):
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt

colors = mcolors.TABLEAU_COLORS
col_keys = list(colors.keys())

S0_list = [1, 2, 4]
delta_S = np.linspace(0, 5, 100)

for idx, S0_value in enumerate(S0_list):
S0 = S0_value + np.zeros(delta_S.shape)
S1 = S0 + delta_S
X = np.array([S0, S1]).T
y = ground_truth(X)
plt.plot(
delta_S,
y,
label=f"$S_0 = {S0_value}$ (Original)",
c=colors[col_keys[idx]],
)
if model is not None:
y = model.predict(X)
plt.plot(
delta_S,
y,
label=f"$S_0 = {S0_value}$ (Recovered)",
c=colors[col_keys[idx]],
linestyle="--",
)

x_limit = [0, variables.independent_variables[0].value_range[1]]
y_limit = [0, 2]
x_label = r"Stimulus Intensity Difference $\Delta S = S_1 - S_0$"
y_label = "Perceived Intensity of Stimulus $S_1$"

plt.xlim(x_limit)
plt.ylim(y_limit)
plt.xlabel(x_label, fontsize="large")
plt.ylabel(y_label, fontsize="large")
plt.legend(loc=2, fontsize="medium")
plt.title("Stroop Model", fontsize="x-large")

collection = SyntheticExperimentCollection(
name=name,
description=stroop_model.__doc__,
variables=variables,
experiment_runner=experiment_runner,
musslick marked this conversation as resolved.
Show resolved Hide resolved
ground_truth=ground_truth,
domain=domain,
plotter=plotter,
params=params,
factory_function=stroop_model,
)
return collection
5 changes: 5 additions & 0 deletions tests/test_bundled_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
from autora.experiment_runner.synthetic.psychology.luce_choice_ratio import (
luce_choice_ratio,
)
from autora.experiment_runner.synthetic.psychology.stroop_model import (
stroop_model,
TheLemonPig marked this conversation as resolved.
Show resolved Hide resolved
)
from autora.experiment_runner.synthetic.neuroscience.task_switching import (
task_switching,
)
Expand All @@ -31,7 +34,9 @@
("luce_choice_ratio", luce_choice_ratio),
("template_experiment", template_experiment),
("weber_fechner_law", weber_fechner_law),
("stroop_model", stroop_model),
("stevens_power_law", stevens_power_law),

]

all_bundled_model_names = [b[0] for b in all_bundled_models]
Expand Down