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

dynamic_inference update #60

Merged
merged 18 commits into from
Dec 1, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
6 changes: 3 additions & 3 deletions REQUIRE
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ RecursiveArrayTools
ParameterizedFunctions
OrdinaryDiffEq
Parameters
#DiffWrappers
ContinuousTransformations 1.0.0
DynamicHMC 0.1.1
DynamicHMC
Distances
ApproxBayes
TransformVariables
LogDensityProblems
2 changes: 1 addition & 1 deletion src/DiffEqBayes.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module DiffEqBayes
using DiffEqBase, Stan, Distributions, Turing, MacroTools
using OrdinaryDiffEq, ParameterizedFunctions, RecursiveArrayTools
using DynamicHMC, ContinuousTransformations
using DynamicHMC, TransformVariables, LogDensityProblems
using Parameters, Distributions, Optim
using Distances, ApproxBayes

Expand Down
58 changes: 27 additions & 31 deletions src/dynamichmc_inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function dynamichmc_inference(prob::DiffEqBase.DEProblem, alg, t, data, priors,
kwargs...)
likelihood = sol -> sum( sum(logpdf.(Normal(0.0, σ), sol(t) .- data[:, i]))
for (i, t) in enumerate(t) )

println(typeof(transformations))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why you are printing it, but that's a minor thing.

Regarding the API: perhaps I am missing something, but I would make transformations part of the problem, ie in DynamicHMCPosterior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify how that would work, I also feel that adding the transformation like I am doing is not really going to work (I actually copied this right off your linear regression example according to my understanding).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also make the transformation a slot in the composite type. But with this interface, it may not be needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, the does sound good, but then how would the applied is not clear to me, I can imagine that with the ContinuousTransformations interface, I'll push with what I think would work here but I doubt it will be correct 😅

dynamichmc_inference(prob, alg, likelihood, priors, transformations;
ϵ=ϵ, initial=initial, num_samples=num_samples,
kwargs...)
Expand All @@ -43,39 +43,35 @@ function dynamichmc_inference(prob::DiffEqBase.DEProblem, alg, likelihood, prior
ϵ=0.001, initial=Float64[], num_samples=1000,
kwargs...)
P = DynamicHMCPosterior(alg, prob, likelihood, priors, kwargs)
ChrisRackauckas marked this conversation as resolved.
Show resolved Hide resolved
println(typeof(transformations))
prob_transform(P::DynamicHMCPosterior) = as((transformations))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for as(...) here, that's the api for making transformations. I would just make the user to that and work with the transformation object from then on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I felt this would give a cleaner interface, this can be changed later on too though so I'll keep this in mind for sure.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I am saying is that defining a function just for the sole purpose of returning the transformations makes little sense. I would do something like

function dynamichmc_inference(prob::DiffEqBase.DEProblem, alg, likelihood, priors, transformations;
                              ϵ=0.001, initial=Float64[], num_samples=1000,
                              kwargs...)
    P = DynamicHMCPosterior(alg, prob, likelihood, priors, kwargs)
    PT = TransformedLogDensity(transformations, P)
    PTG = FluxGradientLogDensity(PT);

    chain, NUTS_tuned = NUTS_init_tune_mcmc(PTG,num_samples, ϵ=ϵ)
    posterior = transform.(Ref(PTG.transformation), get_position.(chain));

    return posterior, chain, NUTS_tuned
end

instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see.

PT = TransformedLogDensity(prob_transform(P), P)
PTG = FluxGradientLogDensity(PT);

transformations_tuple = Tuple(transformations)
parameter_transformation = TransformationTuple(transformations_tuple) # assuming a > 0
PT = TransformLogLikelihood(P, parameter_transformation)
PTG = ForwardGradientWrapper(PT, zeros(length(priors)));

lower_bound = Float64[]
upper_bound = Float64[]

for i in priors
push!(lower_bound, minimum(i))
push!(upper_bound, maximum(i))
end
# lower_bound = Float64[]
# upper_bound = Float64[]

# If no initial position is given use local minimum near expectation of priors.
if length(initial) == 0
for i in priors
push!(initial, mean(i))
end
initial_opt = Optim.minimizer(optimize(a -> -P(a),lower_bound,upper_bound,initial,Fminbox(GradientDescent())))
end
# for i in priors
# push!(lower_bound, minimum(i))
# push!(upper_bound, maximum(i))
# end

initial_inverse_transformed = Float64[]
for i in 1:length(initial_opt)
para = TransformationTuple(transformations[i])
push!(initial_inverse_transformed,inverse(para, (initial_opt[i], ))[1])
end
#println(initial_inverse_transformed)
sample, NUTS_tuned = NUTS_init_tune_mcmc(PTG,
initial_inverse_transformed,
num_samples, ϵ=ϵ)
# # If no initial position is given use local minimum near expectation of priors.
# if length(initial) == 0
# for i in priors
# push!(initial, mean(i))
# end
# initial_opt = Optim.minimizer(optimize(a -> -P(a),lower_bound,upper_bound,initial,Fminbox(GradientDescent())))
# end

posterior = ungrouping_map(Vector, get_transformation(PT) ∘ get_position, sample)
# initial_inverse_transformed = Float64[]
# for i in 1:length(initial_opt)
# para = TransformationTuple(transformations[i])
# push!(initial_inverse_transformed,inverse(para, (initial_opt[i], ))[1])
# end
# #println(initial_inverse_transformed)
chain, NUTS_tuned = NUTS_init_tune_mcmc(PTG,num_samples, ϵ=ϵ)
posterior = transform.(Ref(PTG.transformation), get_position.(chain));
ChrisRackauckas marked this conversation as resolved.
Show resolved Hide resolved

return posterior, sample, NUTS_tuned
return posterior, chain, NUTS_tuned
end
2 changes: 1 addition & 1 deletion src/stan_inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function stan_inference(prob::DiffEqBase.DEProblem,t,data,priors = nothing;alg=:
setup_params = string(setup_params,"row_vector<lower=0>[$length_of_y] sigma$(i-1);")
end
end
tuple_hyper_params = tuple_hyper_params[1:endof(tuple_hyper_params)-1]
tuple_hyper_params = tuple_hyper_params[1:length(tuple_hyper_params)-1]
differential_equation = generate_differential_equation(f)
priors_string = string(generate_priors(f,priors))
stan_likelihood = stan_string(likelihood)
Expand Down
12 changes: 6 additions & 6 deletions test/dynamicHMC.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using DiffEqBayes, OrdinaryDiffEq, ParameterizedFunctions, RecursiveArrayTools
using DynamicHMC, DiffWrappers, ContinuousTransformations
using DynamicHMC, TransformVariables
using Parameters, Distributions, Optim

f1 = @ode_def_nohes LotkaVolterraTest1 begin
f1 = @ode_def LotkaVolterraTest1 begin
dx = a*x - x*y
dy = -3*y + x*y
end a
Expand All @@ -16,8 +16,8 @@ t = collect(range(1,stop=10,length=10)) # observation times
sol = solve(prob1,Tsit5())
randomized = VectorOfArray([(sol(t[i]) + σ * randn(2)) for i in 1:length(t)])
data = convert(Array,randomized)

bayesian_result = dynamichmc_inference(prob1, Tsit5(), t, data, [Normal(1.5, 1)], [bridge(ℝ, ℝ⁺, )])
transform = (a = asℝ₊)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this need a , to make a (named) tuple, ie (a = asℝ₊, ).

bayesian_result = dynamichmc_inference(prob1, Tsit5(), t, data, [Normal(1.5, 1)], transform)
@test mean(bayesian_result[1][1]) ≈ 1.5 atol=1e-1

# With hand-code likelihood function
Expand All @@ -33,11 +33,11 @@ likelihood = function (sol)
end
return l
end
bayesian_result = dynamichmc_inference(prob1, Tsit5(), likelihood, [Truncated(Normal(1.5, 1), 0, 2)], [bridge(ℝ, ℝ⁺, )])
bayesian_result = dynamichmc_inference(prob1, Tsit5(), likelihood, [Truncated(Normal(1.5, 1), 0, 2)])
@test mean(bayesian_result[1][1]) ≈ 1.5 atol=1e-1


f1 = @ode_def_nohes LotkaVolterraTest4 begin
f1 = @ode_def LotkaVolterraTest4 begin
dx = a*x - b*x*y
dy = -c*y + d*x*y
end a b c d
Expand Down
4 changes: 2 additions & 2 deletions test/stan.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using DiffEqBayes, OrdinaryDiffEq, ParameterizedFunctions,
RecursiveArrayTools, Distributions, Test

println("One parameter case")
f1 = @ode_def_nohes LotkaVolterraTest1 begin
f1 = @ode_def LotkaVolterraTest1 begin
dx = a*x - x*y
dy = -3y + x*y
end a
Expand All @@ -25,7 +25,7 @@ theta1 = bayesian_result.chain_results[:,["theta.1"],:]


println("Four parameter case")
f1 = @ode_def_nohes LotkaVolterraTest4 begin
f1 = @ode_def LotkaVolterraTest4 begin
dx = a*x - b*x*y
dy = -c*y + d*x*y
end a b c d
Expand Down