Skip to content

Commit 8da36eb

Browse files
Add negative binomial distribution (#99)
* added fitted quantiles and SDMforecast * update default verbose * remove fitted quantiles * update * add ane to test folder * add NegativeBinomial distribution * add negbin to docs * fix special functions dep
1 parent 73d44f1 commit 8da36eb

File tree

10 files changed

+579
-78
lines changed

10 files changed

+579
-78
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ScoreDrivenModels"
22
uuid = "4a87933e-d659-11e9-0e65-7f40dedd4a3a"
33
authors = ["guilhermebodin <[email protected]>, raphaelsaavedra <[email protected]>"]
4-
version = "0.1.0"
4+
version = "0.1.1"
55

66
[deps]
77
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
@@ -12,7 +12,7 @@ SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
1212

1313
[compat]
1414
julia = "1"
15-
Distributions = "0.21"
15+
Distributions = "0.23"
1616
Optim = "0.20"
1717
SpecialFunctions = "0.8"
1818

docs/src/manual.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ this is handled internally.
9999
|[`Gamma`](@ref)|||
100100
|[`LogitNormal`](@ref)|||
101101
|[`LogNormal`](@ref)|||
102+
|[`NegativeBinomial`](@ref)|| x |
102103
|[`Normal`](@ref)|||
103104
|[`Poisson`](@ref)|||
104105
|[`TDist`](@ref)|||
@@ -115,6 +116,7 @@ ScoreDrivenModels.Exponential
115116
ScoreDrivenModels.Gamma
116117
ScoreDrivenModels.LogitNormal
117118
ScoreDrivenModels.LogNormal
119+
ScoreDrivenModels.NegativeBinomial
118120
ScoreDrivenModels.Normal
119121
ScoreDrivenModels.Poisson
120122
ScoreDrivenModels.TDist

examples/ane.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using ScoreDrivenModels, Plots
2+
3+
# Convert data to vector
4+
y = Vector{Float64}(vec(readdlm("./test/data/ena_northeastern.csv")'))
5+
y_train = y[1:400]
6+
y_test = y[401:end]
7+
8+
# Specify model: here we use lag 1 for trend characterization and lag 12 for seasonality characterization
9+
gas = Model([1, 2, 11, 12], [1, 2, 11, 12], LogNormal, 0.0; time_varying_params = [1])
10+
11+
# Define initial_params with
12+
initial_params = dynamic_initial_params(y_train, gas)
13+
14+
# Estimate the model via MLE
15+
f = fit!(gas, y_train; initial_params = initial_params)
16+
17+
# Compare observations and in-sample estimates
18+
plot(y_train, label = "In-sample ANE")
19+
20+
# Forecasts with 95% confidence interval
21+
forecast = forecast_quantiles(y_train, gas, 60; S = 1_000, initial_params = initial_params)
22+
23+
plot(forecast.scenarios, color = "grey", width = 0.05, label = "")
24+
plot!(y[360:460], label = "ANE", color = "black", xlabel = "Months", ylabel = "GWmed", legend = :topright)
25+
plot!(forecast.quantiles, label = ["Quantiles" "" ""], color = "red", line = :dash)
26+

examples/inflow_lognormal.jl

Lines changed: 0 additions & 74 deletions
This file was deleted.

src/ScoreDrivenModels.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ include("distributions/exponential.jl")
3939
include("distributions/gamma.jl")
4040
include("distributions/logitnormal.jl")
4141
include("distributions/lognormal.jl")
42+
include("distributions/negativebinomial.jl")
4243
include("distributions/normal.jl")
4344
include("distributions/poisson.jl")
4445
include("distributions/tdist.jl")

src/distributions/chi.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ end
2727
function log_likelihood(::Type{Chi}, y::Vector{T}, param::Matrix{T}, n::Int) where T
2828
loglik = 0.0
2929
for t in 1:n
30-
loglik += + (1 - param[t, 1]/2)*log(2) + (param[t, 1] - 1) * log(y[t]) - (y[t]^2)/2 - loggamma(param[t, 1]/2)
30+
loglik += (1 - param[t, 1] / 2) * log(2) + (param[t, 1] - 1) * log(y[t]) - (y[t]^2)/2 - loggamma(param[t, 1]/2)
3131
end
3232
return -loglik
3333
end

src/distributions/common_interface.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const DISTS = [
88
Gamma,
99
LogitNormal,
1010
LogNormal,
11+
NegativeBinomial,
1112
Normal,
1213
Poisson,
1314
TDist,
@@ -23,6 +24,7 @@ export Beta,
2324
Gamma,
2425
LogitNormal,
2526
LogNormal,
27+
NegativeBinomial,
2628
Normal,
2729
Poisson,
2830
TDist,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
NegativeBinomial
3+
4+
* Parametrization
5+
parametrized in r, p
6+
7+
* Score
8+
9+
* Fisher Information
10+
11+
* `time_varying_params` map.
12+
13+
* Default link
14+
"""
15+
NegativeBinomial
16+
17+
function score!(score_til::Matrix{T}, y::Int, ::Type{NegativeBinomial}, param::Matrix{T}, t::Int) where T
18+
score_til[t, 1] = digamma(y + param[t, 1]) - digamma(param[t, 1]) + log(param[t, 2])
19+
score_til[t, 2] = param[t, 1] / param[t, 2] - y / (one(T) - param[t, 2])
20+
return
21+
end
22+
23+
function fisher_information!(aux::AuxiliaryLinAlg{T}, ::Type{NegativeBinomial}, param::Matrix{T}, t::Int) where T
24+
return error("Fisher information not implemented for NegativeBinomial distribution.")
25+
end
26+
27+
function log_likelihood(::Type{NegativeBinomial}, y::Vector{Int}, param::Matrix{T}, n::Int) where T
28+
loglik = zero(T)
29+
for t in 1:n
30+
loglik += loggamma(y[t] + param[t, 1]) - logfactorial(y[t]) - loggamma(param[t, 1]) +
31+
param[t, 1] * log(param[t, 2]) + y[t] * log(1 - param[t, 2])
32+
end
33+
return -loglik
34+
end
35+
36+
# Links
37+
function link!(param_tilde::Matrix{T}, ::Type{NegativeBinomial}, param::Matrix{T}, t::Int) where T
38+
param_tilde[t, 1] = link(LogLink, param[t, 1], zero(T))
39+
param_tilde[t, 2] = link(LogitLink, param[t, 2], zero(T), one(T))
40+
return
41+
end
42+
function unlink!(param::Matrix{T}, ::Type{NegativeBinomial}, param_tilde::Matrix{T}, t::Int) where T
43+
param[t, 1] = unlink(LogLink, param_tilde[t, 1], zero(T))
44+
param[t, 2] = unlink(LogitLink, param_tilde[t, 2], zero(T), one(T))
45+
return
46+
end
47+
function jacobian_link!(aux::AuxiliaryLinAlg{T}, ::Type{NegativeBinomial}, param::Matrix{T}, t::Int) where T
48+
aux.jac[1] = jacobian_link(LogLink, param[t, 1], zero(T))
49+
aux.jac[2] = jacobian_link(LogitLink, param[t, 2], zero(T), one(T))
50+
return
51+
end
52+
53+
# utils
54+
function update_dist(::Type{NegativeBinomial}, param::Matrix{T}, t::Int) where T
55+
return NegativeBinomial(param[t, 1], param[t, 2])
56+
end
57+
58+
function params_sdm(d::NegativeBinomial)
59+
return Distributions.params(d)
60+
end
61+
62+
function num_params(::Type{NegativeBinomial})
63+
return 2
64+
end

0 commit comments

Comments
 (0)