@@ -2,65 +2,34 @@ module BayesianOptimization
22import NLopt, GaussianProcesses
33import GaussianProcesses: GPBase, GPE
44import ElasticPDMats: ElasticPDMat
5- using ForwardDiff, DiffResults, Random, Dates, SpecialFunctions
5+ using ForwardDiff, DiffResults, Random, Dates, SpecialFunctions, TimerOutputs
66export BOpt, ExpectedImprovement, ProbabilityOfImprovement, UpperConfidenceBound,
77ThompsonSamplingSimple, MutualInformation, boptimize!, MLGPOptimizer, NoOptimizer,
88Min, Max, BrochuBetaScaling, NoBetaScaling, Silent, Timings, Progress
99
10+ ENABLE_TIMINGS = true
1011
11- mutable struct IterationCounter
12- c:: Int
13- i:: Int
14- N:: Int
15- end
16- isdone(s:: IterationCounter ) = s. c == s. N
17- step!(s:: IterationCounter ) = (s. c += 1 ; s. i += 1 )
18- init!(s:: IterationCounter ) = s. c = 0
19- mutable struct DurationCounter
20- starttime:: Float64
21- duration:: Float64
22- now:: Float64
23- endtime:: Float64
24- end
25- function init!(s:: DurationCounter )
26- s. starttime = time()
27- s. endtime = s. starttime + s. duration
28- end
29- isdone(s:: DurationCounter ) = (s. now = time()) >= s. endtime
3012abstract type ModelOptimizer end
31- mutable struct MLGPOptimizer{NT} <: ModelOptimizer
32- i:: Int
33- every:: Int
34- options:: NT
35- end
36- """
37- MLGPOptimizer(; every = 10, kwargs...)
38-
39- Set the GP hyperparameters to the maximum likelihood estimate `every` number of steps.
40- """
41- MLGPOptimizer(; every = 10 , kwargs... ) = MLGPOptimizer(0 , every, kwargs. data)
42- function optimizemodel!(o:: MLGPOptimizer , model:: GPBase )
43- if o. i % o. every == 0
44- optimizemodel!(model; o. options... )
45- end
46- o. i += 1
47- end
48-
4913"""
5014Don't optimize the model ever.
5115"""
5216struct NoModelOptimizer <: ModelOptimizer end
5317optimizemodel!(o:: NoModelOptimizer , model) = Nothing
5418
19+ include(" utils.jl" )
20+ include(" acquisitionfunctions.jl" )
21+ include(" acquisition.jl" )
22+ include(" models/gp.jl" )
23+
5524@enum Sense Min= - 1 Max= 1
5625@enum Verbosity Silent= 0 Timings= 1 Progress= 2
5726
58- mutable struct BOpt{F,M,A,MO}
27+ mutable struct BOpt{F,M,A,AO, MO}
5928 func:: F
6029 sense:: Sense
6130 model:: M
6231 acquisition:: A
63- acquisitionoptions:: NamedTuple
32+ acquisitionoptions:: AO
6433 modeloptimizer:: MO
6534 lowerbounds:: Array{Float64, 1}
6635 upperbounds:: Array{Float64, 1}
@@ -73,34 +42,35 @@ mutable struct BOpt{F,M,A,MO}
7342 opt:: NLopt.Opt
7443 verbosity:: Verbosity
7544 lhs_iterations:: Int
45+ repetitions:: Int
46+ timeroutput:: TimerOutput
7647end
77- isdone(o:: BOpt ) = isdone(o. iterations) || isdone(o. duration)
7848"""
7949 BOpt(func, model, acquisition, modeloptimizer, lowerbounds, upperbounds;
8050 sense = Max, maxiterations = 10^4, maxduration = Inf,
81- acquisitionoptions = NamedTuple(), gradientfree = false ,
51+ acquisitionoptions = NamedTuple(), repetitions = 1 ,
8252 verbosity = Progress, lhs_iterations = 5*length(lowerbounds))
8353"""
8454function BOpt(func, model, acquisition, modeloptimizer, lowerbounds, upperbounds;
8555 sense = Max, maxiterations = 10 ^ 4 , maxduration = Inf ,
86- acquisitionoptions = NamedTuple(), gradientfree = false ,
87- verbosity = Progress, lhs_iterations = 5 * length(lowerbounds))
88- if gradientfree
89- default_acquisitionoptions = (method = :GN_DIRECT_L, restarts = 1 , maxeval = 500 )
90- else
91- default_acquisitionoptions = (method = :LD_LBFGS, restarts = 10 , maxeval = 500 )
92- end
93- acquisitionoptions = merge(default_acquisitionoptions, acquisitionoptions)
56+ acquisitionoptions = NamedTuple(),
57+ repetitions = 1 , verbosity = Progress,
58+ lhs_iterations = 5 * length(lowerbounds))
9459 now = time()
95- BOpt(func, sense, model, acquisition, acquisitionoptions,
60+ acquisitionoptions = merge(defaultoptions(typeof(model), typeof(acquisition)),
61+ acquisitionoptions)
62+ maxiterations < lhs_iterations && @error(" maxiterations = $maxiterations < lhs_iterations = $lhs_iterations " )
63+ BOpt(func, sense, model, acquisition,
64+ acquisitionoptions,
9665 modeloptimizer, lowerbounds, upperbounds,
9766 - Inf64 * Int(sense), Array{Float64}(undef, length(lowerbounds)),
9867 - Inf64 * Int(sense), Array{Float64}(undef, length(lowerbounds)),
9968 IterationCounter(0 , 0 , maxiterations),
10069 DurationCounter(now, maxduration, now, now + maxduration),
10170 NLopt. Opt(acquisitionoptions. method, length(lowerbounds)),
102- verbosity, lhs_iterations)
71+ verbosity, lhs_iterations, repetitions, TimerOutput() )
10372end
73+ isdone(o:: BOpt ) = isdone(o. iterations) || isdone(o. duration)
10474import Base: show
10575function show(io:: IO , mime:: MIME"text/plain" , o:: BOpt )
10676 println(io, " Bayesian Optimization object\n\n model:" )
@@ -119,54 +89,52 @@ function show(io::IO, mime::MIME"text/plain", o::BOpt)
11989 end
12090end
12191
122- sample(lowerbounds, upperbounds) =
123- rand(length(lowerbounds)) .* (upperbounds .- lowerbounds) .+ lowerbounds
124-
12592function initialise_model!(o)
126- dac = @elapsed x = latin_hypercube_sampling(o. lowerbounds, o. upperbounds,
127- o. lhs_iterations)
128- dfunc = @elapsed y = Int(o. sense) .* o. func.([x[:, i] for i in 1 : size(x, 2 )])
129- o. iterations. i = o. iterations. c = length(y)
130- dmu = @elapsed update!(o. model, x, y)
131- dom = @elapsed optimizemodel!(o. modeloptimizer, o. model)
132- o. opt = nlopt_setup(o. acquisition, o. model, o. lowerbounds, o. upperbounds;
133- o. acquisitionoptions... )
134- dac, dfunc, dmu, dom
93+ @mytimeit o. timeroutput " acquisition" x = latin_hypercube_sampling(o. lowerbounds, o. upperbounds, o. lhs_iterations)
94+ y = Float64[]
95+ for i in 1 : size(x, 2 )
96+ for j in 1 : o. repetitions
97+ @mytimeit o. timeroutput " function evaluation" push!(y, Int(o. sense) * o. func(x[:, i]))
98+ end
99+ end
100+ o. iterations. i = o. iterations. c = length(y)/ o. repetitions
101+ @mytimeit o. timeroutput " model update" update!(o. model,
102+ hcat(hcat([fill(x[:, i], o. repetitions) for i in 1 : size(x, 2 )]. .. ). .. ),
103+ y)
104+ @mytimeit o. timeroutput " model hyperparameter optimization" optimizemodel!(o. modeloptimizer, o. model)
105+ o. opt = nlopt_setup(o. acquisition, o. model, o. lowerbounds, o. upperbounds,
106+ o. acquisitionoptions)
135107end
136108"""
137109 boptimize!(o::BOpt)
138110"""
139111function boptimize!(o:: BOpt )
140112 init!(o. duration)
141113 init!(o. iterations)
142- dfunc = dom = dac = dmu = 0.
143- if o. iterations. i == 0 dac, dfunc, dmu, dom = initialise_model!(o) end
114+ reset_timer!(o . timeroutput)
115+ o. iterations. i == 0 && initialise_model!(o)
144116 while ! isdone(o)
145117 o. verbosity >= Progress && @info(" $(now()) \t iteration: $(o. iterations. i) \t current optimum: $(o. observed_optimum) " )
146118 setparams!(o. acquisition, o. model)
147- dac += @elapsed f, x = acquire_max(o. opt, o. lowerbounds, o. upperbounds,
148- o. acquisitionoptions. restarts)
149- dfunc += @elapsed y = Int(o. sense) * o. func(x)
119+ @mytimeit o. timeroutput " acquisition" f, x = acquire_max(o. opt, o. lowerbounds, o. upperbounds, o. acquisitionoptions. restarts)
120+ ys = Float64[]
150121 step!(o. iterations)
151- if y > Int(o. sense) * o. observed_optimum
152- o. observed_optimum = Int(o. sense) * y
153- o. observed_optimizer = x
122+ for _ in 1 : o. repetitions
123+ @mytimeit o. timeroutput " function evaluation" y = Int(o. sense) * o. func(x)
124+ push!(ys, y)
125+ if y > Int(o. sense) * o. observed_optimum
126+ o. observed_optimum = Int(o. sense) * y
127+ o. observed_optimizer = x
128+ end
154129 end
155- dmu += @elapsed update!(o. model, x, y )
156- dom += @elapsed optimizemodel!(o. modeloptimizer, o. model)
130+ @mytimeit o . timeroutput " model update" update !(o. model, hcat(fill( x, o . repetitions) . .. ), ys )
131+ @mytimeit o . timeroutput " model hyperparameter optimization " optimizemodel!(o. modeloptimizer, o. model)
157132 end
133+ @mytimeit o. timeroutput " acquisition" o. model_optimum, o. model_optimizer = acquire_model_max(o)
158134 o. duration. now = time()
159- o. verbosity >= Timings && @info(" time spent for:
160- function evaluation \t $dfunc s
161- model update \t\t $dmu s
162- model optimization \t $dom s
163- acquisition \t\t $dac s" )
164- dom += @elapsed o. model_optimum, o. model_optimizer = acquire_model_max(o, restarts = 10 , maxeval = 2000 )
135+ o. verbosity >= Timings && @info(o. timeroutput)
165136 (observerd_optimum = o. observed_optimum, observed_optimizer = o. observed_optimizer,
166137 model_optimum = Int(o. sense) * o. model_optimum, model_optimizer = o. model_optimizer)
167138end
168139
169- include(" acquisition.jl" )
170- include(" models/gp.jl" )
171-
172140end # module
0 commit comments