Skip to content

Commit 68c8782

Browse files
author
andre_ramos
committed
Blue format
1 parent 7e70c3d commit 68c8782

File tree

10 files changed

+234
-83
lines changed

10 files changed

+234
-83
lines changed

paper_tests/simulation_test/evaluate_models.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function get_SSL_results(
1414
X_train::Matrix{Fl},
1515
inf_criteria::String,
1616
true_β::Vector{Fl},
17-
) where Fl <: AbstractFloat
17+
) where {Fl<:AbstractFloat}
1818
series_result = nothing
1919

2020
model = StateSpaceLearning.StructuralModel(
@@ -78,7 +78,7 @@ function get_SS_res_results(
7878
X_train::Matrix{Fl},
7979
inf_criteria::String,
8080
true_β::Vector{Fl},
81-
) where Fl <: AbstractFloat
81+
) where {Fl<:AbstractFloat}
8282
py"""
8383
import math
8484
import statsmodels.api as sm
@@ -141,7 +141,9 @@ function get_SS_res_results(
141141
return series_result, converged
142142
end
143143

144-
function get_exogenous_ss_inf_criteria(y_train::Vector{Fl}, X_train::Matrix{Fl}) where Fl <: AbstractFloat
144+
function get_exogenous_ss_inf_criteria(
145+
y_train::Vector{Fl}, X_train::Matrix{Fl}
146+
) where {Fl<:AbstractFloat}
145147
py"""
146148
import math
147149
import statsmodels.api as sm
@@ -166,7 +168,7 @@ function get_forward_ss(
166168
X_train::Matrix{Fl},
167169
inf_criteria::String,
168170
true_β::Vector{Fl},
169-
) where Fl <: AbstractFloat
171+
) where {Fl<:AbstractFloat}
170172
best_inf_crit = Inf
171173
current_inf_crit = 0
172174
coefs = nothing

src/estimation_procedure.jl

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ function get_path_information_criteria(
7979
Lasso_y::Vector{Fl},
8080
information_criteria::String;
8181
intercept::Bool=true,
82-
)::Tuple{Vector{AbstractFloat},Vector{AbstractFloat}} where {Fl <: AbstractFloat, Tl <: AbstractFloat}
82+
)::Tuple{
83+
Vector{AbstractFloat},Vector{AbstractFloat}
84+
} where {Fl<:AbstractFloat,Tl<:AbstractFloat}
8385
path_size = length(model.lambda)
8486
T = size(Lasso_X, 1)
8587
K = count(i -> i != 0, model.betas; dims=1)'
@@ -136,7 +138,9 @@ function fit_glmnet(
136138
information_criteria::String="aic",
137139
penalty_factor::Vector{Pl}=ones(size(Lasso_X, 2) - 1),
138140
intercept::Bool=intercept,
139-
)::Tuple{Vector{AbstractFloat},Vector{AbstractFloat}} where {Fl <: AbstractFloat, Tl <: AbstractFloat, Pl <: AbstractFloat}
141+
)::Tuple{
142+
Vector{AbstractFloat},Vector{AbstractFloat}
143+
} where {Fl<:AbstractFloat,Tl<:AbstractFloat,Pl<:AbstractFloat}
140144
model = glmnet(
141145
Lasso_X,
142146
Lasso_y;
@@ -188,7 +192,9 @@ function fit_lasso(
188192
components_indexes::Dict{String,Vector{Int}},
189193
penalty_factor::Vector{Pl};
190194
rm_average::Bool=false,
191-
)::Tuple{Vector{AbstractFloat},Vector{AbstractFloat}} where {Fl <: AbstractFloat, Tl <: AbstractFloat, Pl <: AbstractFloat}
195+
)::Tuple{
196+
Vector{AbstractFloat},Vector{AbstractFloat}
197+
} where {Fl<:AbstractFloat,Tl<:AbstractFloat,Pl<:AbstractFloat}
192198
outlier_duplicate_columns = get_outlier_duplicate_columns(
193199
Estimation_X, components_indexes
194200
)
@@ -278,7 +284,9 @@ function estimation_procedure(
278284
ϵ::AbstractFloat,
279285
penalize_exogenous::Bool,
280286
penalize_initial_states::Bool,
281-
)::Tuple{Vector{AbstractFloat},Vector{AbstractFloat}} where {Fl <: AbstractFloat, Tl <: AbstractFloat}
287+
)::Tuple{
288+
Vector{AbstractFloat},Vector{AbstractFloat}
289+
} where {Fl<:AbstractFloat,Tl<:AbstractFloat}
282290
@assert 0 <= α <= 1 "α must be in [0, 1]"
283291
@assert ϵ > 0 "ϵ must be positive"
284292

@@ -398,10 +406,12 @@ function estimation_procedure(
398406
ϵ::AbstractFloat,
399407
penalize_exogenous::Bool,
400408
penalize_initial_states::Bool,
401-
)::Tuple{Vector{Vector{AbstractFloat}},Vector{Vector{AbstractFloat}}} where {Fl <: AbstractFloat, Tl <: AbstractFloat}
409+
)::Tuple{
410+
Vector{Vector{AbstractFloat}},Vector{Vector{AbstractFloat}}
411+
} where {Fl<:AbstractFloat,Tl<:AbstractFloat}
402412
coefs_vec = Vector{AbstractFloat}[]
403-
ε_vec = Vector{AbstractFloat}[]
404-
N_series = size(estimation_y, 2)
413+
ε_vec = Vector{AbstractFloat}[]
414+
N_series = size(estimation_y, 2)
405415

406416
for i in 1:N_series
407417
coef_i, ε_i = estimation_procedure(
@@ -418,4 +428,4 @@ function estimation_procedure(
418428
push!(ε_vec, ε_i)
419429
end
420430
return coefs_vec, ε_vec
421-
end
431+
end

src/fit_forecast.jl

Lines changed: 105 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,26 @@ function fit!(
5050

5151
residuals_variances = get_variances(model, estimation_ε, coefs, components_indexes)
5252

53-
T = typeof(model.y) <:Vector ? length(model.y) : size(model.y, 1)
53+
T = typeof(model.y) <: Vector ? length(model.y) : size(model.y, 1)
5454

55-
ε, fitted = get_fit_and_residuals(
56-
estimation_ε, coefs, model.X, valid_indexes, T
57-
)
55+
ε, fitted = get_fit_and_residuals(estimation_ε, coefs, model.X, valid_indexes, T)
5856

59-
if typeof(model.y) <:Vector
57+
if typeof(model.y) <: Vector
6058
output = Output(coefs, ε, fitted, residuals_variances, valid_indexes, components)
6159
else
6260
output = Output[]
6361
for i in eachindex(coefs)
64-
push!(output, Output(coefs[i], ε[i], fitted[i], residuals_variances[i], valid_indexes, components[i]))
62+
push!(
63+
output,
64+
Output(
65+
coefs[i],
66+
ε[i],
67+
fitted[i],
68+
residuals_variances[i],
69+
valid_indexes,
70+
components[i],
71+
),
72+
)
6573
end
6674
end
6775
return model.output = output
@@ -85,11 +93,13 @@ function forecast(
8593
model::StateSpaceLearningModel,
8694
steps_ahead::Int;
8795
Exogenous_Forecast::Matrix{Fl}=zeros(steps_ahead, 0),
88-
)::Union{Matrix{<:AbstractFloat}, Vector{<:AbstractFloat}} where Fl <: AbstractFloat
89-
90-
exog_idx = typeof(model.output) == Output ? model.output.components["Exogenous_X"]["Indexes"] : model.output[1].components["Exogenous_X"]["Indexes"]
91-
@assert length(exog_idx) ==
92-
size(Exogenous_Forecast, 2) "If an exogenous matrix was utilized in the estimation procedure, it must be provided its prediction for the forecast procedure. If no exogenous matrix was utilized, Exogenous_Forecast must be missing"
96+
)::Union{Matrix{<:AbstractFloat},Vector{<:AbstractFloat}} where {Fl<:AbstractFloat}
97+
exog_idx = if typeof(model.output) == Output
98+
model.output.components["Exogenous_X"]["Indexes"]
99+
else
100+
model.output[1].components["Exogenous_X"]["Indexes"]
101+
end
102+
@assert length(exog_idx) == size(Exogenous_Forecast, 2) "If an exogenous matrix was utilized in the estimation procedure, it must be provided its prediction for the forecast procedure. If no exogenous matrix was utilized, Exogenous_Forecast must be missing"
93103
@assert size(Exogenous_Forecast, 1) == steps_ahead "Exogenous_Forecast must have the same number of rows as steps_ahead"
94104

95105
Exogenous_X = model.X[:, exog_idx]
@@ -109,11 +119,14 @@ function forecast(
109119
)
110120

111121
if typeof(model.output) == Output
112-
return AbstractFloat.(complete_matrix[(end - steps_ahead + 1):end, :] * model.output.coefs)
122+
return AbstractFloat.(
123+
complete_matrix[(end - steps_ahead + 1):end, :] * model.output.coefs
124+
)
113125
else
114126
prediction = Matrix{AbstractFloat}(undef, steps_ahead, length(model.output))
115127
for i in eachindex(model.output)
116-
prediction[:, i] = complete_matrix[(end - steps_ahead + 1):end, :] * model.output[i].coefs
128+
prediction[:, i] =
129+
complete_matrix[(end - steps_ahead + 1):end, :] * model.output[i].coefs
117130
end
118131
return AbstractFloat.(prediction)
119132
end
@@ -140,16 +153,19 @@ function simulate(
140153
N_scenarios::Int;
141154
Exogenous_Forecast::Matrix{Fl}=zeros(steps_ahead, 0),
142155
seasonal_innovation_simulation::Int=0,
143-
)::Union{Vector{Matrix{<:AbstractFloat}}, Matrix{<:AbstractFloat}} where Fl <: AbstractFloat
156+
)::Union{Vector{Matrix{<:AbstractFloat}},Matrix{<:AbstractFloat}} where {Fl<:AbstractFloat}
144157
@assert seasonal_innovation_simulation >= 0 "seasonal_innovation_simulation must be a non-negative integer"
145158
@assert seasonal_innovation_simulation >= 0 "seasonal_innovation_simulation must be a non-negative integer"
146159

147-
prediction = StateSpaceLearning.forecast(model, steps_ahead; Exogenous_Forecast=Exogenous_Forecast)
160+
prediction = StateSpaceLearning.forecast(
161+
model, steps_ahead; Exogenous_Forecast=Exogenous_Forecast
162+
)
148163

149164
is_univariate = typeof(model.output) == StateSpaceLearning.Output
150165

151166
simulation_X = zeros(steps_ahead, 0)
152-
valid_indexes = is_univariate ? model.output.valid_indexes : model.output[1].valid_indexes
167+
valid_indexes =
168+
is_univariate ? model.output.valid_indexes : model.output[1].valid_indexes
153169
components_matrix = zeros(length(valid_indexes), 0)
154170
N_components = 1
155171

@@ -168,54 +184,112 @@ function simulate(
168184

169185
if is_univariate
170186
components_matrix = hcat(components_matrix, model.output.ε[valid_indexes])
171-
@assert N_components < length(model.y) // seasonal_innovation_simulation "The parameter `seasonal_innovation_simulation` is too large for the given dataset, please reduce it"
187+
@assert N_components < length(model.y)//seasonal_innovation_simulation "The parameter `seasonal_innovation_simulation` is too large for the given dataset, please reduce it"
172188
else
173189
for i in eachindex(model.output)
174190
components_matrix = hcat(components_matrix, model.output[i].ε[valid_indexes])
175191
end
176-
N_mv_components = N_components*length(model.output)
177-
@assert N_mv_components < size(model.y, 1) // seasonal_innovation_simulation "The parameter `seasonal_innovation_simulation` is too large for the given dataset, please reduce it"
192+
N_mv_components = N_components * length(model.output)
193+
@assert N_mv_components < size(model.y, 1)//seasonal_innovation_simulation "The parameter `seasonal_innovation_simulation` is too large for the given dataset, please reduce it"
178194
end
179195
simulation_X = hcat(simulation_X, Matrix(1.0 * I, steps_ahead, steps_ahead))
180196
components_matrix += rand(Normal(0, 1), size(components_matrix)) ./ 1e9 # Make sure matrix is positive definite
181197

182198
MV_dist_vec = Vector{MvNormal}(undef, steps_ahead)
183-
o_noises = is_univariate ? zeros(steps_ahead, N_scenarios) : [zeros(steps_ahead, N_scenarios) for _ in 1:length(model.output)]
199+
o_noises = if is_univariate
200+
zeros(steps_ahead, N_scenarios)
201+
else
202+
[zeros(steps_ahead, N_scenarios) for _ in 1:length(model.output)]
203+
end
184204

185205
if seasonal_innovation_simulation == 0
186206
= cov(components_matrix)
187207
for i in 1:steps_ahead
188-
MV_dist_vec[i] = is_univariate ? MvNormal(zeros(N_components), ∑) : MvNormal(zeros(N_mv_components), ∑)
208+
MV_dist_vec[i] = if is_univariate
209+
MvNormal(zeros(N_components), ∑)
210+
else
211+
MvNormal(zeros(N_mv_components), ∑)
212+
end
189213
end
190214

191215
if model.outlier
192216
if is_univariate
193-
o_noises = rand(Normal(0, std(model.output.components["o"]["Coefs"])), steps_ahead, N_scenarios)
217+
o_noises = rand(
218+
Normal(0, std(model.output.components["o"]["Coefs"])),
219+
steps_ahead,
220+
N_scenarios,
221+
)
194222
else
195-
o_noises = [rand(Normal(0, std(model.output[i].components["o"]["Coefs"])), steps_ahead, N_scenarios) for i in eachindex(model.output)]
223+
o_noises = [
224+
rand(
225+
Normal(0, std(model.output[i].components["o"]["Coefs"])),
226+
steps_ahead,
227+
N_scenarios,
228+
) for i in eachindex(model.output)
229+
]
196230
end
197231
end
198232
else
199233
start_seasonal_term = (size(components_matrix, 1) % seasonal_innovation_simulation)
200234
for i in 1:steps_ahead
201-
= cov(components_matrix[i + start_seasonal_term:seasonal_innovation_simulation:end, :])
202-
MV_dist_vec[i] = is_univariate ? MvNormal(zeros(N_components), ∑) : MvNormal(zeros(N_mv_components), ∑)
235+
= cov(
236+
components_matrix[
237+
(i + start_seasonal_term):seasonal_innovation_simulation:end, :,
238+
],
239+
)
240+
MV_dist_vec[i] = if is_univariate
241+
MvNormal(zeros(N_components), ∑)
242+
else
243+
MvNormal(zeros(N_mv_components), ∑)
244+
end
203245
if is_univariate
204-
model.outlier ? o_noises[i, :] = rand(Normal(0, std(model.output.components["o"]["Coefs"][i + start_seasonal_term:seasonal_innovation_simulation:end])), N_scenarios) : nothing
246+
if model.outlier
247+
o_noises[i, :] = rand(
248+
Normal(
249+
0,
250+
std(
251+
model.output.components["o"]["Coefs"][(i + start_seasonal_term):seasonal_innovation_simulation:end],
252+
),
253+
),
254+
N_scenarios,
255+
)
256+
else
257+
nothing
258+
end
205259
else
206260
for j in eachindex(model.output)
207-
model.outlier ? o_noises[j][i, :] = rand(Normal(0, std(model.output[j].components["o"]["Coefs"][i + start_seasonal_term:seasonal_innovation_simulation:end])), N_scenarios) : nothing
261+
if model.outlier
262+
o_noises[j][i, :] = rand(
263+
Normal(
264+
0,
265+
std(
266+
model.output[j].components["o"]["Coefs"][(i + start_seasonal_term):seasonal_innovation_simulation:end],
267+
),
268+
),
269+
N_scenarios,
270+
)
271+
else
272+
nothing
273+
end
208274
end
209275
end
210-
end
276+
end
277+
end
211278

279+
simulation = if is_univariate
280+
AbstractFloat.(hcat([prediction for _ in 1:N_scenarios]...))
281+
else
282+
[
283+
AbstractFloat.(hcat([prediction[:, i] for _ in 1:N_scenarios]...)) for
284+
i in eachindex(model.output)
285+
]
212286
end
213-
214-
simulation = is_univariate ? AbstractFloat.(hcat([prediction for _ in 1:N_scenarios]...)) : [AbstractFloat.(hcat([prediction[:, i] for _ in 1:N_scenarios]...)) for i in eachindex(model.output)]
215287
if is_univariate
216288
fill_simulation!(simulation, MV_dist_vec, o_noises, simulation_X)
217289
else
218-
fill_simulation!(simulation, MV_dist_vec, o_noises, simulation_X, length(model_innovations))
290+
fill_simulation!(
291+
simulation, MV_dist_vec, o_noises, simulation_X, length(model_innovations)
292+
)
219293
simulation = Vector{Matrix{<:AbstractFloat}}(simulation)
220294
end
221295

src/information_criteria.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"""
1717
function get_information(
1818
T::Int, K::Int, ε::Vector{Fl}; information_criteria::String="aic"
19-
)::AbstractFloat where Fl <: AbstractFloat
19+
)::AbstractFloat where {Fl<:AbstractFloat}
2020
if information_criteria == "bic"
2121
return T * log(var(ε)) + K * log(T)
2222
elseif information_criteria == "aic"

0 commit comments

Comments
 (0)