Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ makedocs(
"Adam and AdaMax" => "algo/adam_adamax.md",
"Conjugate Gradient" => "algo/cg.md",
"Gradient Descent" => "algo/gradientdescent.md",
"Accelerated and Momentum Gradient Descent" => "algo/accelerated_gradient_descent.md",
"(L-)BFGS" => "algo/lbfgs.md",
"L-BFGS-B (box constrained)" => "algo/lbfgsb.md",
"Acceleration" => "algo/ngmres.md",
Expand Down
10 changes: 10 additions & 0 deletions docs/src/algo/accelerated_gradient_descent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Accelerated and Momentum Gradient Descent

`AcceleratedGradientDescent` and `MomentumGradientDescent` are first-order methods for
unconstrained objectives with an available gradient. Both use a line search and accept
the same `alphaguess`, `linesearch`, and `manifold` keyword arguments.

```@docs
AcceleratedGradientDescent
MomentumGradientDescent
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,36 @@ end

Base.summary(io::IO, ::AcceleratedGradientDescent) = print(io, "Accelerated Gradient Descent")

"""
AcceleratedGradientDescent(; alphaguess = LineSearches.InitialPrevious(),
linesearch = LineSearches.HagerZhang(), manifold = Flat())

Construct a first-order optimizer using Nesterov-style accelerated gradient descent.
The method takes a line-search step from an extrapolated iterate and updates that iterate
from the current and previous accepted points. Use it with `optimize` on an unconstrained
objective for which a gradient is available.

# Arguments
- `alphaguess`: Initial step-length strategy. A `Real` is converted to a static initial
step length; otherwise it must be compatible with `LineSearches`.
- `linesearch`: Line-search method used to choose each step length.
- `manifold`: Manifold on which iterates are retracted and gradients are projected.
The default, `Flat()`, solves an unconstrained Euclidean problem.

# Example
```julia
julia> using Optim

julia> f(x) = sum(abs2, x);

julia> g!(storage, x) = (storage .= 2 .* x);

julia> result = optimize(f, g!, [1.0, -1.0], AcceleratedGradientDescent());

julia> Optim.converged(result)
true
```
"""
function AcceleratedGradientDescent(;
alphaguess = LineSearches.InitialPrevious(), # TODO: investigate good defaults
linesearch = LineSearches.HagerZhang(), # TODO: investigate good defaults
Expand Down
33 changes: 33 additions & 0 deletions src/multivariate/solvers/first_order/momentum_gradient_descent.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,39 @@ end

Base.summary(io::IO, ::MomentumGradientDescent) = print(io, "Momentum Gradient Descent")

"""
MomentumGradientDescent(; mu = 0.01,
alphaguess = LineSearches.InitialPrevious(),
linesearch = LineSearches.HagerZhang(), manifold = Flat())

Construct a first-order optimizer that adds a momentum term to each gradient-descent
step. The next iterate combines the negative gradient with the displacement between the
two previous accepted iterates. Use it with `optimize` on an unconstrained objective for
which a gradient is available.

# Arguments
- `mu`: Momentum coefficient. `mu = 0` removes the momentum contribution and yields
line-search gradient descent.
- `alphaguess`: Initial step-length strategy. A `Real` is converted to a static initial
step length; otherwise it must be compatible with `LineSearches`.
- `linesearch`: Line-search method used to choose each step length.
- `manifold`: Manifold on which iterates are retracted and gradients are projected.
The default, `Flat()`, solves an unconstrained Euclidean problem.

# Example
```julia
julia> using Optim

julia> f(x) = sum(abs2, x);

julia> g!(storage, x) = (storage .= 2 .* x);

julia> result = optimize(f, g!, [1.0, -1.0], MomentumGradientDescent(mu = 0.1));

julia> Optim.converged(result)
true
```
"""
function MomentumGradientDescent(;
mu::Real = 0.01,
alphaguess = LineSearches.InitialPrevious(), # TODO: investigate good defaults
Expand Down
8 changes: 8 additions & 0 deletions test/general/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
@test Optim.minimum !== minimum
@test Optim.maximum !== maximum

@testset "first-order optimizer documentation" begin
for optimizer in (AcceleratedGradientDescent, MomentumGradientDescent)
binding = Base.Docs.Binding(Optim, Symbol(optimizer))
@test haskey(Base.Docs.meta(Optim), binding)
@test occursin(string(optimizer), sprint(show, Base.Docs.meta(Optim)[binding]))
end
end

rosenbrock = MultivariateProblems.UnconstrainedProblems.examples["Rosenbrock"]
f = MVP.objective(rosenbrock)
g! = MVP.gradient(rosenbrock)
Expand Down
Loading