Skip to content

Commit 942d1fb

Browse files
changed some EstimationResult to FittedSDM (#51)
1 parent 5003faa commit 942d1fb

File tree

9 files changed

+55
-40
lines changed

9 files changed

+55
-40
lines changed

bench/benchmark_estimate.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ num_seeds = 3
1414
@benchmark begin
1515
gas = GAS($p, $q, $Beta, $scaling)
1616
opt_method = ScoreDrivenModels.LBFGS(gas, $num_seeds)
17-
estimate!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
17+
fit!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
1818
end
1919
# BenchmarkTools.Trial:
2020
# memory estimate: 466.69 MiB
@@ -40,7 +40,7 @@ num_seeds = 3
4040
@benchmark begin
4141
gas = GAS($p, $q, $LogNormal, $scaling)
4242
opt_method = ScoreDrivenModels.LBFGS(gas, $num_seeds)
43-
estimate!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
43+
fit!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
4444
end
4545
# BenchmarkTools.Trial:
4646
# memory estimate: 353.02 MiB
@@ -59,7 +59,7 @@ scaling = 0.5
5959
@benchmark begin
6060
gas = GAS($p, $q, $LogNormal, $scaling)
6161
opt_method = ScoreDrivenModels.LBFGS(gas, $num_seeds)
62-
estimate!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
62+
fit!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
6363
end
6464
# BenchmarkTools.Trial:
6565
# memory estimate: 8.26 GiB
@@ -77,7 +77,7 @@ scaling = 1.0
7777
@benchmark begin
7878
gas = GAS($p, $q, $LogNormal, $scaling)
7979
opt_method = ScoreDrivenModels.LBFGS(gas, $num_seeds)
80-
estimate!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
80+
fit!(gas, $simulation; verbose = $verbose, opt_method = opt_method)
8181
end
8282
# BenchmarkTools.Trial:
8383
# memory estimate: 666.69 MiB

docs/src/examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ y = Vector{Float64}(vec(inflow'))
1313
gas = GAS([1, 12], [1, 12], LogNormal, 0.0)
1414

1515
# Estimate the model via MLE
16-
estimate!(gas, y)
16+
fit!(gas, y)
1717

1818
# Obtain in-sample estimates for the inflow
1919
y_gas = fitted_mean(gas, y, dynamic_initial_params(y, gas))

examples/garch.jl

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,10 @@ gas = GAS(1, 1, Normal, 1.0, time_varying_params = [2])
5151
initial_point = [0.0; 0.5; 0.25; 0.75]
5252

5353
# Estimate the model
54-
res = estimate!(gas, y;
55-
initial_params = initial_params,
56-
opt_method = IPNewton(gas, [initial_point]; ub = ub, lb = lb))
57-
54+
f = fit(gas, y; initial_params = initial_params,
55+
opt_method = IPNewton(gas, [initial_point]; ub = ub, lb = lb))
5856

5957
# Another way to estimate the model is to rely on luck and give many random initial_points
6058
# for a non constrained optimization
61-
62-
gas = GAS(1, 1, Normal, 1.0, time_varying_params = [2])
63-
res = estimate!(gas, y;
64-
initial_params = initial_params,
65-
opt_method = NelderMead(gas, 100))
59+
f = fit(gas, y; initial_params = initial_params,
60+
opt_method = NelderMead(gas, 100))

examples/inflow_lognormal.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ y = Vector{Float64}(vec(inflow'))
5151
gas = GAS([1, 12], [1, 12], LogNormal, 0.0)
5252

5353
# Estimate the model via MLE
54-
estimate!(gas, y)
54+
fit!(gas, y)
5555

5656
# Obtain in-sample estimates for the inflow
5757
y_gas = fitted_mean(gas, y, dynamic_initial_params(y, gas))

src/MLE.jl

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
export estimate!
1+
export fit, fit!
22

33
const DEFAULT_INITIAL_PARAM = NaN.*ones(1, 1)
44
const DEFAULT_NUM_SEEDS = 3
5+
const DEFAULT_VERBOSE = 0
56

6-
struct EstimationResults{T <: AbstractFloat}
7+
struct FittedSDM{T <: AbstractFloat}
78
aic::T
89
bic::T
910
llk::T
@@ -45,27 +46,30 @@ function update_aux_estimation!(aux_est::AuxEstimation{T}, func::Optim.TwiceDiff
4546
return
4647
end
4748

48-
function estimate!(sdm::SDM{D, T}, y::Vector{T};
49-
initial_params::Matrix{T} = DEFAULT_INITIAL_PARAM,
50-
opt_method::AbstractOptimizationMethod = LBFGS(sdm, DEFAULT_NUM_SEEDS),
51-
verbose::Int = 0) where {D, T}
49+
function fit(sdm::SDM{D, T}, y::Vector{T};
50+
initial_params::Matrix{T} = DEFAULT_INITIAL_PARAM,
51+
opt_method::AbstractOptimizationMethod = LBFGS(sdm, DEFAULT_NUM_SEEDS),
52+
verbose::Int = DEFAULT_VERBOSE) where {D, T}
5253

5354
# Number of seed and number of params to estimate
5455
n_seeds = length(opt_method.seeds)
5556
n = length(y)
56-
57+
5758
unknowns = find_unknowns(sdm)
5859
n_unknowns = length(unknowns)
59-
60+
6061
# Check if the model has no unknowns
6162
check_model_estimated(n_unknowns) && return sdm
6263

64+
# Create a copy of the model to estimate
65+
sdm_fit = deepcopy(sdm)
66+
6367
# optimize for each seed
6468
aux_est = AuxEstimation{T}()
6569

6670
for i = 1:n_seeds
6771
try
68-
func = TwiceDifferentiable(psi_tilde -> log_lik(psi_tilde, y, sdm, initial_params, unknowns, n), opt_method.seeds[i])
72+
func = TwiceDifferentiable(psi_tilde -> log_lik(psi_tilde, y, sdm_fit, initial_params, unknowns, n), opt_method.seeds[i])
6973
opt_result = optimize(func, opt_method, verbose, i)
7074
update_aux_estimation!(aux_est, func, opt_result)
7175
println("seed $i of $n_seeds - $(-opt_result.minimum)")
@@ -91,9 +95,21 @@ function estimate!(sdm::SDM{D, T}, y::Vector{T};
9195
println(aux_est.opt_result[best_seed])
9296
end
9397

94-
# return the estimated
95-
fill_psitilde!(sdm, coefs, unknowns)
96-
9798
println("Finished!")
98-
return EstimationResults{T}(aic, bic, best_llk, coefs, num_hessian)
99+
return FittedSDM{T}(aic, bic, best_llk, coefs, num_hessian)
100+
end
101+
102+
function fit!(sdm::SDM{D, T}, y::Vector{T};
103+
initial_params::Matrix{T} = DEFAULT_INITIAL_PARAM,
104+
opt_method::AbstractOptimizationMethod = LBFGS(sdm, DEFAULT_NUM_SEEDS),
105+
verbose::Int = DEFAULT_VERBOSE) where {D, T}
106+
107+
unknowns = find_unknowns(sdm)
108+
# Check if the model has no unknowns
109+
n_unknowns = length(unknowns)
110+
check_model_estimated(n_unknowns) && return sdm
111+
112+
f = fit(sdm, y; initial_params = initial_params, opt_method = opt_method, verbose = verbose)
113+
fill_psitilde!(sdm, f.coefs, unknowns)
114+
return f
99115
end

src/ScoreDrivenModels.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module ScoreDrivenModels
33
using Distributions, Optim, SpecialFunctions
44
using LinearAlgebra
55

6-
import Base.length
6+
import Base.length, Base.deepcopy
77

88
const SCALINGS = [0.0, 1/2, 1.0]
99
const BIG_NUM = 1e8

src/gas/gas.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ mutable struct GAS{D <: Distribution, T <: AbstractFloat} <: SDM{D, T}
77
scaling::Real
88
end
99

10+
function deepcopy(gas::GAS{D, T}) where {D, T}
11+
return GAS{D, T}(deepcopy(gas.ω), deepcopy(gas.A), deepcopy(gas.B), deepcopy(gas.scaling))
12+
end
13+
1014
function create_ω(num_params::Int)
1115
return fill(NaN, num_params)
1216
end

test/test_estimate.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,32 @@
77
@testset "Estimation by passing number of seeds" begin
88
# LBFGS
99
gas = GAS(1, 1, Beta, 0.0)
10-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
10+
fit!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
1111
test_coefficients_GAS_1_1(gas, ω, A, B)
1212
# NelderMead
1313
gas = GAS(1, 1, Beta, 0.0)
14-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.NelderMead(gas, 3))
14+
fit!(gas, simulation; verbose = 1, opt_method = SDM.NelderMead(gas, 3))
1515
test_coefficients_GAS_1_1(gas, ω, A, B)
1616
# IPNewton
1717
gas = GAS(1, 1, Beta, 0.0)
18-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.IPNewton(gas, 3))
18+
fit!(gas, simulation; verbose = 1, opt_method = SDM.IPNewton(gas, 3))
1919
test_coefficients_GAS_1_1(gas, ω, A, B)
2020
end
2121
@testset "Estimation by passing seeds" begin
2222
# LBFGS
2323
gas = GAS(1, 1, Beta, 0.0)
2424
seeds = [[0.1, 0.1, 0.5, 0.5, 0.5, 0.5]]
25-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, seeds))
25+
fit!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, seeds))
2626
test_coefficients_GAS_1_1(gas, ω, A, B)
2727
# NelderMead
2828
gas = GAS(1, 1, Beta, 0.0)
2929
seeds = [[0.1, 0.1, 0.5, 0.5, 0.5, 0.5]]
30-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.NelderMead(gas, seeds))
30+
fit!(gas, simulation; verbose = 1, opt_method = SDM.NelderMead(gas, seeds))
3131
test_coefficients_GAS_1_1(gas, ω, A, B)
3232
# IPNewton
3333
gas = GAS(1, 1, Beta, 0.0)
3434
seeds = [[0.1, 0.1, 0.5, 0.5, 0.5, 0.5]]
35-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.IPNewton(gas, seeds))
35+
fit!(gas, simulation; verbose = 1, opt_method = SDM.IPNewton(gas, seeds))
3636
test_coefficients_GAS_1_1(gas, ω, A, B)
3737
end
3838
end
@@ -44,7 +44,7 @@
4444
B = [0.5 0; 0 0.5]
4545
simulation = simulate_GAS_1_1(LogNormal, 0.0, ω, A, B, 13)
4646
gas = GAS(1, 1, LogNormal, 0.0)
47-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
47+
fit!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
4848
test_coefficients_GAS_1_1(gas, ω, A, B)
4949
end
5050
@testset "Scaling = 0.5" begin
@@ -53,7 +53,7 @@
5353
B = [0.5 0; 0 0.5]
5454
simulation = simulate_GAS_1_1(LogNormal, 0.5, ω, A, B, 13)
5555
gas = GAS(1, 1, LogNormal, 0.5)
56-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
56+
fit!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
5757
test_coefficients_GAS_1_1(gas, ω, A, B)
5858
end
5959
@testset "Scaling = 1.0" begin
@@ -62,13 +62,13 @@
6262
B = [0.1 0; 0 0.1]
6363
simulation = simulate_GAS_1_1(LogNormal, 1.0, ω, A, B, 3)
6464
gas = GAS(1, 1, LogNormal, 1.0)
65-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
65+
fit!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
6666
test_coefficients_GAS_1_1(gas, ω, A, B)
6767
end
6868
@testset "GAS([1, 12], [1, 12])" begin
6969
simulation = simulate_GAS_1_12(LogNormal, 0.0, 123)
7070
gas = GAS([1, 12], [1, 12], LogNormal, 0.0)
71-
estimate!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
71+
fit!(gas, simulation; verbose = 1, opt_method = SDM.LBFGS(gas, 3))
7272
test_coefficients_GAS_1_12(gas)
7373
end
7474
end

test/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function test_GARCH_1_1(y, seed::Int, optimizer; atol = 1e-4, rtol = 1e-4)
125125
ub = [1.0; 1.0; 1.0; 1.0]
126126
lb = [-1.0; 0.0; 0.0; 0.0]
127127
gas = GAS(1, 1, Normal, 1.0, time_varying_params = [2])
128-
res = estimate!(gas, y; initial_params = ini, verbose = 1, opt_method = optimizer(gas, 10; ub = ub, lb = lb))
128+
res = fit!(gas, y; initial_params = ini, verbose = 1, opt_method = optimizer(gas, 10; ub = ub, lb = lb))
129129

130130
@test gas.ω[1] - -0.00616637237701241 0 atol = atol rtol = rtol
131131
@test gas.ω[2] - 0.010760592759725487 0 atol = atol rtol = rtol

0 commit comments

Comments
 (0)