Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change ARStep to reverse AR parameters #441

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions EpiAware/docs/src/showcase/replications/mishra-2020/index.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
### A Pluto.jl notebook ###
# v0.19.43
# v0.19.46

using Markdown
using InteractiveUtils
Expand Down Expand Up @@ -545,7 +545,7 @@ let
c = :black,
lab = "prior")

p3 = histogram(inference_results.samples["latent.damp_AR[1]"],
p3 = histogram(inference_results.samples["latent.rev_damp_AR[2]"],
lab = "chain " .* string.([1 2 3 4]),
fillalpha = 0.4,
lw = 0,
Expand All @@ -556,7 +556,7 @@ let
c = :black,
lab = "prior")

p4 = histogram(inference_results.samples["latent.damp_AR[2]"],
p4 = histogram(inference_results.samples["latent.rev_damp_AR[1]"],
lab = "chain " .* string.([1 2 3 4]),
fillalpha = 0.4,
lw = 0,
Expand Down
25 changes: 15 additions & 10 deletions EpiAware/src/EpiLatentModels/models/AR.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct AR{D <: Sampleable, S <: Sampleable, I <: Sampleable, P <: Int} <:
init_prior::I
"Order of the AR model."
p::P
"Reversed order of the damping coefficients for computation."
rev_damp_prior::D
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would we want both damp_prior and reverse damp prior in the struct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically for having ar_model.damp_prior, I'm OK with getting rid of it but we need to be clear that the field is in reverse to expected order.

function AR(damp_prior::Distribution, std_prior::Distribution,
init_prior::Distribution; p::Int = 1)
damp_priors = fill(damp_prior, p)
Expand All @@ -43,17 +45,18 @@ struct AR{D <: Sampleable, S <: Sampleable, I <: Sampleable, P <: Int} <:
p = length(damp_priors)
damp_prior = _expand_dist(damp_priors)
init_prior = _expand_dist(init_priors)
return AR(damp_prior, std_prior, init_prior, p)
rev_damp_prior = _expand_dist(reverse(damp_priors))
return AR(damp_prior, std_prior, init_prior, p, rev_damp_prior)
end

function AR(damp_prior::Distribution, std_prior::Distribution,
init_prior::Distribution, p::Int)
init_prior::Distribution, p::Int, rev_damp_prior::Distribution)
@assert p>0 "p must be greater than 0"
@assert length(damp_prior)==length(init_prior) "damp_prior and init_prior must have the same length"
@assert p==length(damp_prior) "p must be equal to the length of damp_prior"
new{typeof(damp_prior), typeof(std_prior), typeof(init_prior), typeof(p)}(
damp_prior, std_prior, init_prior, p
)
new{typeof(damp_prior), typeof(std_prior),
typeof(init_prior), typeof(p)}(
damp_prior, std_prior, init_prior, p, rev_damp_prior)
end
end

Expand All @@ -78,26 +81,28 @@ Generate a latent AR series.

σ_AR ~ latent_model.std_prior
ar_init ~ latent_model.init_prior
damp_AR ~ latent_model.damp_prior
rev_damp_AR ~ latent_model.rev_damp_prior
ϵ_t ~ filldist(Normal(), n - p)

ar = accumulate_scan(ARStep(damp_AR), ar_init, σ_AR * ϵ_t)
ar = accumulate_scan(ARStep(rev_damp_AR), ar_init, σ_AR * ϵ_t)

return ar
end

@doc raw"
The autoregressive (AR) step function struct
The autoregressive (AR) step function struct.

Note that the AR parameters are stored in reverse order.
"
struct ARStep{D <: AbstractVector{<:Real}} <: AbstractAccumulationStep
damp_AR::D
rev_damp_AR::D
end

@doc raw"
The autoregressive (AR) step function for use with `accumulate_scan`.
"
function (ar::ARStep)(state, ϵ)
new_val = dot(ar.damp_AR, state) + ϵ
new_val = dot(ar.rev_damp_AR, state) + ϵ
new_state = vcat(state[2:end], new_val)
return new_state
end
32 changes: 31 additions & 1 deletion EpiAware/test/EpiLatentModels/models/AR.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ end
end
end

@testitem "Testing AR process against theoretical properties" begin
@testitem "Testing AR(1) process against theoretical properties" begin
using DynamicPPL, Turing
using HypothesisTests: ExactOneSampleKSTest, pvalue
using Distributions
Expand Down Expand Up @@ -88,3 +88,33 @@ end
samples, Normal(theoretical_mean, sqrt(theoretical_var))) |> pvalue
@test ks_test_pval > 1e-6
end

@testitem "Testing AR(2) process against theoretical properties" begin
using DynamicPPL, Turing
using HypothesisTests: ExactOneSampleKSTest, pvalue
using Distributions, Random
Random.seed!(1234)

ar_model = AR(Normal(), HalfNormal(0.1), Normal(), p = 2)
n = 1000
damp = [0.8, 0.1]
σ_AR = 1.0

theoretical_mean = 0.0
theoretical_var = σ_AR^2 / (1 - damp[1]^2 - damp[2]^2 -
2 * (damp[1]^2 * damp[2] / (1 - damp[2])))
theoretical_1step_cov = theoretical_var * damp[1] / (1 - damp[2])
init_Σ = [theoretical_var theoretical_1step_cov; theoretical_1step_cov theoretical_var]

# Draw initial values from the stationary distribution so process starts at stationarity
ar_init = rand(MvNormal(zeros(2), init_Σ))

model = generate_latent(ar_model, n)
fixed_model = fix(model, (σ_AR = σ_AR, rev_damp_AR = reverse(damp), ar_init = ar_init))
# Draw samples from the model
X = fixed_model()

ks_test_pval = ExactOneSampleKSTest(
X, Normal(theoretical_mean, sqrt(theoretical_var))) |> pvalue
@test ks_test_pval > 1e-6
end
Loading