-
-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Implementation of a Levenberg–Marquardt algorithm #131
Conversation
Codecov Report
@@ Coverage Diff @@
## master #131 +/- ##
==========================================
+ Coverage 88.79% 90.89% +2.09%
==========================================
Files 6 7 +1
Lines 348 494 +146
==========================================
+ Hits 309 449 +140
- Misses 39 45 +6
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
src/ad.jl
Outdated
@@ -26,7 +26,7 @@ end | |||
function SciMLBase.solve(prob::NonlinearProblem{<:Union{Number, StaticArraysCore.SVector}, | |||
iip, | |||
<:Dual{T, V, P}}, | |||
alg::Union{NewtonRaphson, TrustRegion}, | |||
alg::Union{NewtonRaphson, TrustRegion, LevenbergMarquardt}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alg::Union{NewtonRaphson, TrustRegion, LevenbergMarquardt}, | |
alg::AbstractNewtonAlgorithm, |
src/ad.jl
Outdated
@@ -35,7 +35,8 @@ end | |||
function SciMLBase.solve(prob::NonlinearProblem{<:Union{Number, StaticArraysCore.SVector}, | |||
iip, | |||
<:AbstractArray{<:Dual{T, V, P}}}, | |||
alg::Union{NewtonRaphson, TrustRegion}, args...; | |||
alg::Union{NewtonRaphson, TrustRegion, LevenbergMarquardt}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alg::Union{NewtonRaphson, TrustRegion, LevenbergMarquardt}, | |
alg::AbstractNewtonAlgorithm, |
src/levenberg.jl
Outdated
cache.v = -(JᵀJ .+ λ .* DᵀD) \ mul!(cache.du_tmp, J', fu) | ||
|
||
# Geodesic acceleration (step_size = v + a / 2). | ||
@unpack v, alg = cache | ||
h = alg.finite_diff_step_geodesic | ||
f(cache.fu_tmp, u .+ h .* v, p) | ||
cache.a = -J \ ((2 / h) .* ((cache.fu_tmp .- fu) ./ h .- mul!(cache.du_tmp, J, v))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two \
's should be changed to linsolve
handlings.
src/levenberg.jl
Outdated
@unpack u, p, λ, JᵀJ, DᵀD, J = cache | ||
|
||
# Usual Levenberg-Marquardt step ("velocity"). | ||
cache.v = -(JᵀJ .+ λ .* DᵀD) \ mul!(cache.du_tmp, J', fu) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-(JᵀJ .+ λ .* DᵀD)
should be put into a temporary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mul!(cache.du_tmp, J', fu)
I'd move that to a different line for clarity. Though it returns cache.du_tmp
in most dispatches, it's usually best to mutate in one line and then use in the next
Edit: |
Testing to remove the precompilation of |
Think I've found the issue from #128. |
linres = dolinsolve(alg.precs, linsolve, A = cache.mat_tmp, b = _vec(cache.fu_tmp), | ||
linu = _vec(cache.du_tmp), p = p, reltol = cache.abstol) | ||
cache.linsolve = linres.cache | ||
@. cache.v = -cache.du_tmp | ||
|
||
# Geodesic acceleration (step_size = v + a / 2). | ||
@unpack v, alg = cache | ||
h = alg.finite_diff_step_geodesic | ||
f(cache.fu_tmp, u .+ h .* v, p) | ||
|
||
# The following lines do: cache.a = -J \ cache.fu_tmp | ||
mul!(cache.du_tmp, J, v) | ||
@. cache.fu_tmp = (2 / h) * ((cache.fu_tmp - fu) / h - cache.du_tmp) | ||
linres = dolinsolve(alg.precs, linsolve, A = J, b = _vec(cache.fu_tmp), | ||
linu = _vec(cache.du_tmp), p = p, reltol = cache.abstol) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to split the preconditioners between these two. But that's for follow up.
This looks good for a first pass. More to be done, but we should split correctness from improvements. |
Forward Mode overloads for Least Squares Problem
Implementation of a Levenberg–Marquardt algorithm #119, according to the paper Improvements to the Levenberg-Marquardt algorithm for nonlinear least-squares minimization.
The solver in
raphson.jl
was used as a template for this solver.