Skip to content

Commit 6a825f7

Browse files
Merge pull request #303 from LAMPSPUC/small_improvements
add some improvements
2 parents 8c542ea + 826c833 commit 6a825f7

16 files changed

+68
-50
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "StateSpaceModels"
22
uuid = "99342f36-827c-5390-97c9-d7f9ee765c78"
33
authors = ["raphaelsaavedra <[email protected]>, guilhermebodin <[email protected]>, mariohsouto"]
4-
version = "0.5.22"
4+
version = "0.6.0"
55

66
[deps]
77
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
@@ -19,8 +19,8 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1919
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
2020

2121
[compat]
22-
Distributions = "0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24"
23-
MatrixEquations = "1"
22+
Distributions = "0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25"
23+
MatrixEquations = "1, 2"
2424
Optim = "0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 1.2"
2525
OrderedCollections = "1"
2626
Polynomials = "1, 2"

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ model = LocalLevel(y)
2626

2727
fit!(model)
2828

29-
results(model)
29+
print_results(model)
3030

3131
forecast(model, 10)
3232

@@ -105,6 +105,7 @@ Quick examples on automatic forecasting. When performing automatic forecasting
105105
users should provide the seasonal period if there is one.
106106
```julia
107107
model = auto_ets(log_air_passengers; seasonal = 12)
108+
model = auto_arima(log_air_passengers; seasonal = 12)
108109
```
109110

110111
## Contributing

docs/src/examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ air_passengers = CSV.File(StateSpaceModels.AIR_PASSENGERS) |> DataFrame
147147
log_air_passengers = log.(air_passengers.passengers)
148148
model = SARIMA(log_air_passengers; order = (0, 1, 1), seasonal_order = (0, 1, 1, 12))
149149
fit!(model)
150-
results(model)
150+
print_results(model)
151151
```
152152

153153
To make a forecast of 24 steps ahead of the model the command is:

docs/src/manual.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ model = LocalLevel(y)
1919

2020
fit!(model)
2121

22-
results(model)
22+
print_results(model)
2323

2424
forec = forecast(model, 10)
2525

src/StateSpaceModels.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export kalman_smoother
119119
export loglike
120120
export num_states
121121
export number_hyperparameters
122-
export results
122+
export print_results
123123
export set_initial_hyperparameters!
124124
export simulate
125125
export simulate_scenarios

src/cross_validation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function cross_validation(model::StateSpaceModel, steps_ahead::Int, start_idx::I
5858
y_to_fit = model.system.y[1:start_idx - 1 + i]
5959
y_to_verify = model.system.y[start_idx + i:start_idx - 1 + i + steps_ahead]
6060
model_to_fit = reinstantiate(model, y_to_fit)
61-
fit!(model_to_fit; filter=filter, optimizer=optimizer)
61+
fit!(model_to_fit; filter=filter, optimizer=optimizer, save_hyperparameter_distribution=false)
6262
forec = forecast(model_to_fit, steps_ahead; filter=filter)
6363
scenarios = simulate_scenarios(model_to_fit, steps_ahead, n_scenarios; filter=filter)
6464
expected_value_vector = forecast_expected_value(forec)[:]

src/filters/multivariate_kalman_filter.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ function update_Ptt!(kalman_state::MultivariateKalmanState{Fl}, Z::Matrix{Fl}) w
154154
end
155155

156156
function repeat_P_in_Ptt!(kalman_state::MultivariateKalmanState{Fl}) where Fl
157-
for i in axes(kalman_state.P, 1), j in axes(kalman_state.P, 2)
157+
for j in axes(kalman_state.P, 1), i in axes(kalman_state.P, 2)
158158
kalman_state.Ptt[i, j] = kalman_state.P[i, j]
159159
end
160160
return kalman_state

src/filters/sparse_univariate_kalman_filter.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ function update_Ptt!(kalman_state::SparseUnivariateKalmanState{Fl}) where Fl
163163
end
164164

165165
function repeat_P_in_Ptt!(kalman_state::SparseUnivariateKalmanState{Fl}) where Fl
166-
for i in axes(kalman_state.P, 1), j in axes(kalman_state.P, 2)
166+
for j in axes(kalman_state.P, 1), i in axes(kalman_state.P, 2)
167167
kalman_state.Ptt[i, j] = kalman_state.P[i, j]
168168
end
169169
return kalman_state

src/filters/univariate_kalman_filter.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ end
131131

132132
function update_att!(kalman_state::UnivariateKalmanState{Fl}, Z::Vector{Fl}) where Fl
133133
copyto!(kalman_state.att, kalman_state.a)
134-
@inbounds for i in axes(kalman_state.P, 1), j in axes(kalman_state.P, 2)
134+
@inbounds for j in axes(kalman_state.P, 1), i in axes(kalman_state.P, 2)
135135
kalman_state.att[i] +=
136136
(kalman_state.v / kalman_state.F) * kalman_state.P[i, j] * Z[j]
137137
end
@@ -162,7 +162,7 @@ function update_Ptt!(kalman_state::UnivariateKalmanState{Fl}) where Fl
162162
end
163163

164164
function repeat_P_in_Ptt!(kalman_state::UnivariateKalmanState{Fl}) where Fl
165-
for i in axes(kalman_state.P, 1), j in axes(kalman_state.P, 2)
165+
for j in axes(kalman_state.P, 1), i in axes(kalman_state.P, 2)
166166
kalman_state.Ptt[i, j] = kalman_state.P[i, j]
167167
end
168168
return kalman_state

src/fit.jl

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
fit!(
33
model::StateSpaceModel;
44
filter::KalmanFilter=default_filter(model),
5-
optimizer::Optimizer=Optimizer(Optim.LBFGS())
5+
optimizer::Optimizer=Optimizer(Optim.LBFGS()),
6+
save_hyperparameter_distribution::Bool=true
67
)
78
89
Estimate the state-space model parameters via maximum likelihood. The resulting optimal
@@ -29,6 +30,7 @@ function fit!(
2930
model::StateSpaceModel;
3031
filter::KalmanFilter=default_filter(model),
3132
optimizer::Optimizer=default_optimizer(model),
33+
save_hyperparameter_distribution::Bool=true
3234
)
3335
isfitted(model) && return model
3436
@assert has_fit_methods(typeof(model))
@@ -45,12 +47,29 @@ function fit!(
4547
opt_loglikelihood = -opt.minimum * size(model.system.y, 1)
4648
opt_hyperparameters = opt.minimizer
4749
update_model_hyperparameters!(model, opt_hyperparameters)
48-
# TODO
49-
# I leaned that this is not a good way to compute the covariance matrix of paarameters
50-
# we should investigate other methods
51-
numerical_hessian = Optim.hessian!(func, opt_hyperparameters)
52-
std_err = diag(pinv(numerical_hessian))
53-
fill_results!(model, opt_loglikelihood, std_err)
50+
51+
if save_hyperparameter_distribution
52+
numerical_hessian = Optim.hessian!(func, opt_hyperparameters)
53+
try
54+
std_err = numerical_hessian |> pinv |> diag .|> sqrt
55+
fill_results!(model, opt_loglikelihood, std_err)
56+
catch
57+
@warn(
58+
"The optimization process converged but the Hessian matrix is not positive definite. " *
59+
"This means that StateSpaceModels.jl cannot estimate the distribution of the hyperparameters " *
60+
"If you are interested in estimates of the distribution of ther hyperparameters we advise you to" *
61+
"change the optimization algorithm by using the kwarg fit(...; optimizer = "*
62+
"Optimizer(StateSpaceModels.Optim.THE_METHOD_OF_YOUR_CHOICE()))" *
63+
"The list of possible algorithms can be found on this link https://julianlsolvers.github.io/Optim.jl/stable/#" *
64+
"Otherwise you can simply skip this proccess by using fit(...; save_hyperparameter_distribution=false) "
65+
)
66+
std_err = fill(NaN, number_hyperparameters(model))
67+
fill_results!(model, opt_loglikelihood, std_err)
68+
end
69+
else
70+
std_err = fill(NaN, number_hyperparameters(model))
71+
fill_results!(model, opt_loglikelihood, std_err)
72+
end
5473
return model
5574
end
5675

@@ -121,12 +140,7 @@ function Results{Fl}() where Fl
121140
return Results{Fl}("", CoefficientTable{Fl}(), Fl(NaN), Fl(NaN), Fl(NaN), Fl(NaN), 0, 0)
122141
end
123142

124-
"""
125-
results(model::StateSpaceModel)
126-
127-
Query the results of the optimization called by `fit!`.
128-
"""
129-
results(model::StateSpaceModel) = model.results
143+
get_results(model::StateSpaceModel) = model.results
130144
function Base.isempty(results::Results)
131145
return isempty(results.coef_table) &&
132146
isnan(results.llk) &&

0 commit comments

Comments
 (0)