Skip to content

Commit

Permalink
Fix Continuation method bug and further optimise ProgressMeter use
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelTrent committed Jun 28, 2023
1 parent 51716d8 commit 0e9f956
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 68 deletions.
53 changes: 37 additions & 16 deletions src/bivariate_methods/bivariate_profile_likelihood.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,31 +164,33 @@ function bivariate_confidenceprofile(bivariate_optimiser::Function,
consistent, ind1, ind2,
model.core.num_pars, initGuess,
θranges, ωranges)

put!(channel, true)

elseif method isa Fix1AxisMethod
boundary, internal = bivariate_confidenceprofile_fix1axis(
bivariate_optimiser, model,
num_points, consistent, ind1, ind2,
mle_targetll, save_internal_points)
mle_targetll, save_internal_points, channel)

elseif method isa SimultaneousMethod
boundary, internal = bivariate_confidenceprofile_vectorsearch(
bivariate_optimiser, model,
num_points, consistent, ind1, ind2,
mle_targetll, save_internal_points)
mle_targetll, save_internal_points, channel)

elseif method isa RadialRandomMethod
boundary, internal = bivariate_confidenceprofile_vectorsearch(
bivariate_optimiser, model,
num_points, consistent, ind1, ind2,
mle_targetll, save_internal_points,
mle_targetll, save_internal_points, channel,
num_radial_directions=method.num_radial_directions)

elseif method isa RadialMLEMethod
boundary, internal = bivariate_confidenceprofile_vectorsearch(
bivariate_optimiser, model,
num_points, consistent, ind1, ind2,
mle_targetll, save_internal_points,
mle_targetll, save_internal_points, channel,
ellipse_confidence_level=0.1,
ellipse_start_point_shift=method.ellipse_start_point_shift,
ellipse_sqrt_distortion=method.ellipse_sqrt_distortion)
Expand All @@ -202,7 +204,7 @@ function bivariate_confidenceprofile(bivariate_optimiser::Function,
method.ellipse_start_point_shift,
method.num_level_sets,
method.level_set_spacing,
mle_targetll, save_internal_points)
mle_targetll, save_internal_points, channel)

elseif method isa IterativeBoundaryMethod
boundary, internal = bivariate_confidenceprofile_iterativeboundary(
Expand All @@ -211,10 +213,9 @@ function bivariate_confidenceprofile(bivariate_optimiser::Function,
method.initial_num_points, method.angle_points_per_iter,
method.edge_points_per_iter, method.radial_start_point_shift,
method.ellipse_sqrt_distortion, method.use_ellipse,
mle_targetll, save_internal_points)
mle_targetll, save_internal_points, channel)
end

put!(channel, true)

return BivariateConfidenceStruct(boundary, internal)
catch
@error string("an error occurred when finding the bivariate boundary with settings: ",
Expand All @@ -230,6 +231,16 @@ function bivariate_confidenceprofile(bivariate_optimiser::Function,
return nothing
end

function get_bivariate_method_tasknumbers(method::AbstractBivariateMethod, num_points::Int)
if method isa ContinuationMethod
return num_points * method.num_level_sets
elseif method isa AnalyticalEllipseMethod
return 1
else
return num_points
end
end

"""
bivariate_confidenceprofiles!(model::LikelihoodModel,
θcombinations::Vector{Vector{Int}},
Expand Down Expand Up @@ -262,6 +273,10 @@ Finds `num_points` `profile_type` boundary points at a specified `confidence_lev
# Details
Using [`bivariate_confidenceprofile`](@ref) this function calls the algorithm/method specified by `method` for each parameter combination in `θcombinations` (depending on the setting for `existing_profiles` and `num_points` if these profiles already exist). Updates `model.biv_profiles_df` for each successful profile and saves their results as a [`BivariateConfidenceStruct`](@ref) in `model.biv_profiles_dict`, where the keys for the dictionary is the row number in `model.biv_profiles_df` of the corresponding profile.
## Iteration Speed Of the Progress Meter
The time/it value is the time it takes for each new boundary point to be found (for all methods except for [`AnalyticalEllipseMethod`](@ref) and [`ContinuationMethod`](@ref)). For [`AnalyticalEllipseMethod`](@ref) this is the time it takes to find all points on the boundary of the ellipse of two interest parameters. For [`ContinuationMethod`](@ref) this is the time it takes to find each new point, internal or on the boundary.
"""
function bivariate_confidenceprofiles!(model::LikelihoodModel,
θcombinations::Vector{Vector{Int}},
Expand Down Expand Up @@ -355,9 +370,14 @@ function bivariate_confidenceprofiles!(model::LikelihoodModel,
len_θcombinations = length(θcombinations)
len_θcombinations > 0 || return nothing


channel = RemoteChannel(() -> Channel{Bool}(1))
p = Progress(length(θcombinations); desc="Computing bivariate profiles: ",


tasks_per_profile = get_bivariate_method_tasknumbers(method, num_points)
totaltasks = tasks_per_profile * len_θcombinations
# channel_buffer_size = min(ceil(Int, tasks_per_profile * 0.05), 30)
channel_buffer_size = 2
channel = RemoteChannel(() -> Channel{Bool}(channel_buffer_size))
p = Progress(totaltasks; desc="Computing bivariate profiles: ",
dt=PROGRESS__METER__DT, enabled=show_progress, showspeed=true)

@sync begin
Expand All @@ -368,11 +388,12 @@ function bivariate_confidenceprofiles!(model::LikelihoodModel,
if use_distributed
@async begin
profiles_to_add = @distributed (vcat) for i in 1:len_θcombinations
[((θcombinations[i][1], θcombinations[i][2]), bivariate_confidenceprofile(bivariate_optimiser, model, num_new_points[i],
confidence_level, consistent,
θcombinations[i][1], θcombinations[i][2], profile_type,
method, mle_targetll,
save_internal_points, channel))]
[((θcombinations[i][1], θcombinations[i][2]),
bivariate_confidenceprofile(bivariate_optimiser, model, num_new_points[i],
confidence_level, consistent,
θcombinations[i][1], θcombinations[i][2], profile_type,
method, mle_targetll,
save_internal_points, channel))]
end
put!(channel, false)

Expand Down
34 changes: 23 additions & 11 deletions src/bivariate_methods/continuation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ function continuation_line_search!(p::NamedTuple,
target_confidence_ll::Float64,
search_directions::Matrix{Float64},
start_level_set_2D::Matrix{Float64},
channel::RemoteChannel;
start_level_set_all::Matrix{Float64}=zeros(0,0),
level_set_not_smoothed::Bool=true;
level_set_not_smoothed::Bool=true,
is_a_zero::BitVector=falses(num_points))

start_have_all_pars = !isempty(start_level_set_all)
Expand Down Expand Up @@ -146,6 +147,7 @@ function continuation_line_search!(p::NamedTuple,
if !biv_opt_is_ellipse_analytical
variablemapping!(@view(target_level_set_all[:, i]), p.ω_opt, p.θranges, p.ωranges)
end
put!(channel, true)
end

if biv_opt_is_ellipse_analytical
Expand Down Expand Up @@ -190,7 +192,8 @@ function continuation_inwards_radial_search!(p::NamedTuple,
target_confidence_ll::Float64,
search_directions::Matrix{Float64},
start_level_set_2D::Matrix{Float64},
is_a_zero::BitVector)
is_a_zero::BitVector,
channel::RemoteChannel)

mle_point = model.core.θmle[[ind1, ind2]]

Expand Down Expand Up @@ -222,6 +225,7 @@ function continuation_inwards_radial_search!(p::NamedTuple,
bivariate_optimiser(ψ, p)
variablemapping!(@view(target_level_set_all[:, i]), p.ω_opt, p.θranges, p.ωranges)
end
put!(channel, true)
end

if biv_opt_is_ellipse_analytical
Expand Down Expand Up @@ -260,7 +264,8 @@ function initial_continuation_solution!(p::NamedTuple,
profile_type::AbstractProfileType,
ellipse_confidence_level::Float64,
target_confidence_ll::Float64,
ellipse_start_point_shift::Float64)
ellipse_start_point_shift::Float64,
channel::RemoteChannel)

check_ellipse_approx_exists!(model)

Expand Down Expand Up @@ -318,6 +323,7 @@ function initial_continuation_solution!(p::NamedTuple,
model,
num_points, ind1, ind2,
corrected_ll, search_directions, ellipse_points,
channel,
is_a_zero=is_a_zero
)
return a, b, search_directions, min_ll, point_is_on_bounds
Expand All @@ -329,7 +335,7 @@ function initial_continuation_solution!(p::NamedTuple,
a, b = continuation_inwards_radial_search!(p, bivariate_optimiser, model,
num_points, ind1, ind2,
corrected_ll, search_directions, ellipse_points,
is_a_zero)
is_a_zero, channel)
return a, b, search_directions, target_confidence_ll, point_is_on_bounds
end

Expand All @@ -338,8 +344,10 @@ function initial_continuation_solution!(p::NamedTuple,
is_a_zero[findfirst(ellipse_true_lls .== max_ll)] = true

@warn string("ellipse starting point for continuation with variables ", model.core.θnames[ind1], " and ", model.core.θnames[ind2]," intersects the smallest target confidence level set. Using a smaller ellipse confidence level is recommended")
a, b = continuation_inwards_radial_search!(p, bivariate_optimiser, model, num_points,
ind1, ind2, corrected_ll, search_directions, ellipse_points, is_a_zero)
a, b = continuation_inwards_radial_search!(p, bivariate_optimiser, model,
num_points, ind1, ind2,
corrected_ll, search_directions, ellipse_points,
is_a_zero, channel)
return a, b, search_directions, max_ll, point_is_on_bounds
end

Expand All @@ -360,6 +368,7 @@ function bivariate_confidenceprofile_continuation(bivariate_optimiser::Function,
level_set_spacing::Symbol,
mle_targetll::Float64,
save_internal_points::Bool,
channel::RemoteChannel
)

newLb, newUb, initGuess, θranges, ωranges = init_nuisance_parameters(model, ind1, ind2)
Expand Down Expand Up @@ -394,7 +403,7 @@ function bivariate_confidenceprofile_continuation(bivariate_optimiser::Function,
initial_continuation_solution!(p, bivariate_optimiser,
model, num_points, ind1, ind2, profile_type,
ellipse_confidence_level, initial_target_ll,
ellipse_start_point_shift)
ellipse_start_point_shift, channel)

# display(scatter(current_level_set_2D[1,:], current_level_set_2D[2,:], legend=false, markeropacity=0.4))

Expand All @@ -420,7 +429,9 @@ function bivariate_confidenceprofile_continuation(bivariate_optimiser::Function,
for (i, level_set_ll) in enumerate(level_set_lls)
if save_internal_points
internal_all = hcat(internal_all, current_level_set_all[:, .!point_is_on_bounds])
ll_values = vcat(ll_values, fill(i == 1 ? initial_ll : level_set_lls[i-1], length(point_is_on_bounds) - sum(point_is_on_bounds)))
ll_values = vcat(ll_values, fill(i == 1 ?
get_target_loglikelihood(model, initial_confidence_level, profile_type, 2) :
level_set_lls[i-1], length(point_is_on_bounds) - sum(point_is_on_bounds)))
end

# perform any desired manipulation of the polygon boundary or search directions
Expand All @@ -438,8 +449,9 @@ function bivariate_confidenceprofile_continuation(bivariate_optimiser::Function,
continuation_line_search!(p, point_is_on_bounds,
bivariate_optimiser,
model, num_points, ind1, ind2, level_set_ll, search_directions,
current_level_set_2D, current_level_set_all,
level_set_not_smoothed)
current_level_set_2D, channel,
start_level_set_all=current_level_set_all,
level_set_not_smoothed=level_set_not_smoothed)

if require_TSP_reordering
path = minimum_perimeter_polygon!(current_level_set_2D)[1:end-1]
Expand All @@ -448,7 +460,7 @@ function bivariate_confidenceprofile_continuation(bivariate_optimiser::Function,
end
end

if save_internal_points; ll_values .= ll_values .+ mle_targetll end
if save_internal_points; ll_values .= ll_values .- ll_correction(model, profile_type, 0.0) end

return current_level_set_all, PointsAndLogLikelihood(internal_all, ll_values)
end
11 changes: 8 additions & 3 deletions src/bivariate_methods/fix1axis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ function findNpointpairs_fix1axis!(p::NamedTuple,
j::Int,
mle_targetll::Float64,
save_internal_points::Bool,
biv_opt_is_ellipse_analytical::Bool)
biv_opt_is_ellipse_analytical::Bool,
channel::RemoteChannel)

x_vec, y_vec = zeros(num_points), zeros(2, num_points)
local internal_all = zeros(model.core.num_pars, save_internal_points ? num_points : 0)
Expand Down Expand Up @@ -44,6 +45,7 @@ function findNpointpairs_fix1axis!(p::NamedTuple,
break
end
end
put!(channel, true)
end

if save_internal_points
Expand Down Expand Up @@ -87,6 +89,7 @@ function findNpointpairs_fix1axis!(p::NamedTuple,
break
end
end
put!(channel, true)
end
end

Expand All @@ -102,7 +105,8 @@ function bivariate_confidenceprofile_fix1axis(bivariate_optimiser::Function,
ind1::Int,
ind2::Int,
mle_targetll::Float64,
save_internal_points::Bool)
save_internal_points::Bool,
channel::RemoteChannel)

newLb, newUb, initGuess, θranges, ωranges = init_nuisance_parameters(model, ind1, ind2)

Expand All @@ -126,7 +130,7 @@ function bivariate_confidenceprofile_fix1axis(bivariate_optimiser::Function,

x_vec, y_vec, internal, ll = findNpointpairs_fix1axis!(p, bivariate_optimiser, model,
N, i, j, mle_targetll, save_internal_points,
biv_opt_is_ellipse_analytical)
biv_opt_is_ellipse_analytical, channel)

for k in 1:N
count +=1
Expand All @@ -142,6 +146,7 @@ function bivariate_confidenceprofile_fix1axis(bivariate_optimiser::Function,
bivariate_optimiser(ψ_y1, p)
variablemapping!(@view(boundary[:, count]), p.ω_opt, θranges, ωranges)
end
put!(channel, true)
end

if save_internal_points
Expand Down
Loading

0 comments on commit 0e9f956

Please sign in to comment.