Repository navigation
CoordinateDescent 0.7 on ProximalSolvers 0.1.1 and ProximalBase 0.5 - #23
Merged
Merged
Conversation
… 0.7.0 The estimators (lasso, sqrtLasso, scaledLasso, feasibleLasso!, LassoPath, locpolyl1, lvocv_locpolyl1) call ProximalOPT's CDSolver, solve_path and reweight! on ProximalOPT's models; the engine of this package (passes, screening, Anderson acceleration, momentum, group steps) is removed. coordinateDescent!, CDOptions and CDInfo stay as a thin layer over ProximalOPT.solve!: the CD losses build ProximalOPT models, and a user-defined CoordinateDifferentiableFunction runs through a model that calls its descendCoordinate!. ProximalBase 0.5 and ProximalOPT 0.2 are not registered yet; [sources] takes them from their pull requests (ProximalBase #23, ProximalOPT #11). Co-Authored-By: Claude Opus 5.5 <[email protected]>
The examples use the names of ProximalBase 0.5 (NormL1, ZeroFunction, GroupNormL2, prox_entry) and check the custom logistic loss, elastic net and MCP against ProximalBase's. The README and benchmark/README.md describe the move to ProximalOPT; momentum_default_bench.jl goes, since momentum is not in ProximalOPT yet, and order_anderson_bench.jl times the cyclic and random orders and Anderson acceleration. benchmark/compare/ runs 0.6.0 from the registry (with its default momentum and with momentum = false) and this checkout on the same cases, interleaved: against 0.6.0 without momentum every case takes the same passes, the solutions agree to 2e-14 and the times to 3%; against the default of 0.6.0, paths take 2.7-4.5 times as long until momentum moves to ProximalOPT. CI adds ProximalBase 0.5 and ProximalOPT 0.2 by URL on Julia 1.10, in one Pkg.add call. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #23 +/- ##
==========================================
+ Coverage 97.81% 98.83% +1.02%
==========================================
Files 9 6 -3
Lines 1370 600 -770
==========================================
- Hits 1340 593 -747
+ Misses 30 7 -23 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
At λmax the group that attains it is on the boundary, and the group step of ProximalOPT, which sums the gradient in its own order, exceeded the test's BLAS λmax in the last bit on x86 (CI on Linux and Windows). Take λmax (1 + √eps), as LassoPath does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
mlakolar
added a commit
to mlakolar/ProximalSolvers.jl
that referenced
this pull request
Oct 23, 2026
Found while porting CoordinateDescent onto this branch (mlakolar/HighDimensionalModels.jl#23): - CDSolver(; momentum): Nesterov momentum on the passes over the active set, with adaptive restarts, as in CoordinateDescent 0.6. It is on by default with the random order on a SparseIterate for least squares, square-root least squares, quadratics and GLMs, whose caches move with the point. KronQuadratic takes it with momentum = true. Seeded runs take the passes of CoordinateDescent 0.6.0, and the passes allocate nothing. - The interface of CDModel has public, unexported names: initialize!, coordinate_derivatives, update_cache!, coordinate_step!, and the optional coordinate_scale, response_scale, loss_value, check_penalty. - solve! checks the weights and bounds of the penalty against the iterate before the passes, which read them unchecked. - QuadModel uses a dense Matrix{T} as it is, instead of copying it. - solve!(...; continuation) with a penalty without a level (ZeroFunction, IndBox) solves from zero directly. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ProximalOPT's CDSolver has momentum since mlakolar/ProximalSolvers.jl#11 (b58ef35), with the default rule of 0.6, so CDOptions passes it through: - momentum = true works again, with order = :random; the cyclic order refuses it, as in 0.6. - The adapter of user-defined losses extends ProximalOPT's public interface (coordinate_step!, coordinate_scale, response_scale, loss_value) instead of its internals. - The momentum tests, the README section, the rows of example 02 and the momentum column of order_anderson_bench.jl are back, without order = :active. - benchmark/compare compares the passes and solutions with the default of 0.6.0, which uses momentum. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ProximalBase 0.5.0 is registered (JuliaRegistries/General#173046), so its [sources] entries go (Project.toml, benchmark/, benchmark/compare/new/, examples/), and the Julia 1.10 CI step adds only ProximalOPT by URL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ProximalOPT's QuadModel no longer copies a dense Matrix{T}, so
CDQuadraticLoss behaves as in 0.6 there; any other matrix is copied.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Against 0.6.0's default, every one of the 19 cases takes the same passes, the solutions agree to 4e-14 and the times are 0.94-1.03 (three interleaved rounds on an EPYC 7513, Slurm job 13326700). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This was referenced Oct 23, 2026
ProximalOPT is now ProximalSolvers (new UUID, version 0.1.0 registering as General #173068); [deps], compat, [sources], the Julia 1.10 CI step and the code follow. Until ProximalSolvers 0.1.1 is registered, [sources] takes it from its branch sqrt-quadratic, which adds SqrtQuadraticFunction. #24 ported onto ProximalSolvers: - scaledLasso! solves the square-root lasso in one run of coordinate descent, on SqrtLeastSquaresLoss with NormL1(√n λ, ω), with options.optionsCD; σ̂ = ‖r‖/√n and the penalty is λσ̂. - CDSqrtQuadraticLoss(A, b, c; check) is the model of ProximalSolvers' SqrtQuadraticFunction, which keeps #24's exact coordinate step, the check = false path, and momentum through a hook that recomputes the value after the cache moves; scaledLasso!(x, f, λ, ω, options) on it. - #24's tests; sizes now throw DimensionMismatch, as for CDQuadraticLoss. - benchmark/scaledlasso_bench.jl and example 04 with the 0.5 names; cd_bench.jl no longer calls the removed _findInitSigma!. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Its branch sqrt-quadratic is at version 0.1.1 (33a72d6). The compat in Project.toml and the examples, benchmark and compare environments follows. Co-Authored-By: Claude Opus 5.5 <[email protected]>
ProximalSolvers #15 (SqrtQuadraticFunction, version 0.1.1) is merged as 541690c, so [sources] and the Julia 1.10 CI step take master instead of the branch sqrt-quadratic, until 0.1.1 is registered. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
mlakolar
marked this pull request as ready for review
October 23, 2026 21:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on ProximalSolvers 0.1.1 (mlakolar/ProximalSolvers.jl, formerly ProximalOPT). It merges into master before that is registered: the packages are developed on master until they settle, and registered then.
SqrtQuadraticFunction, the model ofCDSqrtQuadraticLoss. It is merged in ProximalSolvers' master (SqrtQuadraticFunction: the square-root lasso from sufficient statistics; version 0.1.1 ProximalSolvers.jl#15, 541690c) and is registered after 0.1.0.Until ProximalSolvers 0.1.1 is registered:
[sources]takes ProximalSolvers from its master (Julia 1.11 and later);[sources], CI adds it by URL.This PR is step 5 of mlakolar/ProximalSolvers.jl#11's release order: CoordinateDescent becomes a thin layer over ProximalSolvers.
What changes
lasso,sqrtLasso,scaledLasso(!),feasibleLasso!,LassoPath,locpolyl1andlvocv_locpolyl1keep their signatures. They now call ProximalSolvers'CDSolver,solve_pathandreweight!, on ProximalSolvers' models.coordinate_descent.jl,anderson.jl,momentum.jl,atom_iterator.jl,cd_differentiable_function.jl) are deleted, about 1,600 lines. Momentum, the default since 0.6, now runs in ProximalSolvers'CDSolver, andCDOptions(; momentum)passes through to it.coordinateDescent!,CDOptionsandCDInfomap ontoProximalSolvers.solve!.CDLeastSquaresLoss,CDWeightedLSLoss,CDSqrtLassoLossandCDQuadraticLossbuild ProximalSolvers models.coordinateDescent!also takes any loss thatProximalSolvers.cdmodelknows, such asKronQuadraticor a scaledLogisticLoss.CoordinateDifferentiableFunctionruns through a small adapter model,_LossModelinsrc/losses.jl. It calls the loss'sdescendCoordinate!and extends ProximalSolvers' public model interface (coordinate_step!,coordinate_scale,response_scale,loss_value).scaledLasso!solves the square-root lasso in one run of coordinate descent, onSqrtLeastSquaresLosswithNormL1(√n λ, ω).CDSqrtQuadraticLoss(A, b, c; check)is the model of ProximalSolvers'SqrtQuadraticFunction. It keeps scaledLasso: the square-root lasso in one run, and CDSqrtQuadraticLoss for sufficient statistics (version 0.6.1) #24's exact coordinate step and thecheck = falsepath, and gets momentum through a hook that recomputes the value after the cache moves.scaledLasso!(x, f, λ, ω, options)works on that model.NormL1,ZeroFunction,GroupNormL2,prox_entry,prox_coordinate!andcoordinates. The tests and examples pass with--depwarn=error.Breaking changes (version 0.7.0)
LassoSolution.penaltyis aNormL1, whose weights are the fieldw(wasλ).CD*Lossconstructors return ProximalSolvers models.f.r(the residuals) still works, andProximalSolvers.intercept(f, x)replacesf.ybar - dot(f.xbar, x).CDQuadraticLosscopies anAthat is not a denseMatrix; a dense one is used as it is, as in 0.6.f(x)(callable), notProximalBase.value(f, x).prox_entryorprox_coordinate!.SymmetricSparseIterate, coordinatekiscoordinates(x)[k].isseparable,prox_entry, and a callable value.order = :active, which was within −27% to +17% of:randomin 0.6.feasibleLasso!andlvocv_locpolyl1always warm start their inner fits.scaledLasso!has usedoptionsCDas it is since 0.6.1.feasibleLasso!'spenalty.wholds the loadings of the last fit. In 0.6 it held the loadings recomputed after the last fit.AtomIterateor for a loss without a value. It just has no effect there.LassoPathneeds a decreasingλpath.CDSqrtQuadraticLossthrowsDimensionMismatchfor sizes that do not match (ArgumentErrorin 0.6.1), asCDQuadraticLossdoes.Benchmark against 0.6.0 (
benchmark/compare/)benchmark/compare/runs two environments in interleaved processes, from the same seeds:momentum = false;The cases are those of 0.6's momentum benchmark (designs A, E, F and
locpolyl1). The table below summarizes three rounds on USC CARC Discovery (one core of an AMD EPYC 7513, Slurm job 13326700). All 19 cases are inbenchmark/README.md.LassoPath(A, E, F)CDQuadraticLossat 0.02 λmaxlassoat 0.05 λmaxlocpolyl1locpolyl1is a 0.8 ms case.benchmark/scaledlasso_bench.jladded, since 0.6.1 changedscaledLasso.Moved into ProximalSolvers for this PR
The five gaps found while porting are in ProximalSolvers now (#11):
xbefore the passes;_LossModelnow uses;QuadModelusing a denseMatrix{T}without copying it;solve!(...; continuation)for a penalty without a level.The NormL1/GroupNormL2 check in
_solve!stays. In 0.6 only those penalties followed a path of levels withwarmStart = false, and an MCP or SCAD path would change the local solution found.The estimator-level code stays here: the λ grid, the standardization loadings, the initialization of the scaled and feasible lasso,
refitLassoPath, the kernels andlocpoly.Dependents and overlapping PRs
"0.4, 0.5, 0.6", so this release does not affect them.SqrtQuadModeland the hook after the momentum step came with ProximalSolvers 0.1.1 (SqrtQuadraticFunction: the square-root lasso from sufficient statistics; version 0.1.1 ProximalSolvers.jl#15). On Discovery, that model takes the passes of CoordinateDescent 0.6.1 and gives bit-identical solutions.Testing
Pkg.test()with--depwarn=errorpasses all 1077 tests on Julia 1.13.2 and 1.10.12, with ProximalSolvers 0.1.1 from its master. Aqua is included.CDOptions.--depwarn=error. Examples 08 and 09 check the custom logistic loss, elastic net and MCP against ProximalBase's built-in ones.Release order
SqrtQuadraticFunction, Examples, how to write a loss or a penalty, and the local polynomial benchmark #15) is merged; it is registered after 0.1.0.ProximalSolvers = "0.1.1"and[sources]at ProximalSolvers' master.[sources](also inexamples/,benchmark/andbenchmark/compare/new/) and the CI step, once ProximalSolvers 0.1.1 installs;benchmark/compare/ab.shon Discovery against 0.6.1, with the scaled lasso cases, where every case must be at or below 1.0 against its default;🤖 Generated with Claude Code