Skip to content

Commit 48b25fc

Browse files
committed
Update optimization to adopt new API from ProximalAlgorithms/ProximalCore
1 parent 0502653 commit 48b25fc

File tree

4 files changed

+21
-51
lines changed

4 files changed

+21
-51
lines changed

Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors = ["Quint Wiersma <qnt.wrsm@gmail.com> and contributors"]
44
version = "0.1.0"
55

66
[deps]
7+
DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
78
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
89
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
910
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
@@ -23,6 +24,8 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
2324
StatsAPI = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
2425

2526
[compat]
27+
DifferentiationInterface = "0.6.53"
28+
FiniteDiff = "2.27.0"
2629
julia = "1.9"
2730

2831
[extras]

src/DynamicFactorModels.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ using Distributions: MvNormal
2121

2222
using StatsAPI: StatisticalModel
2323

24-
using MultivariateStats: PCA, projection, predict
24+
using MultivariateStats: PCA, fit, projection, predict
2525

2626
using IrrationalConstants: log2π
2727

@@ -30,9 +30,10 @@ using Distances: evaluate, Chebyshev
3030
using LogExpFunctions: logistic, logit
3131
using Optim
3232
using FiniteDiff
33+
using DifferentiationInterface: AutoFiniteDiff
3334
using ProximalCore
3435
using ProximalOperators: NormL1, NormL21, TotalVariation1D
35-
using ProximalAlgorithms: FastForwardBackward
36+
using ProximalAlgorithms
3637

3738
using ProgressMeter
3839

src/fit/solver.jl

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,9 @@ function update_loadings!(F::AbstractUnrestrictedFactorProcess, y::AbstractMatri
7979

8080
return (0.5 * dot(ΩΛ, Λ * Eff) - dot(ΩΛ, Eyf)) / length(V)
8181
end
82-
function gradient!(∇::AbstractMatrix, Λ::AbstractMatrix)
83-
∇ .= Σ \* Eff - Eyf)
84-
./= length(V)
85-
86-
return nothing
87-
end
88-
f = ObjectiveGradientWrapper(objective, gradient!)
89-
ffb = FastForwardBackward(maxit = 100, tol = 1e-2)
82+
gradient::AbstractMatrix) =\* Eff - Eyf)) ./ length(V)
83+
f = ObjectiveGradientWrapper(objective, gradient)
84+
ffb = ProximalAlgorithms.FastForwardBackward(maxit = 1000, tol = 1e-4)
9085
(solution, _) = ffb(x0 = loadings(F), f = f, g = regularizer)
9186
loadings(F) .= solution
9287

@@ -220,14 +215,9 @@ function update!(μ::Exogenous, y::AbstractMatrix, Σ::AbstractMatrix, regulariz
220215

221216
return (0.5 * dot(Ωβ, β * XX) - dot(Ωβ, yX)) / size(regressors(μ), 2)
222217
end
223-
function gradient!(∇::AbstractMatrix, β::AbstractMatrix)
224-
∇ .= Σ \* XX - yX)
225-
./= size(regressors(μ), 2)
226-
227-
return nothing
228-
end
229-
f = ObjectiveGradientWrapper(objective, gradient!)
230-
ffb = FastForwardBackward(maxit = 100, tol = 1e-2)
218+
gradient::AbstractMatrix) =\* XX - yX)) ./ size(regressors(μ), 2)
219+
f = ObjectiveGradientWrapper(objective, gradient)
220+
ffb = ProximalAlgorithms.FastForwardBackward(maxit = 1000, tol = 1e-4)
231221
(solution, _) = ffb(x0 = slopes(μ), f = f, g = regularizer)
232222
slopes(μ) .= solution
233223

@@ -274,7 +264,7 @@ function update!(ε::SpatialAutoregression, e::AbstractMatrix, Λ::AbstractMatri
274264

275265
return -logdet(G) + 0.5 * dot(Ω, Eee) / size(e, 2)
276266
end
277-
opt = optimize(objective, logit.((spatial(ε) .+ offset) ./ scale), ConjugateGradient(),
267+
opt = optimize(objective, logit.((spatial(ε) .+ offset) ./ scale), LBFGS(),
278268
Optim.Options(g_tol = 1e-4))
279269
spatial(ε) .= scale .* logistic.(Optim.minimizer(opt)) .- offset
280270

@@ -302,9 +292,8 @@ function update!(ε::SpatialAutoregression, e::AbstractMatrix, Λ::AbstractMatri
302292

303293
return -logdet(G) + 0.5 * dot(Ω, Eee) / size(e, 2)
304294
end
305-
cache = FiniteDiff.GradientCache(copy(spatial(ε)), copy(spatial(ε)))
306-
f = ObjectiveWrapper(objective, cache)
307-
ffb = FastForwardBackward(maxit = 100, tol = 1e-2)
295+
f = ProximalAlgorithms.AutoDifferentiable(objective, AutoFiniteDiff())
296+
ffb = ProximalAlgorithms.FastForwardBackward(maxit = 1000, tol = 1e-4)
308297
(solution, _) = ffb(x0 = logit.((spatial(ε) .+ offset) ./ scale), f = f,
309298
g = regularizer)
310299
spatial(ε) .= scale .* logistic.(solution) .- offset
@@ -333,7 +322,7 @@ function update!(ε::SpatialMovingAverage, e::AbstractMatrix, Λ::AbstractMatrix
333322

334323
return logdet(G) + 0.5 * tr\ Eee) / size(e, 2)
335324
end
336-
opt = optimize(objective, logit.((spatial(ε) .+ offset) ./ scale), ConjugateGradient(),
325+
opt = optimize(objective, logit.((spatial(ε) .+ offset) ./ scale), LBFGS(),
337326
Optim.Options(g_tol = 1e-4))
338327
spatial(ε) .= scale .* logistic.(Optim.minimizer(opt)) .- offset
339328

@@ -361,9 +350,8 @@ function update!(ε::SpatialMovingAverage, e::AbstractMatrix, Λ::AbstractMatrix
361350

362351
return logdet(G) + 0.5 * tr\ Eee) / size(e, 2)
363352
end
364-
cache = FiniteDiff.GradientCache(copy(spatial(ε)), copy(spatial(ε)))
365-
f = ObjectiveWrapper(objective, cache)
366-
ffb = FastForwardBackward(maxit = 100, tol = 1e-2)
353+
f = ProximalAlgorithms.AutoDifferentiable(objective, AutoFiniteDiff())
354+
ffb = ProximalAlgorithms.FastForwardBackward(maxit = 1000, tol = 1e-4)
367355
(solution, _) = ffb(x0 = logit.((spatial(ε) .+ offset) ./ scale), f = f,
368356
g = regularizer)
369357
spatial(ε) .= scale .* logistic.(solution) .- offset

src/fit/utilities.jl

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,6 @@ utilities.jl
99
@date: 2023/12/08
1010
=#
1111

12-
"""
13-
ObjectiveWrapper
14-
15-
Wrapper for objective functions for gradient dispatching to finit differences.
16-
"""
17-
struct ObjectiveWrapper{F, C}
18-
f::F
19-
cache::C
20-
end
21-
22-
(f::ObjectiveWrapper)(x) = f.f(x)
23-
24-
function ProximalCore.gradient!(y, f::ObjectiveWrapper, x)
25-
FiniteDiff.finite_difference_gradient!(y, f, x, f.cache)
26-
27-
return f(x)
28-
end
29-
3012
"""
3113
ObjectiveGradientWrapper
3214
@@ -35,16 +17,12 @@ function.
3517
"""
3618
struct ObjectiveGradientWrapper{F, G}
3719
f::F
38-
g!::G
20+
g::G
3921
end
4022

4123
(f::ObjectiveGradientWrapper)(x) = f.f(x)
4224

43-
function ProximalCore.gradient!(y, f::ObjectiveGradientWrapper, x)
44-
f.g!(y, x)
45-
46-
return f(x)
47-
end
25+
ProximalAlgorithms.value_and_gradient(f::ObjectiveGradientWrapper, x) = (f(x), f.g(x))
4826

4927
"""
5028
init!(model, method)
@@ -423,7 +401,7 @@ function objective(model::DynamicFactorModel, regularizer::NamedTuple)
423401
end
424402

425403
function dof(model::DynamicFactorModel)
426-
R = size(process(model))
404+
R = nfactors(model)
427405

428406
# factor component
429407
process(model) isa AbstractUnrestrictedFactorProcess &&

0 commit comments

Comments
 (0)