Overview
The purpose of this page is to demonstrate basic usage of the API. The following examples will be based on the context efect model described in Busemeyer & Wang (2018). A brief description of the model can be found here and a more detailed description can be found here.
Make Predictions
The function predict
will generate all possible joint probability tables of a dimensionality specified by n_way
.
Two-way Tables
The code block below demonstrates how to generate predictions for 2-way joint probability tables. Each table is of size $2 \times 2$ because each attribute is binary. Given four attributes and n_way=2
, there are $P(4,2) = 12$ joint probability tables in total (including the order of attributes within a pair).
using QuantumContextEffectModels
n_way = 2
parms = (
Ψ = sqrt.([.3,.1,.2,.4]),
θil = .3,
θpb = .3,
)
model = QuantumModel(; parms...)
preds = predict(model; n_way)
6-element Vector{Vector{Vector{Float64}}}:
[[0.29999999999999993, 0.19999999999999998, 0.1, 0.4], [0.29999999999999993, 0.19999999999999998, 0.1, 0.4]]
[[0.3296242254116391, 0.6244490954320945, 0.03005940175537921, 0.015867277400887215], [0.13819660112501053, 0.3927050983124843, 0.2618033988749895, 0.2072949016875158]]
[[0.33382612127177164, 0.5999011042230776, 0.06617387872822834, 9.889577692232744e-5], [0.33382612127177164, 0.5999011042230776, 0.06617387872822834, 9.889577692232744e-5]]
[[0.46750946842846075, 0.4865638524152729, 0.03249053157153925, 0.013436147584727174], [0.46750946842846075, 0.4865638524152729, 0.03249053157153925, 0.013436147584727174]]
[[0.3225948223531861, 0.6111324031416632, 0.043376094045810484, 0.02289668045934019], [0.17274575140626314, 0.3272542485937369, 0.32725424859373686, 0.17274575140626316]]
[[0.9335790596597751, 0.00014816583507435547, 0.02049426118395861, 0.04577851332119207], [0.9335790596597751, 0.00014816583507435547, 0.02049426118395861, 0.04577851332119207]]
The nested vector preds
contains $C(4,2) = 6$ combinations of attributes (ignoring order). As shown below, each sub-vector contains a flattened joint probability table, one for each order.
preds[1]
2-element Vector{Vector{Float64}}:
[0.29999999999999993, 0.19999999999999998, 0.1, 0.4]
[0.29999999999999993, 0.19999999999999998, 0.1, 0.4]
Three-way Tables
The code block below shows how to create all possible joint probability tables of dimensionality 3 by changing n_way=2
to n_way=3
. In this example,there are $P(4,3) = 24$ joint probability tables (6 orders for each unique set of 3 attributes).
preds = predict(model; n_way = 3)
4-element Vector{Vector{Vector{Float64}}}:
[[0.1615205488264342, 0.30598891960202657, 0.1681036765852049, 0.31846017583006797, 0.02126532899171032, 0.011225202579828931, 0.00879407276366889, 0.004642074821058283], [0.1615205488264342, 0.30598891960202657, 0.1681036765852049, 0.31846017583006797, 0.02126532899171032, 0.011225202579828931, 0.00879407276366889, 0.004642074821058283], [0.1615205488264342, 0.30598891960202657, 0.1681036765852049, 0.31846017583006797, 0.02126532899171032, 0.011225202579828931, 0.00879407276366889, 0.004642074821058283], [0.10364745084375789, 0.13090169943749475, 0.03454915028125263, 0.26180339887498955, 0.19635254915624212, 0.06909830056250527, 0.06545084971874739, 0.13819660112501053], [0.10364745084375789, 0.13090169943749475, 0.03454915028125263, 0.26180339887498955, 0.19635254915624212, 0.06909830056250527, 0.06545084971874739, 0.13819660112501053], [0.10364745084375789, 0.13090169943749475, 0.03454915028125263, 0.26180339887498955, 0.19635254915624212, 0.06909830056250527, 0.06545084971874739, 0.13819660112501053]]
[[0.11533408831626103, 0.20726073403692505, 0.21849203295551062, 0.3926403701861526, 0.043311365919478866, 6.472812633162075e-5, 0.022862512808749482, 3.4167650590706694e-5], [0.10364745084375789, 0.06909830056250527, 0.06545084971874739, 0.26180339887498955, 0.19635254915624212, 0.13090169943749475, 0.03454915028125263, 0.13819660112501053], [0.11533408831626103, 0.20726073403692505, 0.21849203295551062, 0.3926403701861526, 0.043311365919478866, 6.472812633162075e-5, 0.022862512808749482, 3.4167650590706694e-5], [0.11533408831626103, 0.20726073403692505, 0.21849203295551062, 0.3926403701861526, 0.043311365919478866, 6.472812633162075e-5, 0.022862512808749482, 3.4167650590706694e-5], [0.10364745084375789, 0.06909830056250527, 0.06545084971874739, 0.26180339887498955, 0.19635254915624212, 0.13090169943749475, 0.03454915028125263, 0.13819660112501053], [0.10364745084375789, 0.06909830056250527, 0.06545084971874739, 0.26180339887498955, 0.19635254915624212, 0.13090169943749475, 0.03454915028125263, 0.13819660112501053]]
[[0.3225436323161609, 0.6110354273436143, 9.697579804904305e-5, 5.119003702531242e-5, 0.007080593095478287, 0.013413668088480324, 0.029962425957330167, 0.015816087363861902], [0.3225436323161609, 0.6110354273436143, 9.697579804904305e-5, 5.119003702531242e-5, 0.007080593095478287, 0.013413668088480324, 0.029962425957330167, 0.015816087363861902], [0.11533408831626105, 0.3926403701861527, 0.21849203295551065, 0.20726073403692513, 0.022862512808749482, 6.47281263316202e-5, 0.04331136591947887, 3.4167650590707026e-5], [0.11533408831626105, 0.3926403701861527, 0.21849203295551065, 0.20726073403692513, 0.022862512808749482, 6.47281263316202e-5, 0.04331136591947887, 3.4167650590707026e-5], [0.3225436323161609, 0.6110354273436143, 9.697579804904305e-5, 5.119003702531242e-5, 0.007080593095478287, 0.013413668088480324, 0.029962425957330167, 0.015816087363861902], [0.11533408831626105, 0.3926403701861527, 0.21849203295551065, 0.20726073403692513, 0.022862512808749482, 6.47281263316202e-5, 0.04331136591947887, 3.4167650590707026e-5]]
[[0.3225436323161608, 0.6110354273436143, 5.11900370253121e-5, 9.697579804904337e-5, 0.01341366808848032, 0.007080593095478291, 0.029962425957330167, 0.015816087363861902], [0.3225436323161608, 0.6110354273436143, 5.11900370253121e-5, 9.697579804904337e-5, 0.01341366808848032, 0.007080593095478291, 0.029962425957330167, 0.015816087363861902], [0.3225436323161608, 0.6110354273436143, 5.11900370253121e-5, 9.697579804904337e-5, 0.01341366808848032, 0.007080593095478291, 0.029962425957330167, 0.015816087363861902], [0.16152054882643424, 0.3184601758300681, 0.011225202579828928, 0.00879407276366889, 0.30598891960202657, 0.16810367658520492, 0.021265328991710325, 0.004642074821058287], [0.16152054882643424, 0.3184601758300681, 0.011225202579828928, 0.00879407276366889, 0.30598891960202657, 0.16810367658520492, 0.021265328991710325, 0.004642074821058287], [0.16152054882643424, 0.3184601758300681, 0.011225202579828928, 0.00879407276366889, 0.30598891960202657, 0.16810367658520492, 0.021265328991710325, 0.004642074821058287]]
In general, if there are $n_a$ attributes, the function predict
can generate tables of dimensionality $[1,2,\dots, n_a]$.
Single Order
As shown below, you can assign the function get_joint_probs
to the keyword joint_func
to omit the orders of joint probability tables (e.g., [A,B] instead of [A,B], [B,A]).
using QuantumContextEffectModels
n_way = 2
parms = (
Ψ = sqrt.([.3,.1,.2,.4]),
θil = .3,
θpb = .3,
)
model = QuantumModel(; parms...)
preds = predict(
model;
joint_func = get_joint_probs,
n_way
)
6-element Vector{Vector{Float64}}:
[0.29999999999999993, 0.19999999999999998, 0.1, 0.4]
[0.3296242254116391, 0.6244490954320945, 0.03005940175537921, 0.015867277400887215]
[0.33382612127177164, 0.5999011042230776, 0.06617387872822834, 9.889577692232744e-5]
[0.46750946842846075, 0.4865638524152729, 0.03249053157153925, 0.013436147584727174]
[0.3225948223531861, 0.6111324031416632, 0.043376094045810484, 0.02289668045934019]
[0.9335790596597751, 0.00014816583507435547, 0.02049426118395861, 0.04577851332119207]
Simulate Model
The code block below demonstrates how to generate simulated data from the model using rand
. In the example, we will generate 100 simulated trials for each condition.
using QuantumContextEffectModels
n_way = 2
n_trials = 100
parms = (
Ψ = sqrt.([.3,.1,.2,.4]),
θil = .3,
θpb = .3,
)
model = QuantumModel(; parms...)
data = rand(model, n_trials; n_way)
6-element Vector{Vector{Vector{Int64}}}:
[[28, 25, 9, 38], [25, 19, 10, 46]]
[[44, 52, 1, 3], [19, 34, 27, 20]]
[[40, 56, 4, 0], [38, 55, 7, 0]]
[[51, 42, 4, 3], [47, 48, 4, 1]]
[[37, 57, 3, 3], [10, 35, 34, 21]]
[[91, 0, 2, 7], [92, 0, 4, 4]]
Labeled Tables
Interpreting the large number of nested arrays can be challenging. In the model illustrated here, there are 12 two-way tables embedded within the nested arrays. We can use to_table
to assign labels to aid in the intepretation. In the code block below, we define two variables: var_names
, which is the name of the attributes, and values
which are the corresponding values for each attribute. To ensure the tables are labeled correctly, it is necessary to use the same order of attributes and values defined in make_projectors
.
There are 12 tables in the full set. For ease of presentation, we will focus on the first two sets. The first set contains two tables for attributes believable and informative–-one for each order. The predictions are the same for each order because believable and informative are compatible. For example,
\[\Pr(B = -1 \cap I = 1) = \Pr(I = 1 \cap B = -1) = .20,\]
where 1 corresponds to yes and -1 correspond to no.
using QuantumContextEffectModels
n_way = 2
parms = (
Ψ = sqrt.([.3,.1,.2,.4]),
θil = .3,
θpb = .3,
)
model = QuantumModel(; parms...)
preds = predict(model; n_way)
var_names = [
:B, # believable
:I, # informative
:P, # persuasive
:L # likable
]
values = fill([:yes,:no], 4)
df = to_tables(preds, var_names, values, n_way)
df[1]
2-element Vector{DataFrames.DataFrame}:
4×6 DataFrame
Row │ group order attributes values val_idx preds
│ Int64 Int64 Array… Array… Int64 Float64
─────┼──────────────────────────────────────────────────────────
1 │ 1 1 [:B, :I] [:yes, :yes] 1 0.3
2 │ 1 1 [:B, :I] [:no, :yes] 2 0.2
3 │ 1 1 [:B, :I] [:yes, :no] 3 0.1
4 │ 1 1 [:B, :I] [:no, :no] 4 0.4
4×6 DataFrame
Row │ group order attributes values val_idx preds
│ Int64 Int64 Array… Array… Int64 Float64
─────┼──────────────────────────────────────────────────────────
1 │ 1 2 [:I, :B] [:yes, :yes] 1 0.3
2 │ 1 2 [:I, :B] [:yes, :no] 2 0.2
3 │ 1 2 [:I, :B] [:no, :yes] 3 0.1
4 │ 1 2 [:I, :B] [:no, :no] 4 0.4
The code block below shows the second set for believable and persuasive. Again, there is a $2 \times 2$ table for each order. However, in this case, the $2 \times 2$ tables are different because believable and persuasive are incompatible, resulting in order effects. For example,
\[\Pr(B = -1 \cap P = 1) \ne \Pr(P = 1 \cap B = -1).\]
df[2]
2-element Vector{DataFrames.DataFrame}:
4×6 DataFrame
Row │ group order attributes values val_idx preds
│ Int64 Int64 Array… Array… Int64 Float64
─────┼────────────────────────────────────────────────────────────
1 │ 2 1 [:B, :P] [:yes, :yes] 1 0.329624
2 │ 2 1 [:B, :P] [:no, :yes] 2 0.624449
3 │ 2 1 [:B, :P] [:yes, :no] 3 0.0300594
4 │ 2 1 [:B, :P] [:no, :no] 4 0.0158673
4×6 DataFrame
Row │ group order attributes values val_idx preds
│ Int64 Int64 Array… Array… Int64 Float64
─────┼───────────────────────────────────────────────────────────
1 │ 2 2 [:P, :B] [:yes, :yes] 1 0.138197
2 │ 2 2 [:P, :B] [:yes, :no] 2 0.392705
3 │ 2 2 [:P, :B] [:no, :yes] 3 0.261803
4 │ 2 2 [:P, :B] [:no, :no] 4 0.207295
DataFrame
In many cases, the use of a flat data structure can facilitate data analysis and plotting. The function to_dataframe
converts a nested array into a flat DataFrame
object. Similar to the function to_tables
, to_dataframe
requires attribute names and attribute values, which are specified in the same order as the projectors in make_projectors
.
using QuantumContextEffectModels
n_way = 2
parms = (
Ψ = sqrt.([.3,.1,.2,.4]),
θil = .3,
θpb = .3,
)
model = QuantumModel(; parms...)
preds = predict(model; n_way)
var_names = [
:B, # believable
:I, # informative
:P, # persuasive
:L # likable
]
values = fill([:yes,:no], 4)
df = to_dataframe(preds, var_names, values, n_way)
first(df, 8)
Row | group | order | attributes | values | val_idx | preds |
---|---|---|---|---|---|---|
Int64 | Int64 | Array… | Array… | Int64 | Float64 | |
1 | 1 | 1 | [:B, :I] | [:yes, :yes] | 1 | 0.3 |
2 | 1 | 1 | [:B, :I] | [:no, :yes] | 2 | 0.2 |
3 | 1 | 1 | [:B, :I] | [:yes, :no] | 3 | 0.1 |
4 | 1 | 1 | [:B, :I] | [:no, :no] | 4 | 0.4 |
5 | 1 | 2 | [:I, :B] | [:yes, :yes] | 1 | 0.3 |
6 | 1 | 2 | [:I, :B] | [:yes, :no] | 2 | 0.2 |
7 | 1 | 2 | [:I, :B] | [:no, :yes] | 3 | 0.1 |
8 | 1 | 2 | [:I, :B] | [:no, :no] | 4 | 0.4 |
Evaluate Log Likelihood
The log likelihood of data can be evaluated using logpdf
. In the code block below, we generate simulated data and evaluate the logpdf:
using QuantumContextEffectModels
n_way = 2
n_trials = 100
parms = (
Ψ = sqrt.([.3,.1,.2,.4]),
θil = .3,
θpb = .3,
)
model = QuantumModel(; parms...)
data = rand(model, n_trials; n_way)
logpdf(model, data, n_trials; n_way)
-78.58301738686018