AccessibleOptimization.jl
Combining Accessors.jl
+ Optimization.jl
to enable function optimization with arbitrary structs. Vary struct parameters, combinations and transformations of them. Uniform and composable, zero overhead.
Defining features of AccessibleOptimization
:
- No need to deal with raw vectors of optimized parameters: their values are automatically put into model structs
- Can use arbitrary structs as model definitions, no requirements or limitations on their content, types, or methods
- Can flexibly specify the list of parameters to optimize, as well as their bounds and constrains - independently of the model struct/object creation
- Everything is type-stable and performant
Usage
Suppose you want to fit a model to data. Here, our model is a sum of squared exponentials.
First, define your model and a way to evaluate it. Regular Julia code, no special types or functions. This is not Accessors
/Optimization
specific at all, you may have model definitions already!
struct ExpModel{A,B}
scale::A
shift::B
end
struct SumModel{T <: Tuple}
comps::T
end
(m::ExpModel)(x) = m.scale * exp(-(x - m.shift)^2)
(m::SumModel)(x) = sum(c -> c(x), m.comps)
loss(m, data) = @p data |> sum(abs2(_.y - m(_.x)))
Then, load AccessibleOptimization
, define optimization parameters, and perform optimization:
using AccessibleOptimization
# which parameters to optimize, what are their bouds?
vars = OptArgs(
@optic(_.comps[∗].shift) => 0..10., # shifts of both components: values from 0..10
@optic(log10(_.comps[∗].scale)) => -1..1, # component scales: positive-only (using log10 transformation), from 10^-1 to 10^1
)
# create and solve the optimization problem, interface very similar to Optimization.jl
ops = OptProblemSpec(Base.Fix2(loss, data), mod0, vars)
sol = solve(ops, ECA(), maxiters=300)
sol.uobj::SumModel # the optimal model
See also a walkthrough, with more examples and details.
Related packages
AccessibleOptimization
gains its composability and generality powers (and half its name!) from Accessors
and AccessorsExtra
packages.
The optimization part is directly delegated to Optimization
. Other backends are possible, but best to add them as methods to Optimization
proper and use from AccessibleOptimization
.
These packages have generally similar goals, but neither provides all features AccessibleOptimization
or Accessors
do: