Is it possible to pass a struct of parameters as an argument to an optimizer? The example below estimates an OLS model in which the intercept and slope are passed a vector p
.
function ssr(y,x,p)
return sum((y .- (p[1] .+ p[2] .* x)).^2)
end
x1 = cumsum(ones(10))
y1 = 2 .+ 3 .* x1 .+ rand(10)
Optim.minimizer(optimize(p->ssr(y1,x1,p), ones(2)))
Is it possible to instead pass the intercept and slope as a struct?
struct ols_struct
intercept::Float64
slope::Float64
end
p = ols_struct(1,1)
Most optimizers expect a vector of unknowns, but you can just wrap an anonymous function around your struct p -> ols_struct(p[1], p[2])
.
Most optimizers require flat arrays, but there are some options to pass more structured data instead:
function nice_ssr(y, x, p)
sum(@. (y - (p.intercept + p.slope * x))^2)
end
ComponentArrays.jl which allows to treat (nested) named tuples as flat vectors
using ComponentArrays
p0 = ComponentArray(intercept = 1.0, slope = 1.0)
optimize(p -> nice_ssr(y1, x1, p), p0)
or if you prefer using structs, Functors.jl which help in converting between (nested) structs and flat vectors:
using Functors
@functor ols_struct
_, rebuild = Functors.functor(ols_struct(1.0, 1.0))
optimize(x -> nice_ssr(y1, x1, rebuild(x)), ones(2))