Skip to content

Commit ee5fa88

Browse files
committed
unify prior parameterization and computation
1 parent c51ef87 commit ee5fa88

6 files changed

Lines changed: 57 additions & 60 deletions

File tree

src/HybridSolver.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ function CommonSolve.solve(prob::AbstractHybridProblem, solver::HybridPointSolve
1313
ad_backend_loss = AutoZygote(),
1414
epochs,
1515
is_omitting_NaNbatches = false,
16-
is_omit_priors::Val{is_omit_prior} = Val(false),
16+
is_omit_priors::Val{omit_priors} = Val(false),
1717
kwargs...
18-
) where {is_infer, is_omit_prior}
18+
) where {is_infer, omit_priors}
1919
gdevs = isnothing(gdevs) ? get_gdev_MP(scenario) : gdevs
2020
pt = get_hybridproblem_par_templates(prob; scenario)
2121
g, ϕg0 = get_hybridproblem_MLapplicator(prob; scenario)
@@ -63,13 +63,17 @@ function CommonSolve.solve(prob::AbstractHybridProblem, solver::HybridPointSolve
6363
priors = get_hybridproblem_priors(prob; scenario)
6464
priorsP = Tuple(priors[k] for k in keys(pt.θP))
6565
priorsM = Tuple(priors[k] for k in keys(pt.θM))
66+
zero_prior_logdensity = omit_priors ? 0f0 : get_zero_prior_logdensity(
67+
priorsP, priorsM, pt.θP, pt.θM)
6668
#intP = ComponentArrayInterpreter(pt.θP)
6769
loss_gf = get_loss_gf(g_dev, transM, transP, f_dev, py, intϕ;
6870
n_site_batch=n_batch,
69-
cdev=infer_cdev(gdevs), pbm_covars, priorsP, priorsM, is_omit_priors,)
71+
cdev=infer_cdev(gdevs), pbm_covars,
72+
priorsP, priorsM, is_omit_priors, zero_prior_logdensity,)
7073
loss_gf_test = get_loss_gf(g_dev, transM, transP, ftest_dev, py, intϕ;
7174
n_site_batch=n_site_test,
72-
cdev=infer_cdev(gdevs), pbm_covars, priorsP, priorsM, is_omit_priors,)
75+
cdev=infer_cdev(gdevs), pbm_covars,
76+
priorsP, priorsM, is_omit_priors, zero_prior_logdensity,)
7377
# call loss function once
7478
l1 = is_infer ?
7579
Test.@inferred(loss_gf(ϕ0_dev, first(train_loader_dev)...; is_testmode=true))[1] :

src/elbo.jl

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ function neg_elbo_ζtf(ζsP, ζsMs, σ, f, py, xP, y_ob, y_unc;
134134
transMs=StackedArray(transM, size(ζsMs, 2)),
135135
priorsP, priorsM,
136136
floss_penalty, ϕg, ϕq,
137-
is_omit_priors::Val{omit_priors},
137+
is_omit_priors::Val,
138138
zero_prior_logdensity,
139-
) where omit_priors
139+
)
140140
n_MC = size(ζsP,2)
141141
f_sample = (ζP, ζMs) -> begin
142142
θP, θMs, logjac_i = transform_and_logjac_ζ(ζP, ζMs; transP, transMs)
@@ -150,16 +150,8 @@ function neg_elbo_ζtf(ζsP, ζsMs, σ, f, py, xP, y_ob, y_unc;
150150
# @descend_code_warntype f(θP, θMs, xP)
151151
nLy_i = py(y_ob, y_pred_i, y_unc)
152152
loss_penalty_i = convert(eltype(nLy_i),floss_penalty(y_pred_i, θMs, θP, ϕg, ϕq))
153-
neg_log_prior_i = if omit_priors
154-
zero_prior_logdensity
155-
elseif (θP isa AbstractGPUArray) || (θMs isa AbstractGPUArray)
156-
@warn("neg_elbo_ζtf: Cannot apply priors to gpu array. Piors are omitted. " *
157-
"either compute PBM on CPU or omit priors.")
158-
zero_prior_logdensity
159-
else
160-
compute_priors_logdensity(priorsP, priorsM, θP, θMs, zero_prior_logdensity)
161-
end
162-
153+
neg_log_prior_i = compute_priors_logdensity(priorsP, priorsM, θP, θMs,
154+
is_omit_priors, zero_prior_logdensity)
163155
# make sure names to not match outer, otherwise Box type instability
164156
(nLy_i, neg_log_prior_i, -logjac_i, loss_penalty_i)
165157
#(nLy_i, 0.0, 0.0, 0.0)
@@ -207,6 +199,19 @@ function neg_elbo_ζtf(ζsP, ζsMs, σ, f, py, xP, y_ob, y_unc;
207199
(;nLjoint, entropy_ζ, loss_penalty, nLy, neg_log_prior, neg_log_jac)
208200
end
209201

202+
function compute_priors_logdensity(priorsP, priorsM, θP, θMs,
203+
::Val{omit_priors}, zero_prior_logdensity) where {omit_priors}
204+
if omit_priors
205+
zero_prior_logdensity
206+
elseif (θP isa AbstractGPUArray) || (θMs isa AbstractGPUArray)
207+
@warn("neg_elbo_ζtf: Cannot apply priors to gpu array. Piors are omitted. "*
208+
"either compute PBM on CPU or omit priors.")
209+
zero_prior_logdensity
210+
else
211+
compute_priors_logdensity(priorsP, priorsM, θP, θMs, zero_prior_logdensity)
212+
end
213+
end
214+
210215
function compute_priors_logdensity(priorsP, priorsM, θP, θMs, zero_prior_logdensity)
211216
logpdf_t = (prior, θ) -> logpdf(prior, θ)::eltype(θP)
212217
function logpdf_tv_sum(prior, θ::AbstractVector{T}) where T

src/gf.jl

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -231,16 +231,20 @@ function get_loss_gf(g, transM, transP, f, py,
231231
intϕ(1:length(intϕ)).ϕP);
232232
cdev=cpu_device(),
233233
pbm_covars, n_site_batch,
234-
priorsP, priorsM, floss_penalty = zero_penalty_loss,
235-
is_omit_priors::Val{is_omit_prior} = Val(false),
236-
kwargs...) where is_omit_prior
234+
floss_penalty = zero_penalty_loss,
235+
priorsP, priorsM,
236+
is_omit_priors::Val = Val(false),
237+
zero_prior_logdensity,
238+
kwargs...)
237239

238240
let g = g, transM = transM, transP = transP, f = f,
239241
intϕ = get_concrete(intϕ),
240242
transMs = StackedArray(transM, n_site_batch),
241243
cdev = cdev,
242244
pbm_covar_indices = CA.getdata(intP(1:length(intP))[pbm_covars]),
243-
priorsP = priorsP, priorsM = priorsM, floss_penalty = floss_penalty,
245+
zero_prior_logdensity = zero_prior_logdensity, is_omit_priors = is_omit_priors,
246+
priorsP = priorsP, priorsM = priorsM,
247+
floss_penalty = floss_penalty,
244248
cpu_dev = cpu_device() # real cpu, different form infer_cdev(gdevs) that maybe idenetity
245249
#, intP = get_concrete(intP)
246250
#inv_transP = inverse(transP), kwargs = kwargs
@@ -273,29 +277,8 @@ function get_loss_gf(g, transM, transP, f, py,
273277
logpdf_tv = (prior, θ::AbstractVector) -> begin
274278
map(Base.Fix1(logpdf, prior), θ)::Vector{eltype(θP_pred)}
275279
end
276-
#Main.@infiltrate_main
277-
#Maybe: move priors to GPU, for now need to move θ to cpu
278-
# currently does not work on gpu, moving to dpu has problems with gradient
279-
# need to specify is_omit_priors if PBM is on GPU
280-
neg_log_prior = if is_omit_prior
281-
zero(nLy)
282-
else
283-
nLP = if isempty(θP_pred)
284-
zero(nLy)
285-
else
286-
θP_pred_cpu = CA.getdata(θP_pred)
287-
-sum(logpdf_t.(priorsP, θP_pred_cpu))
288-
end
289-
θMs_pred_cpu = CA.getdata(θMs_pred)
290-
nLM = -sum(map((priorMi, θMi) -> sum(
291-
logpdf_tv(priorMi, θMi)), priorsM, eachcol(θMs_pred_cpu)))
292-
nLP + nLM
293-
end
294-
# neg_log_prior = is_omit_priors ? zero(nLy) :
295-
# (isempty() ? zero(nLy) : ) +
296-
# -sum(map((priorMi, θMi) -> sum(
297-
# logpdf_tv(priorMi, θMi)), priorsM, eachcol(θMs_pred_cpu)))
298-
#neg_log_prior = min(sqrt(floatmax(neg_log_prior0)), neg_log_prior0)
280+
neg_log_prior = compute_priors_logdensity(priorsP, priorsM, θP_pred, θMs_pred,
281+
is_omit_priors, zero_prior_logdensity)
299282
if !isfinite(neg_log_prior)
300283
@info "loss_gf: encountered non-finite prior density"
301284
@show θP_pred, θMs_pred, ϕc.ϕP

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
2727
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
2828
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
2929
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
30+
UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
3031
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3132
cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"

test/test_HybridProblem.jl

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Test
22
using HybridVariationalInference
33
using HybridVariationalInference: HybridVariationalInference as CP
4+
using UnPack
45
using StableRNGs
56
using Random
67
using Statistics
@@ -19,6 +20,7 @@ using Suppressor
1920

2021
using Functors
2122

23+
2224
cdev = cpu_device()
2325

2426
#scenario = Val((:default,))
@@ -106,9 +108,7 @@ end
106108
function test_f_doubleMM::AbstractVector{ET}, x; intθ1) where ET
107109
# extract parameters not depending on order, i.e whether they are in θP or θM
108110
θc = intθ1(θ)
109-
(r0, r1, K1, K2) = map((:r0, :r1, :K1, :K2)) do par
110-
CA.getdata(θc[par])::ET
111-
end
111+
@unpack r0, r1, K1, K2 = θc
112112
r0 .+ r1 .* x.S1 ./ (K1 .+ x.S1) .* x.S2 ./ (K2 .+ x.S2)
113113
end
114114
y = @inferred test_f_doubleMM(CA.getdata(θ2), xP1; intθ1 = int_θdoubleMM)
@@ -151,14 +151,16 @@ test_without_flux = (scenario) -> begin
151151
intϕ = ComponentArrayInterpreter(CA.ComponentVector(
152152
ϕg=1:length(ϕg0), ϕP=par_templates.θP))
153153
priors = get_hybridproblem_priors(prob; scenario)
154-
priorsP = [priors[k] for k in keys(par_templates.θP)]
155-
priorsM = [priors[k] for k in keys(par_templates.θM)]
154+
priorsP = Tuple(priors[k] for k in keys(par_templates.θP))
155+
priorsM = Tuple(priors[k] for k in keys(par_templates.θM))
156156
# slightly disturb θP_true
157157
p = p0 = vcat(ϕg0, par_templates.θP .* convert(eltype(ϕg0), 0.8))
158158

159159
# Pass the site-data for the batches as separate vectors wrapped in a tuple
160+
zero_prior_logdensity = CP.get_zero_prior_logdensity(
161+
priorsP, priorsM, par_templates.θP, par_templates.θM)
160162
loss_gf = get_loss_gf(g, transM, transP, f, py, intϕ;
161-
pbm_covars, n_site_batch = n_batch, priorsP, priorsM,
163+
pbm_covars, n_site_batch = n_batch, priorsP, priorsM, zero_prior_logdensity,
162164
)
163165
(_xM, _xP, _y_o, _y_unc, _i_sites) = first(train_loader)
164166
#l1 = loss_gf(p0, _xM, _xP, _y_o, _y_unc, _i_sites; is_testmode = false)
@@ -312,13 +314,13 @@ test_with_flux_gpu = (scenario) -> begin
312314
(; y, θsP, θsMs) = predict_hvi(rng, probo; scenario = scenf, n_sample_pred);
313315
# to inspect correlations among θP and θMs construct ComponentVector
314316
# TODO redo get_int_PMst_site
315-
# get_ca_int_PMs = let
316-
# function get_ca_int_PMs_inner(n_site)
317-
# ComponentArrayInterpreter(CA.ComponentVector(; P = θP,
318-
# Ms = CA.ComponentMatrix(
319-
# zeros(n_θM, n_site), first(CA.getaxes(θM)), CA.Shaped1DAxis((n_site,)))))
320-
# end
321-
# end
317+
# get_ca_int_PMs = let
318+
# function get_ca_int_PMs_inner(n_site)
319+
# ComponentArrayInterpreter(CA.ComponentVector(; P = θP,
320+
# Ms = CA.ComponentMatrix(
321+
# zeros(n_θM, n_site), first(CA.getaxes(θM)), CA.Shaped1DAxis((n_site,)))))
322+
# end
323+
# end
322324
int_mPMs = stack_ca_int(Val((n_sample_pred,)), get_int_PMst_site(hpints))
323325
θs = int_mPMs(CP.flatten_hybrid_pars(θsP, θsMs))
324326
mean_θ = CA.ComponentVector(vec(mean(CA.getdata(θs), dims=1)), last(CA.getaxes(θs)))

test/test_doubleMM.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ end
204204
f2 = create_nsite_applicator(f, n_site)
205205
py = get_hybridproblem_neg_logden_obs(prob; scenario)
206206
priors = get_hybridproblem_priors(prob; scenario)
207-
priorsP = [priors[k] for k in keys(par_templates.θP)]
208-
priorsM = [priors[k] for k in keys(par_templates.θM)]
207+
priorsP = Tuple(priors[k] for k in keys(par_templates.θP))
208+
priorsM = Tuple(priors[k] for k in keys(par_templates.θM))
209209

210210
intϕ = ComponentArrayInterpreter(CA.ComponentVector(
211211
ϕg = 1:length(ϕg0), ϕP = par_templates.θP))
@@ -222,10 +222,12 @@ end
222222
pbm_covars = get_hybridproblem_pbmpar_covars(prob; scenario)
223223

224224
#loss_gf = get_loss_gf(g, transM, f, intϕ; gdev = identity)
225+
zero_prior_logdensity = CP.get_zero_prior_logdensity(
226+
priorsP, priorsM, par_templates.θP, par_templates.θM)
225227
loss_gf = get_loss_gf(g, transM, transP, f, py, intϕ;
226-
pbm_covars, n_site_batch = n_batch, priorsP, priorsM)
228+
pbm_covars, n_site_batch = n_batch, priorsP, priorsM, zero_prior_logdensity)
227229
loss_gf_site = get_loss_gf(g, transM, transP, f2, py, intϕ;
228-
pbm_covars, n_site_batch = n_site, priorsP, priorsM)
230+
pbm_covars, n_site_batch = n_site, priorsP, priorsM, zero_prior_logdensity)
229231
nLjoint = @inferred first(loss_gf(p0, first(train_loader)...; is_testmode=true))
230232
(xM_batch, xP_batch, y_o_batch, y_unc_batch, i_sites_batch) = first(train_loader)
231233
# @usingany Cthulhu

0 commit comments

Comments
 (0)