Skip to content

Add proximal gradient optimizers: FBS, FISTA, and FASTA - #427

Merged
rcurtin merged 35 commits into
mlpack:masterfrom
rcurtin:fbs
Sep 18, 2025
Merged

Add proximal gradient optimizers: FBS, FISTA, and FASTA#427
rcurtin merged 35 commits into
mlpack:masterfrom
rcurtin:fbs

Conversation

@rcurtin

@rcurtin rcurtin commented Jul 30, 2025

Copy link
Copy Markdown
Member

I implemented these a very long time ago but only just now got the okay to contribute them back.

This PR implements three new optimizers for ensmallen:

  • FBS: forward-backward splitting
  • FISTA: fast iterative shrinkage-thresholding algorithm
  • FASTA: fast adaptive shrinkage/thresholding algorithm

These are differentiable optimizers, sort of, but they are specifically made for a class of functions that consist of both a differentiable part and a non-differentiable part:

h(x) = f(x) + g(x)
 - f(x) is differentiable
 - g(x) is an arbitrary non-differentiable function!

This situation arises all over the place. For me, the interesting application is L1-constrained objective functions like this one:

argminᵦ ∑loss(xᵢ, yᵢ, β) + |β|₁

Here, the L1 penalty is not differentiable and is instead often solved with "proximal gradient" algorithms, that take a 'forward' step to improve the differentiable f(x) term, then a 'backward' step to ensure that the objective of the non-differentiable g(x) parameter did not increase too much. That backward step can also be called 'shrinkage'.

Inside of ensmallen, I implemented this type of constrained objective function by having the FBS, FISTA, and FASTA functions take both f(x) and g(x) separately. The classes L1Penalty and L1Constraint are implemented, and the documentation includes examples of how to do L1-regularized optimization with ensmallen. It looks like this:

  // Construct the objective function f(x), and the penalty function g(x) with a
  // lambda value of 0.1.
  LinearRegressionEWGFunction lrf(data, responses);
  ens::L1Penalty g(0.1);

  // Create the FBS optimizer with default parameters, and optimize the function
  // f(x) + g(x) (i.e. L1-penalized linear regression).
  // The ens::FBS class can be replaced with any ensmallen proximal gradient
  // optimizer.
  ens::FBS fbs(g);
  arma::mat lrfParams(startingPoint);
  fbs.Optimize(lrf, lrfParams);

Originally, my aim was to implement newGLMNET, another proximal gradient optimizer (it is what is inside LIBLINEAR), and then compare whether ensmallen's newGLMNET was better or worse than these three optimizers for learning L1-constrained logistic regression models. However, that project was never completed and funding situation changes mean it's on indefinite hold (honestly speaking I am unlikely to ever return to that effort). At the same time, these three optimizers are tested and ready to go.

@rcurtin

rcurtin commented Jul 30, 2025

Copy link
Copy Markdown
Member Author

Just to add, I would rather merge #425 and #426 first, and then rebase this PR on those changes, which will be a little tedious but only a little.

@github-actions github-actions Bot removed the s: stale label Sep 13, 2025

@coatless coatless left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rcurtin minor nit: missing a HISTORY.md entry.

@rcurtin

rcurtin commented Sep 16, 2025

Copy link
Copy Markdown
Member Author

@coatless thanks for pointing that out; fixed now in bdb029a.

@rcurtin

rcurtin commented Sep 17, 2025

Copy link
Copy Markdown
Member Author

A couple unexpected fixes were necessary to make this build... once I get things to pass I'll go ahead and merge.

@rcurtin

rcurtin commented Sep 18, 2025

Copy link
Copy Markdown
Member Author

Not sure what is going on with the GPU runners, but the tests at least build, and this PR doesn't modify any GPU tests, so I am going to assume that it would work fine if it did run.

@rcurtin
rcurtin merged commit 37b057d into mlpack:master Sep 18, 2025
5 of 9 checks passed
@rcurtin
rcurtin deleted the fbs branch September 18, 2025 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants