Skip to content

Commit 0c1d5e2

Browse files
committed
update docs
1 parent cfca5e8 commit 0c1d5e2

File tree

3 files changed

+259
-17
lines changed

3 files changed

+259
-17
lines changed

src/functions.jl

Lines changed: 187 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,87 @@
1+
"""
2+
prior_probs(model::Model, parm_grid)
3+
4+
Computes a grid of prior probabilities over model parameters.
5+
6+
- `model::Model`: a model object
7+
- `parm_grid`: a grid of parameter values
8+
"""
19
function prior_probs(model::Model, parm_grid)
210
return prior_probs(model.prior, parm_grid)
311
end
412

13+
"""
14+
prior_probs(prior, parm_grid)
15+
16+
Computes a grid of prior probabilities over model parameters.
17+
18+
- `prior`: a vector of `Distribution` objects, one for each parameter
19+
- `parm_grid`: a grid of parameter values
20+
"""
521
function prior_probs(prior, parm_grid)
622
dens = [mapreduce((θ,d)->pdf(d, θ), *, g, prior) for g in parm_grid]
723
return dens/sum(dens)
824
end
925

26+
"""
27+
prior_probs(prior, parm_grid)
28+
29+
Computes a grid of uniform prior probabilities over model parameters.
30+
31+
- `prior::Nothing`: a vector of `Distribution` objects, one for each parameter
32+
- `parm_grid`: a grid of parameter values
33+
"""
1034
function prior_probs(prior::Nothing, parm_grid)
1135
return fill(1/length(parm_grid), size(parm_grid))
1236
end
1337

38+
"""
39+
loglikelihood(model::Model, design_grid, parm_grid, data_grid, model_type, model_state)
40+
41+
Computes a three dimensional grid of log likelihoods where the first dimension is the model parameters, the second
42+
dimension is the design parameters, and the third dimension is the data values.
43+
44+
- `model::Model`: a model object containing a log likelihood function and prior distributions
45+
- `parm_grid`: a grid of model parameters
46+
- `design_grid`: a grid of design parameters
47+
- `data_grid`: a grid of data values
48+
- `model_type`: model type can be `Static` or `Dynamic`
49+
- `model_state`: model state variables that are updated for `Dynamic` models
50+
"""
1451
function loglikelihood(model::Model, design_grid, parm_grid, data_grid, model_type, model_state)
1552
return loglikelihood(model.loglike, design_grid, parm_grid, data_grid)
1653
end
1754

55+
"""
56+
loglikelihood(model::Model, design_grid, parm_grid, data_grid, model_type, model_state)
57+
58+
Computes a three dimensional grid of log likelihoods where the first dimension is the model parameters, the second
59+
dimension is the design parameters, and the third dimension is the data values.
60+
61+
- `model::Model`: a model object containing a log likelihood function and prior distributions
62+
- `parm_grid`: a grid of model parameters
63+
- `design_grid`: a grid of design parameters
64+
- `data_grid`: a grid of data values
65+
- `model_type`: model type can be `Static` or `Dynamic`
66+
- `model_state`: model state variables that are updated for `Dynamic` models
67+
"""
1868
function loglikelihood(model::Model, design_grid, parm_grid, data_grid, model_type::Dyn, model_state)
1969
return loglikelihood(model.loglike, design_grid, parm_grid, data_grid, model_state)
2070
end
2171

72+
"""
73+
loglikelihood(model::Model, design_grid, parm_grid, data_grid, model_type, model_state)
74+
75+
Computes a three dimensional grid of log likelihoods where the first dimension is the model parameters, the second
76+
dimension is the design parameters, and the third dimension is the data values.
77+
78+
- `loglike`: a model object containing a log likelihood function and prior distributions
79+
- `parm_grid`: a grid of model parameters
80+
- `design_grid`: a grid of design parameters
81+
- `data_grid`: a grid of data values
82+
- `model_type`: model type can be `Static` or `Dynamic`
83+
- `model_state`: model state variables that are updated for `Dynamic` models
84+
"""
2285
function loglikelihood(loglike, design_grid, parm_grid, data_grid)
2386
LLs = zeros(length(parm_grid), length(design_grid), length(data_grid))
2487
for (d, data) in enumerate(data_grid)
@@ -31,25 +94,61 @@ function loglikelihood(loglike, design_grid, parm_grid, data_grid)
3194
return LLs
3295
end
3396

97+
"""
98+
loglikelihood(model::Model, design_grid, parm_grid, data_grid, model_type, model_state)
99+
100+
Computes a three dimensional grid of log likelihoods for a dynamic model where the first dimension is the model parameters,
101+
the second dimension is the design parameters, and the third dimension is the data values.
102+
103+
- `loglike`: a model object containing a log likelihood function and prior distributions
104+
- `parm_grid`: a grid of model parameters
105+
- `design_grid`: a grid of design parameters
106+
- `data_grid`: a grid of data values
107+
- `model_type`: model type can be `Static` or `Dynamic`
108+
- `model_state`: model state variables that are updated for `Dynamic` models
109+
"""
34110
function loglikelihood(loglike, design_grid, parm_grid, data_grid, model_state)
35111
LLs = zeros(length(parm_grid), length(design_grid), length(data_grid))
36112
i = 0
37113
for (d, data) in enumerate(data_grid)
38114
for (k,design) in enumerate(design_grid)
39115
for (p,parms) in enumerate(parm_grid)
40116
i += 1
41-
LLs[p,k,d] = loglike(parms..., design..., data..., model_state[i])
117+
state = deepcopy(model_state[i])
118+
LLs[p,k,d] = loglike(parms..., design..., data..., state)
42119
end
43120
end
44121
end
45122
return LLs
46123
end
47124

125+
"""
126+
loglikelihood(optimizer::Optimizer)
127+
128+
Computes a three dimensional grid of log likelihoods for a dynamic model where the first dimension is the model parameters,
129+
the second dimension is the design parameters, and the third dimension is the data values.
130+
131+
- `optimizer`: an optimizer object
132+
133+
"""
48134
function loglikelihood!(optimizer)
49135
@unpack model, log_like, design_grid, parm_grid, data_grid, model_state = optimizer
50136
return loglikelihood!(model.loglike, log_like, design_grid, parm_grid, data_grid, model_state)
51137
end
52138

139+
"""
140+
loglikelihood(optimizer::Optimizer)
141+
142+
Computes a three dimensional grid of log likelihoods where the first dimension is the model parameters, the second
143+
dimension is the design parameters, and the third dimension is the data values.
144+
145+
- `loglike`: a model object containing a log likelihood function and prior distributions
146+
- `parm_grid`: a grid of model parameters
147+
- `design_grid`: a grid of design parameters
148+
- `data_grid`: a grid of data values
149+
- `model_type`: model type can be `Static` or `Dynamic`
150+
- `model_state`: model state variables that are updated for `Dynamic` models
151+
"""
53152
function loglikelihood!(loglike, log_like, design_grid, parm_grid, data_grid, model_state)
54153
i = 0
55154
for (d, data) in enumerate(data_grid)
@@ -64,18 +163,48 @@ function loglikelihood!(loglike, log_like, design_grid, parm_grid, data_grid, mo
64163
return nothing
65164
end
66165

166+
"""
167+
marginal_log_like!(optimizer)
168+
169+
Marginalizes the log likelihoods over model parameters, resulting in a three dimensional array where the first dimension is length 1,
170+
the second dimension is the design parameters, and the third dimension is the data values.
171+
172+
- `optimizer`: an optimizer object
173+
"""
67174
function marginal_log_like!(optimizer)
68175
@unpack marg_log_like,log_like,log_post = optimizer
69176
marg_log_like .= marginal_log_like(log_post, log_like)
70177
end
71178

179+
"""
180+
marginal_log_like(optimizer)
181+
182+
Marginalizes the log likelihoods over model parameters, resulting in a three dimensional array where the first dimension is length 1,
183+
the second dimension is the design parameters, and the third dimension is the data values.
184+
185+
- `log_post`: a vector of posterior log likelihood values for the model parameters
186+
- `log_like`: a three dimensional vector of log likelihood values where the first dimension corresponds to the model parameters,
187+
the second dimension corresponds to the design parameters, and the third dimension corresponds to the data values
188+
"""
72189
function marginal_log_like(log_post, log_like)
73190
return logsumexp(log_post .+ log_like, dims=1)
74191
end
75192

76-
function marginal_posterior(optimizer)
77-
@unpack posteriors = optimizer
78-
return map(d->sum(posterior, dims=d), ndims(posterior):-1:1)
193+
# """
194+
# marginal_posterior(optimizer)
195+
196+
# Computes a three dimensional grid of log likelihoods where the first dimension is the model parameters, the second
197+
# dimension is the design parameters, and the third dimension is the data values.
198+
199+
# - `optimizer`: an optimizer object
200+
# """
201+
# function marginal_posterior(optimizer)
202+
# @unpack posteriors = optimizer
203+
# return map(d->sum(posterior, dims=d), ndims(posterior):-1:1)
204+
# end
205+
206+
function compute_entropy(log_like)
207+
return -1*sum(exp.(log_like) .* log_like, dims=3)[:,:]
79208
end
80209

81210
function conditional_entropy(entropy, post)
@@ -88,10 +217,6 @@ function conditional_entropy!(optimizer)
88217
cond_entropy .= conditional_entropy(entropy, post)
89218
end
90219

91-
function compute_entropy(log_like)
92-
return -1*sum(exp.(log_like) .* log_like, dims=3)[:,:]
93-
end
94-
95220
function marginal_entropy!(optimizer::Optimizer)
96221
@unpack marg_entropy,marg_log_like = optimizer
97222
marg_entropy .= marginal_entropy(marg_log_like)
@@ -101,10 +226,25 @@ function marginal_entropy(marg_log_like)
101226
return -sum(exp.(marg_log_like).*marg_log_like, dims=3)[:]
102227
end
103228

229+
"""
230+
mutual_information(optimizer)
231+
232+
Computes a vector of the mutual information values where each element corresponds to a design parameter.
233+
234+
- `marg_entropy`: a vector of marginal entropy values where each element corresponds to a design parameter
235+
- `cond_entropy`: a vector of conditional entropy values where each element corresponds to a design parameter
236+
"""
104237
function mutual_information(marg_entropy, cond_entropy)
105238
return marg_entropy .- cond_entropy
106239
end
107240

241+
"""
242+
mutual_information!(optimizer)
243+
244+
Computes a vector of the mutual information values where each element corresponds to a design parameter.
245+
246+
- `optimizer`: an optimizer object
247+
"""
108248
function mutual_information!(optimizer)
109249
@unpack mutual_info,marg_entropy,cond_entropy = optimizer
110250
mutual_info .= mutual_information(marg_entropy, cond_entropy)
@@ -249,4 +389,42 @@ end
249389

250390
function create_state(model_type::Stat, T, dims, args...; kwargs...)
251391
return nothing
252-
end
392+
end
393+
394+
# function update(θ1, θ2, p, data)
395+
# #like = pdf.(Binomial.(n, x), k)
396+
# like = pdf.(Bernoulli.(x), d)
397+
# for d in data
398+
# θ1 .*= like
399+
# θ2 .*= like
400+
# end
401+
402+
# # e1 = θ1'*like
403+
# # e2 = θ2'*like
404+
405+
# # θ1 .= (θ1 .* like)/e1
406+
# # θ2 .= (θ2 .* like)/e2
407+
# e1 = sum(θ1)
408+
# e2 = sum(θ2)
409+
# θ1 ./= e1
410+
# θ2 ./= e2
411+
412+
# post_odds = (p * e1) / ((1 - p) * e2)
413+
# p = post_odds/(1 + post_odds)
414+
# return p, θ1, θ2
415+
# end
416+
417+
# # function update_model_posterior(ps, es)
418+
# # map(i->ps[i]./(sum(ps.*(es./es[i]))),1:length(ps))
419+
# # end
420+
421+
# using Distributions
422+
# p = .5
423+
# x = .001:.001:.999
424+
# θ1 = pdf.(Beta(10,1), x)
425+
# θ1 /= sum(θ1)
426+
427+
# θ2 = pdf.(Beta(1,1), x)
428+
# θ2 /= sum(θ2)
429+
430+
# p, θ1, θ2 = update(θ1, θ2, p, [1])

src/structs.jl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function Model(args...; prior=nothing, loglike, kwargs...)
6161
end
6262

6363
"""
64-
*Optimizer*
64+
Optimizer(;task, model, grid_design, grid_parms, grid_response)
6565
6666
`Optimizer` constructs a model object for adaptive design optimization
6767
@@ -75,13 +75,7 @@ end
7575
- `log_post`: a one dimensional array of log posterior probabilities for parameters
7676
- `entropy`: a two dimensional array of entropy values for parameter and design combinations
7777
-
78-
79-
Constructor
80-
81-
````julia
82-
Optimizer(;task, model, grid_design, grid_parms, grid_response)
83-
````
84-
# """
78+
"""
8579
mutable struct Optimizer{A,MT,M<:Model,T1,T2,T3,T4,T5,T6,T7,T8,T9,
8680
T10,T11}
8781
design_type::A

test/runtests.jl

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,40 @@ using SafeTestsets
3636
@test std_post(randomizer)[1] std(Beta+1+2)) atol = 5e-3
3737
end
3838

39+
@safetestset "Updating Default Prior" begin
40+
using Test, Distributions, AdaptiveDesignOptimization
41+
42+
α = 1
43+
β = 1
44+
loglike(θ, d, data) = logpdf(Bernoulli(θ), data)
45+
model = Model(; loglike)
46+
47+
parm_list = (
48+
θ = range(0, 1, length=200),
49+
)
50+
51+
design_list = (d = [1,2],)
52+
53+
data_list = (choice=[true, false],)
54+
55+
randomizer = Optimizer(;design_list, parm_list, data_list, model,
56+
approach=Randomize)
57+
58+
@test mean_post(randomizer)[1] mean(Beta(α,β)) atol = 5e-3
59+
@test std_post(randomizer)[1] std(Beta(α,β)) atol = 5e-3
60+
61+
update!(randomizer, false)
62+
@test mean_post(randomizer)[1] mean(Beta(α,β+1)) atol = 5e-3
63+
@test std_post(randomizer)[1] std(Beta(α,β+1)) atol = 5e-3
64+
65+
update!(randomizer, false)
66+
@test mean_post(randomizer)[1] mean(Beta(α,β+2)) atol = 5e-3
67+
@test std_post(randomizer)[1] std(Beta(α,β+2)) atol = 5e-3
68+
69+
update!(randomizer, true)
70+
@test mean_post(randomizer)[1] mean(Beta+1+2)) atol = 5e-3
71+
@test std_post(randomizer)[1] std(Beta+1+2)) atol = 5e-3
72+
end
3973

4074
@safetestset "Updating Prior Dynamic Model" begin
4175
using Test, Distributions, AdaptiveDesignOptimization
@@ -77,3 +111,39 @@ end
77111
@test std_post(randomizer)[1] std(Beta+1+2)) atol = 5e-3
78112
end
79113

114+
115+
@safetestset "Dimension Check" begin
116+
using Test, Distributions, AdaptiveDesignOptimization
117+
118+
loglike(μ, σ, data, args...) = logpdf(Normal(μ, σ), data)
119+
model = Model(; loglike)
120+
121+
parm_list = (
122+
μ = range(0, 10, length=10),
123+
σ = range(1, 5, length=10),
124+
)
125+
126+
design_list = (
127+
d = range(1, 5, length=10),
128+
z = range(1, 5, length=10),
129+
v = range(1, 5, length=10)
130+
)
131+
132+
data_list = (
133+
choice=[true, false],
134+
v = 1:3
135+
)
136+
137+
optimizer = Optimizer(;design_list, parm_list, data_list, model)
138+
139+
@test optimizer.parm_grid |> size == (10,10)
140+
@test optimizer.design_grid |> size == (10,10,10)
141+
@test optimizer.data_grid |> size == (2,3)
142+
@test optimizer.log_like |> size == (100,1000,6)
143+
@test optimizer.log_post |> size == (100,)
144+
@test optimizer.priors |> size == (10,10)
145+
@test optimizer.mutual_info |> size == (1000,)
146+
@test optimizer.marg_log_like |> size == (1,1000,6)
147+
@test optimizer.marg_entropy |> size == (1000,)
148+
@test optimizer.cond_entropy |> size == (1000,)
149+
end

0 commit comments

Comments
 (0)