-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: make synthetic runners use dataframes and rename inputs so stat… #10
Changes from 7 commits
98d93af
11dfb9d
bad8114
79a89db
9b6da21
d867fdf
019c2d9
ab056a7
bccb745
3cdf129
f095cb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
from functools import partial | ||
from typing import Optional, Union | ||
|
||
import numpy as np | ||
import pandas as pd | ||
|
||
from autora.experiment_runner.synthetic.economics.expected_value_theory import ( | ||
get_variables, | ||
|
@@ -10,7 +12,6 @@ | |
|
||
def prospect_theory( | ||
name="Prospect Theory", | ||
added_noise=0.01, | ||
choice_temperature=0.1, | ||
value_alpha=0.88, | ||
value_beta=0.88, | ||
|
@@ -20,7 +21,7 @@ def prospect_theory( | |
resolution=10, | ||
minimum_value=-1, | ||
maximum_value=1, | ||
rng=np.random.default_rng(), | ||
random_state: Optional[int] = None, | ||
): | ||
""" | ||
Parameters from | ||
|
@@ -44,7 +45,6 @@ def prospect_theory( | |
""" | ||
|
||
params = dict( | ||
added_noise=added_noise, | ||
choice_temperature=choice_temperature, | ||
value_alpha=value_alpha, | ||
value_beta=value_beta, | ||
|
@@ -54,15 +54,20 @@ def prospect_theory( | |
resolution=resolution, | ||
minimum_value=minimum_value, | ||
maximum_value=maximum_value, | ||
rng=rng, | ||
random_state=random_state, | ||
name=name, | ||
) | ||
|
||
variables = get_variables( | ||
minimum_value=minimum_value, maximum_value=maximum_value, resolution=resolution | ||
) | ||
rng = np.random.default_rng(random_state) | ||
|
||
def experiment_runner(X: np.ndarray, added_noise_=added_noise): | ||
def experiment_runner( | ||
conditions: Union[pd.DataFrame, np.ndarray, np.recarray], | ||
observation_noise=0.01, | ||
): | ||
X = np.array(conditions) | ||
Y = np.zeros((X.shape[0], 1)) | ||
for idx, x in enumerate(X): | ||
# power value function according to: | ||
|
@@ -113,8 +118,8 @@ def experiment_runner(X: np.ndarray, added_noise_=added_noise): | |
x[3] ** coefficient + (1 - x[3]) ** coefficient | ||
) ** (1 / coefficient) | ||
|
||
expected_value_A = value_A * probability_a + rng.normal(0, added_noise_) | ||
expected_value_B = value_B * probability_b + rng.normal(0, added_noise_) | ||
expected_value_A = value_A * probability_a + rng.normal(0, observation_noise) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, I would call |
||
expected_value_B = value_B * probability_b + rng.normal(0, observation_noise) | ||
|
||
# compute probability of choosing option A | ||
p_choose_A = np.exp(expected_value_A / choice_temperature) / ( | ||
|
@@ -124,9 +129,12 @@ def experiment_runner(X: np.ndarray, added_noise_=added_noise): | |
|
||
Y[idx] = p_choose_A | ||
|
||
return Y | ||
experiment_data = pd.DataFrame(conditions) | ||
experiment_data.columns = [v.name for v in variables.independent_variables] | ||
experiment_data[variables.dependent_variables[0].name] = Y | ||
return experiment_data | ||
|
||
ground_truth = partial(experiment_runner, added_noise_=0.0) | ||
ground_truth = partial(experiment_runner, observation_noise=0.0) | ||
|
||
def domain(): | ||
v_a = variables.independent_variables[0].allowed_values | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,19 @@ | ||
from functools import partial | ||
from typing import Optional, Union | ||
|
||
import numpy as np | ||
import pandas as pd | ||
|
||
from autora.experiment_runner.synthetic.utilities import SyntheticExperimentCollection | ||
from autora.variable import DV, IV, ValueType, VariableCollection | ||
|
||
|
||
def luce_choice_ratio( | ||
name="Luce-Choice-Ratio", | ||
added_noise=0.01, | ||
resolution=8, | ||
maximum_similarity=10, | ||
focus=0.8, | ||
rng=np.random.default_rng(), | ||
random_state: Optional[int] = None, | ||
): | ||
""" | ||
Luce-Choice-Ratio | ||
|
@@ -23,7 +24,7 @@ def luce_choice_ratio( | |
resolution: number of allowed values for stimulus DVs | ||
maximum_similarity: upperbound for DVs | ||
focus: parameter measuring participant focus | ||
rng: integer used to seed the random number generator | ||
random_state: integer used to seed the random number generator | ||
|
||
Shepard-Luce Choice Rule according to: | ||
- Equation (4) in Logan, G. D., & Gordon, R. D. (2001). | ||
|
@@ -32,39 +33,42 @@ def luce_choice_ratio( | |
- Equation (5) in Luce, R. D. (1963). Detection and recognition. | ||
|
||
Examples: | ||
First we seed numpy to get replicable results: | ||
>>> np.random.seed(42) | ||
|
||
We can instantiate a Shepard-Cue Choice Experiment. We use a seed to get replicable results: | ||
>>> l_s_experiment = luce_choice_ratio(rng=42) | ||
>>> l_s_experiment = luce_choice_ratio(random_state=42) | ||
|
||
We can look at the name of the experiment: | ||
>>> l_s_experiment.name | ||
'Luce-Choice-Ratio' | ||
|
||
To call the ground truth, we can use an attribute of the experiment: | ||
>>> l_s_experiment.ground_truth(np.array([[1,2,3,4]])) | ||
array([[0.21052632]]) | ||
similarity_category_A1 ... choose_A1 | ||
0 1 ... 0.210526 | ||
<BLANKLINE> | ||
[1 rows x 5 columns] | ||
|
||
We can also run an experiment: | ||
>>> l_s_experiment.experiment_runner(np.array([[1,2,3,4]])) | ||
array([[0.21016246]]) | ||
similarity_category_A1 ... choose_A1 | ||
0 1 ... 0.20779 | ||
<BLANKLINE> | ||
[1 rows x 5 columns] | ||
|
||
To plot the experiment use: | ||
>>> l_s_experiment.plotter() | ||
>>> plt.show() # doctest: +SKIP | ||
|
||
""" | ||
|
||
minimum_similarity = 1 / maximum_similarity | ||
|
||
params = dict( | ||
name=name, | ||
added_noise=added_noise, | ||
maximum_similarity=maximum_similarity, | ||
minimum_similarity=minimum_similarity, | ||
resolution=resolution, | ||
focus=focus, | ||
rng=rng, | ||
random_state=random_state, | ||
) | ||
|
||
similarity_category_A1 = IV( | ||
|
@@ -121,19 +125,22 @@ def luce_choice_ratio( | |
dependent_variables=[choose_A1], | ||
) | ||
|
||
rng = np.random.default_rng(random_state) | ||
|
||
def experiment_runner( | ||
X: np.ndarray, | ||
conditions: Union[pd.DataFrame, np.ndarray, np.recarray], | ||
focus_: float = focus, | ||
added_noise_: float = added_noise, | ||
observation_noise=0.01, | ||
): | ||
X = np.array(conditions) | ||
Y = np.zeros((X.shape[0], 1)) | ||
for idx, x in enumerate(X): | ||
similarity_A1 = x[0] | ||
similarity_A2 = x[1] | ||
similarity_B1 = x[2] | ||
similarity_B2 = x[3] | ||
|
||
y = (similarity_A1 * focus + np.random.normal(0, added_noise_)) / ( | ||
y = (similarity_A1 * focus + rng.normal(0, observation_noise)) / ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think here it is somewhat fine because we add it at the end and then normalize. You might still want to call it |
||
similarity_A1 * focus | ||
+ similarity_A2 * focus | ||
+ similarity_B1 * (1 - focus_) | ||
|
@@ -145,10 +152,12 @@ def experiment_runner( | |
elif y >= 1: | ||
y = 0.9999 | ||
Y[idx] = y | ||
experiment_data = pd.DataFrame(conditions) | ||
experiment_data.columns = [v.name for v in variables.independent_variables] | ||
experiment_data[choose_A1.name] = Y | ||
return experiment_data | ||
|
||
return Y | ||
|
||
ground_truth = partial(experiment_runner, added_noise_=0.0) | ||
ground_truth = partial(experiment_runner, observation_noise=0.0) | ||
|
||
def domain(): | ||
similarity_A1 = variables.independent_variables[0].allowed_values | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would call this
value_noise
which is specific to the expected utility theory instead ofobservation_noise