I am trying to implement a copula regression model by leveraging Turing and copulas in Julia.
The author of copula implemented a nice working example as below
using Copulas, Distributions, Random, Turing, Plots, StatsPlots
Random.seed!(123)
D = SklarDist(ClaytonCopula(3,7), (Exponential(1.0), Pareto(3.0), Exponential(2.0)))
draws = rand(D, 2_000)
@model function copula(X)
# Priors
θ ~ TruncatedNormal(1.0, 1.0, 0, Inf)
θ₁ ~ TruncatedNormal(1.0, 1.0, 0, Inf)
θ₂ ~ TruncatedNormal(1.0, 1.0, 0, Inf)
θ₃ ~ TruncatedNormal(1.0, 1.0, 0, Inf)
# Marginals distributions and copula
X₁ = Exponential(θ₁)
X₂ = Pareto(θ₂)
X₃ = Exponential(θ₃)
C = ClaytonCopula(3,θ)
D = SklarDist(C, (X₁, X₂, X₃))
Turing.Turing.@addlogprob! loglikelihood(D, X)
end
sampler = NUTS() # MH() works too
chain = sample(copula(draws), sampler, MCMCThreads(), 1_00, 4)
plot(chain)
I would like to implement a regression equivalent of that model. I have a simple example below. But NUTS and HMC samplers do not work. PG works but does not produce a reliable results.
using Random
Random.seed!(43);
n = 200
p = 2
X = randn(n, p)
β1 = randn(p)
Y = X*hcat(β1,β1) + transpose(rand(SklarDist(GaussianCopula([1 .8; .8 1]), (Normal(0.0, 1.), Normal(0.0,1.0))), n))
#-- Look at the data
cornerplot(Y, compact=true)
#-- Model
@model function copulaReg(Y, X)
n, K = size(X)
# Priors
ρ ~ truncated(Normal(0,.3), -1, 1) #-- Corelated
θ ~ Normal(0.,1.)
θ₁ ~ Normal(0.,1.)
θ₂ ~ Normal(0.,1.)
β1 ~ filldist(Normal(0., 1.), K)
β2 ~ filldist(Normal(0., 1.), K)
β ~ filldist(Normal(0., 1.), K)
#-- Regression parameters
μ1 = zeros(n)
μ2 = zeros(n)
for i in 1:n
μ1[i] = θ₁ .+ sum(X[i,:].* β1)
μ2[i] = θ₂ .+ sum(X[i,:].* β2)
#Turing.Turing.@addlogprob! loglikelihood(SklarDist(GaussianCopula([1. ρ; ρ 1.0]), (Normal(μ1[i], σ1), Normal(μ2[i], σ2))), Y[i,:])
Turing.Turing.@addlogprob! loglikelihood(SklarDist(GaussianCopula([1. ρ; ρ 1.0]), (Normal(μ1[i], 1.), Normal(μ2[i], 1.))), Y[i,:])
end
end
#-- sampler
sampler = NUTS() # doe not work
sampler = PG(10) # works but gives weird results!!
#-- sample from the posterior
chain = sample(copulaReg(Y, X), sampler, MCMCThreads(), 2_000, 3)
describe(chain)
I am not sure why NUTS and HMC are not working on this. Any help on this will be greatly appreciated. Thank you.