The chosen data is Government debt as percent of GDP (available at: https://www.google.com/publicdata/explore?ds=ds22a34krhq5p_#! ). The data contains the yearly debt progression of European countries out of which a subset of countries is analyzed here. The range of data was limited between years 2002-2016 for consistent data availability.
The problem addressed is the prediction of the debt progress based on history data using gaussian processes.
library(ggplot2)
library(reshape2)
library(ggthemes)
data <- read.csv("data.tsv",header=T,sep="\t",na.strings = ":",row.names = 1)
data2 <- data[,-c(1:7)]
l <- rownames(data2)
n <- data2$name
data2 <- as.data.frame(t(data2[,-1]))
colnames(data2) <- n
data2$myfactor <- factor(row.names(data2))
colnames(data2) <- l
data2 <- data2[,-c(33)]
data2$year <- c(2003:2016)
cnames <- colnames(data2)
df_melt <- melt(data2[, cnames], id="year")
gg <- ggplot(df_melt, aes(x=year))
gg + geom_line(aes(y=value, color=variable), size=1) + scale_color_discrete(name="Legend") +
ylab("% of GDP") +
ggtitle("General government gross debt % of GDP") +
theme_igray()We have developed two models here. We start with separate models for each countries. In the second part of this report we develop the model further and add hierarchical components as well.
The data is a time-series data by nature which makes Gaussian Processes a natural choice. The growing trend of the data is incorporated into the model as a linear component:
Then we have the exponentiated quadratic kernel as a covariance:
And together these compose the full separate model (in addition to the random noise sigma):
There are in total four initial prior choices in the model. We have listed our inital choices for the priors here, however, these will adjusted later due to some convergence issues. The initial prior choices are:
In addition, there are two parameters and for which standard prior choices were used. is needed for the Cholesky decomposition to generate the covariance matrix, is used to incorporate the random, unexplainable variation in the model. Both use standard prior choices .
These two parameters form the linear trend for the model. The intercept is restricted to positive and left vague, , which covers the range of government debts in year 2002. The slope parameter is also fairly vague but possibly non-positive as well, .
Alpha is the strength parameter for the Gaussian Process. The vague prior was the initial choice and seems to provide sufficient strength for the variation.
Length_param controls the speed at which the correlation effect decays as distance between data points grows (lower value = faster decay). Since the amount of data points is low and the data behaves extremely irregularly, using a vague prior for the length parameter resulted in low values ( < 1.0) value that overfit the data. Using prior choice , the model puts less emphasis on the high frequency fluctuation and fit becomes smoother. We think this is reasonable, because the financial crisis at 2008 is impossible to explain based only on this dataset, so we want to prevent overfitting as much as possible.
data {
// Samples used for fitting
int<lower=1> N_is;
real x_is[N_is];
vector[N_is] y_is;
// Samples used for prediction
int<lower=1> N_pred;
real x_pred[N_pred];
}
transformed data {
int<lower=1> N = N_is + N_pred;
real x[N];
vector[N] xv;
real jitter = 1e-9;
for (n in 1:N_is) x[n] = x_is[n];
for (n in 1:N_pred) x[N_is + n] = x_pred[n]; // Join the in sample and prediction features.
xv = to_vector(x);
}
parameters {
real<lower=0> alpha; // Strength parameter for GP
real<lower=1> length_param; // Lag parameter
real<lower=0> sigma; // Random, unexplained noise
vector[N] eta; // Gaussian 0,1 for generating the covariance from Cholesky decompose
real<lower=0> mu_0;
real mu_b;
}
transformed parameters {
vector[N] f;
{
matrix[N, N] K = cov_exp_quad(x, alpha, length_param) + diag_matrix(rep_vector(jitter, N));
matrix[N, N] L_K = cholesky_decompose(K);
f = mu_0 + mu_b * xv + L_K * eta;
}
}
model {
alpha ~ normal(0, 1);
//length_param ~ gamma(4,4); // Vague prior
length_param ~ weibull(10, 3); // More informative prior
sigma ~ normal(0, 1);
eta ~ normal(0, 1);
mu_0 ~ normal(0, 100);
mu_b ~ normal(0, 5);
y_is ~ normal(f[1:N_is], sigma);
}
generated quantities {
vector[N] y_pred;
vector[N_is] log_lik;
for (n in 1:N) y_pred[n] = normal_rng(f[n], sigma);
for (n in 1:N_is) log_lik[n] = normal_lpdf(y_is[n] | f[n], sigma);
}
Training of the initial separate model and plots for different countries.
library(rstan)
rstan_options(auto_write = TRUE)
options(mc.cores = parallel::detectCores())
data = read.csv('data.csv', row.names=1)
data = data.frame(t(data))
data[,'year'] = seq(2002, 2016, by=1)
gp <- function(country_id,country_name) {
cc = country_id
y = data[,cc]
x = 1:length(y)
ss = 3
y_is = y[1:(length(y) - ss)]
x_is = x[1:(length(x) - ss)]
N_is = length(x_is)
y_os = tail(y, (ss + 1))
x_os = tail(x, (ss + 1))
x_pred = tail(x, ss)
N_pred = length(x_pred)
gp_model = 'debt_gp_linear.stan'
fit_gp <- stan(file=gp_model,
data=list(x_is = x_is,
y_is = y_is,
N_is = N_is,
x_pred = x_pred,
N_pred),
iter=200,
chains=3)
sample = extract(fit_gp)
sample_preds = data.frame(sample$y_pred)
sample_quantiles <- apply(sample_preds,2,function(x){quantile(x,c(0.05,0.5,0.95))})
sample_data <- data.frame(low = sample_quantiles[1,],
med = sample_quantiles[2,],
high = sample_quantiles[3,],
x = x)
training_data <- data.frame(x=x_is, obs=y_is)
validation_data <- data.frame(x=x_os, obs=y_os)
cols <- c("GP median"="black","GP 90% percentile"="lightblue","True debt"="red")
ggplot(sample_data, aes(x=x, y=med)) +
geom_ribbon(aes(x=x,ymin=low,ymax=high,colour="GP 90% percentile"),alpha=0.6,fill="lightblue") +
geom_line(aes(x=x,y=med,colour="GP median")) +
geom_point() +
geom_line(data=training_data, aes(x=x, y=obs,colour="True debt")) +
geom_line(data=validation_data, aes(x=x, y=obs,colour="True debt"), linetype="dashed") +
xlab('year') +
ylab('Debt (% of GDP)') +
ggtitle(sprintf('Government debt, country = \'%s\'', country_name)) +
scale_colour_manual(name="Colour",values=cols) +
theme(plot.title = element_text(hjust = 0.5))
}
gp('FI','Finland')gp('SE','Sweden')gp('EL','Greece')Analysis is done using a separate model generated for Finland.
cc = 'FI'
y = data[,cc]
x = 1:length(y)
ss = 3
y_is = y[1:(length(y) - ss)]
x_is = x[1:(length(x) - ss)]
N_is = length(x_is)
y_os = tail(y, (ss + 1))
x_os = tail(x, (ss + 1))
x_pred = tail(x, ss)
N_pred = length(x_pred)
gp_model = 'debt_gp_linear_w.stan'
fit_gp <- stan(file=gp_model,
data=list(x_is = x_is,
y_is = y_is,
N_is = N_is,
x_pred = x_pred,
N_pred),
iter=1000,
chains=10,control=list(adapt_delta=0.99,max_treedepth=15))fit_gpInference for Stan model: debt_gp_linear_w.
10 chains, each with iter=1000; warmup=500; thin=1;
post-warmup draws per chain=500, total post-warmup draws=5000.
mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
alpha 3.19 0.01 0.54 2.18 2.82 3.17 3.55 4.33 2463 1.00
length_param 1.80 0.01 0.27 1.21 1.63 1.83 2.00 2.23 660 1.01
sigma 1.62 0.02 0.54 0.48 1.28 1.59 1.93 2.77 659 1.01
eta[1] 1.17 0.02 0.88 -0.55 0.58 1.16 1.76 2.91 2583 1.00
eta[2] 0.63 0.01 0.70 -0.81 0.20 0.66 1.10 1.97 3879 1.00
eta[3] -0.55 0.01 0.83 -2.21 -1.11 -0.52 0.01 1.03 3463 1.00
eta[4] -1.53 0.02 0.93 -3.36 -2.17 -1.51 -0.86 0.20 2826 1.00
eta[5] -2.01 0.02 0.88 -3.71 -2.60 -2.02 -1.41 -0.32 2377 1.00
eta[6] -1.20 0.04 1.14 -3.51 -1.97 -1.14 -0.41 0.93 961 1.01
eta[7] 0.27 0.01 0.93 -1.57 -0.36 0.29 0.89 2.08 5000 1.00
eta[8] 0.50 0.02 0.86 -1.25 -0.06 0.50 1.07 2.15 2587 1.00
eta[9] 0.21 0.02 0.98 -1.63 -0.49 0.22 0.88 2.13 2093 1.01
eta[10] 0.76 0.01 0.91 -1.01 0.16 0.75 1.36 2.56 5000 1.00
eta[11] 0.73 0.01 0.97 -1.20 0.07 0.73 1.40 2.59 5000 1.00
eta[12] 0.17 0.01 0.97 -1.72 -0.48 0.19 0.84 2.03 5000 1.00
eta[13] 0.00 0.01 1.00 -1.94 -0.67 -0.02 0.66 1.97 5000 1.00
eta[14] -0.02 0.01 0.98 -1.91 -0.68 -0.01 0.64 1.84 5000 1.00
eta[15] 0.00 0.01 1.00 -1.96 -0.69 -0.02 0.65 2.02 5000 1.00
mu_0 34.99 0.07 3.38 28.29 32.75 35.04 37.21 41.56 2148 1.00
mu_b 1.40 0.01 0.43 0.55 1.11 1.40 1.68 2.28 2223 1.00
f[1] 40.07 0.02 1.41 37.13 39.20 40.11 40.94 42.93 5000 1.00
f[2] 41.99 0.02 1.16 39.44 41.30 42.08 42.78 44.06 3577 1.00
f[3] 42.11 0.02 1.11 39.72 41.44 42.19 42.85 44.13 5000 1.00
f[4] 40.35 0.01 1.05 38.13 39.70 40.37 41.04 42.37 5000 1.00
f[5] 37.49 0.02 1.08 35.38 36.80 37.49 38.18 39.68 5000 1.00
f[6] 35.11 0.03 1.39 32.83 34.11 34.94 35.94 38.26 2122 1.00
f[7] 35.99 0.05 1.57 32.99 34.96 35.94 36.95 39.25 920 1.01
f[8] 40.70 0.02 1.10 38.56 40.00 40.69 41.41 42.87 4150 1.00
f[9] 45.94 0.02 1.10 43.69 45.23 45.96 46.70 47.99 2672 1.00
f[10] 49.87 0.02 1.08 47.73 49.15 49.86 50.59 52.00 2352 1.00
f[11] 53.17 0.02 1.10 50.87 52.51 53.22 53.90 55.20 5000 1.00
f[12] 55.50 0.03 1.49 52.22 54.62 55.65 56.52 58.10 2674 1.00
f[13] 56.37 0.04 2.59 51.02 54.71 56.42 58.15 61.26 5000 1.00
f[14] 56.53 0.06 3.92 48.75 53.93 56.57 59.15 64.11 3893 1.00
f[15] 56.90 0.08 4.80 47.55 53.66 56.89 60.03 66.23 3491 1.00
y_pred[1] 40.09 0.03 2.21 35.55 38.78 40.12 41.47 44.46 5000 1.00
y_pred[2] 41.97 0.03 2.08 37.41 40.78 42.11 43.24 45.87 5000 1.00
y_pred[3] 42.07 0.03 2.06 37.62 40.90 42.17 43.39 46.01 4622 1.00
y_pred[4] 40.37 0.03 2.01 36.12 39.22 40.37 41.61 44.32 5000 1.00
y_pred[5] 37.46 0.03 1.99 33.42 36.20 37.48 38.66 41.55 4954 1.00
y_pred[6] 35.11 0.04 2.19 31.30 33.68 34.89 36.37 40.12 3319 1.00
y_pred[7] 36.01 0.06 2.32 32.19 34.38 35.82 37.38 41.16 1598 1.00
y_pred[8] 40.70 0.03 2.05 36.54 39.44 40.72 41.90 44.90 5000 1.00
y_pred[9] 45.96 0.03 2.04 41.60 44.75 46.06 47.23 49.88 5000 1.00
y_pred[10] 49.87 0.03 2.05 45.76 48.62 49.82 51.17 54.05 4480 1.00
y_pred[11] 53.22 0.03 2.06 48.98 51.98 53.30 54.43 57.22 5000 1.00
y_pred[12] 55.53 0.04 2.25 50.50 54.22 55.69 56.96 59.55 4060 1.00
y_pred[13] 56.35 0.04 3.08 49.90 54.44 56.43 58.41 62.17 5000 1.00
y_pred[14] 56.53 0.07 4.28 47.90 53.64 56.66 59.38 64.76 4141 1.00
y_pred[15] 56.90 0.08 5.09 47.04 53.49 56.81 60.32 66.59 3727 1.00
log_lik[1] -1.70 0.02 0.64 -3.22 -1.96 -1.63 -1.35 -0.53 830 1.01
log_lik[2] -1.68 0.02 0.59 -3.05 -1.96 -1.62 -1.35 -0.54 820 1.01
log_lik[3] -1.62 0.02 0.53 -2.79 -1.88 -1.59 -1.33 -0.51 741 1.01
log_lik[4] -1.60 0.02 0.49 -2.61 -1.84 -1.59 -1.35 -0.48 767 1.01
log_lik[5] -1.70 0.02 0.58 -3.04 -1.94 -1.66 -1.41 -0.53 848 1.01
log_lik[6] -1.80 0.02 0.73 -3.54 -2.16 -1.69 -1.34 -0.55 989 1.01
log_lik[7] -3.65 0.05 1.61 -7.31 -4.57 -3.52 -2.56 -0.76 1089 1.00
log_lik[8] -1.82 0.02 0.66 -3.45 -2.08 -1.74 -1.48 -0.54 1023 1.01
log_lik[9] -1.82 0.02 0.68 -3.40 -2.14 -1.77 -1.46 -0.48 864 1.01
log_lik[10] -2.01 0.02 0.79 -3.87 -2.32 -1.88 -1.58 -0.56 1116 1.01
log_lik[11] -1.67 0.02 0.57 -2.99 -1.91 -1.62 -1.36 -0.50 863 1.01
log_lik[12] -1.87 0.03 0.84 -3.97 -2.18 -1.71 -1.38 -0.51 1119 1.00
lp__ -20.82 0.20 4.32 -29.40 -23.34 -20.79 -18.36 -11.40 482 1.02
Samples were drawn using NUTS(diag_e) at Sat Dec 9 11:11:30 2017.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at
convergence, Rhat=1).
All values are below 1.1 so our MCMC simulations convergences well.
source("stan_utility.R")
check_treedepth(fit_gp)[1] "0 of 5000 iterations saturated the maximum tree depth of 10 (0%)"
Monte Carlo simulations did not hit the maximum trajectory length, so we don’t need to increase the tree depth.
check_energy(fit_gp)[1] "E-BFMI indicated no pathological behavior"
check_div(fit_gp)[1] "21 of 5000 iterations ended with a divergence (0.42%)"
[1] " Try running with larger adapt_delta to remove the divergences"
Divergences does not vanish completely even though adapt_delta value is 0.999. Let’s check the posterior of length_param (length-scale) and sigma, which is the unexpleinable variance in the data, to see if divergences are false positives or caused by an actual problem.
c_dark <- c("#8F272780")
green <- c("#00FF0080")
partition <- partition_div(fit_gp)
div_params <- partition[[1]]
nondiv_params <- partition[[2]]
par(mar = c(4, 4, 0.5, 0.5))
plot(nondiv_params$length_param, nondiv_params$sigma,
col=c_dark, pch=16, cex=0.8, xlab="length_param", ylab="sigma",
xlim=c(0, 4), ylim=c(0,7))
points(div_params$length_param, div_params$sigma,
col=green, pch=16, cex=0.8)As can be seen from the plot, all the divergences are clustered to the bottom left where the posterior abrupts quickly. So there is indeed problem with our model. Monte Carlo is not able to explore that area properly so our posterior is slightly biased.
One issue we see in the posterior plot above is that some simulations of the length parameter in our exponential gaussian kernel fall below 1. This is a possible cause of overfit that might result in divergences, since our data contains only yearly observations.
We try to fix our model by adjusting our prior for length_param (length-scale). At the moment we have , which might give us values between 0 and 1. We can fix this by moving our prior further away from 1 and clipping the prior so that it can only get values higher than 1. Our prior for length-scale is with minimum of 1. After adjusting the prior, the convergence analytics are performed again:
check_treedepth(fit_gp)[1] "0 of 5000 iterations saturated the maximum tree depth of 10 (0%)"
check_energy(fit_gp)[1] "E-BFMI indicated no pathological behavior"
check_div(fit_gp)[1] "0 of 5000 iterations ended with a divergence (0%)"
Changing the prior of the length parameter seems to fix our divergence issues.
sample = extract(fit_gp)
sample_preds = data.frame(sample$y_pred)
sample_quantiles <- apply(sample_preds,2,function(x){quantile(x,c(0.05,0.5,0.95))})
sample_data <- data.frame(low = sample_quantiles[1,],
med = sample_quantiles[2,],
high = sample_quantiles[3,],
x = x)
training_data <- data.frame(x=x_is, obs=y_is)
validation_data <- data.frame(x=x_os, obs=y_os)
cols <- c("GP median"="black","GP 90% percentile"="lightblue","True debt"="red")
ggplot(sample_data, aes(x=x, y=med)) +
geom_ribbon(aes(x=x,ymin=low,ymax=high,colour="GP 90% percentile"),alpha=0.6,fill="lightblue") +
geom_line(aes(x=x,y=med,colour="GP median")) +
geom_point() +
geom_line(data=training_data, aes(x=x, y=obs,colour="True debt")) +
geom_line(data=validation_data, aes(x=x, y=obs,colour="True debt"), linetype="dashed") +
xlab('year') +
ylab('Debt (% of GDP)') +
ggtitle(sprintf('Government debt, country = Finland')) +
scale_colour_manual(name="Colour",values=cols) +
theme(plot.title = element_text(hjust = 0.5))The empirical data stays withing the 90% confidence interval in all cases apart from the Year 7 (corresponding to year 2008). This is the year of bank crisis and is therefore an anomaly to the process as does not follow the natural progression explained by the model.
Changing the prior for the length param smoothens the median compared to the original prior choice. This is natural, as increasing the length parameter increases time scale at which the correlation decays. In other words, the effect of the time steps further away contribute more to the value, thus reducing the frequency of the signal.
The out of sample predictions (dashed red line) fall also within the cofidence interval. However, the dataset is small and therefore making accurate predictions is not a trivial task without additional knowledge.
library(bayesplot)This is bayesplot version 1.4.0
- Plotting theme set to bayesplot::theme_default()
- Online documentation at mc-stan.org/bayesplot
sample = extract(fit_gp)
ppc_dens_overlay(y=y_is, yrep=sample$y_pred[,1:(length(y) - ss)])+ggtitle("Posterior predictive for Finland") + xlab("Debt (% of GDP)")Simulated draws from the posterior distribution follow the empirical data distribution roughly. Huge variance in draws at 40-45 is due the fact that our informative prior smoothens the dip (2008 financial crisis) quite heavily so our posterior gives more probablity mass around 40-45 compared to the empirical data.
We are focusing our sensitivity analysis on different priors for length_param which is the length-scale parameter for gaussian process. Ideally the sensitivity analysis should be performed for the other priors as well, however, due to time constraints we have chose the the length parameter as changing it is expected to have the most notable effect.
cc = 'FI'
y = data[,cc]
x = 1:length(y)
ss = 3
y_is = y[1:(length(y) - ss)]
x_is = x[1:(length(x) - ss)]
N_is = length(x_is)
y_os = tail(y, (ss + 1))
x_os = tail(x, (ss + 1))
x_pred = tail(x, ss)
N_pred = length(x_pred)
prior_check <- function(model_name) {
fit_gp_tmp <- stan(file=model_name,
data=list(x_is = x_is,
y_is = y_is,
N_is = N_is,
x_pred = x_pred,
N_pred),
iter=1000,
chains=10,control=list(adapt_delta=0.99,max_treedepth=15))
sample <- extract(fit_gp_tmp)
sample_preds <- data.frame(sample$y_pred)
sample_quantiles <- apply(sample_preds,2,function(x){quantile(x,c(0.05,0.5,0.95))})
sample_data <- data.frame(low = sample_quantiles[1,],
med = sample_quantiles[2,],
high = sample_quantiles[3,],
x = x)
training_data <- data.frame(x=x_is, obs=y_is)
validation_data <- data.frame(x=x_os, obs=y_os)
return(list(s=sample_data, t=training_data, v=validation_data,m=fit_gp_tmp))
}
sample1 <- prior_check('debt_gp_linear.stan')
sample2 <- prior_check('debt_gp_linear2.stan')
sample3 <- prior_check('debt_gp_linear3.stan')
#cols <- c("Weibull(10,2)"="black","Gamma(4,4)"="green","Uniform prior"="blue","True debt"="red")
ggplot(sample1$s, aes(x=x, y=med)) +
geom_line(aes(x=x,y=med,colour="Weibull(15,3)")) +
geom_line(data=sample2$s, aes(x=x,y=med,colour="Gamma(4,4)")) +
geom_line(data=sample3$s, aes(x=x,y=med,colour="Uniform prior")) +
geom_line(data=sample1$t, aes(x=x, y=obs,colour="True debt")) +
geom_line(data=sample1$v, aes(x=x, y=obs,colour="True debt"), linetype="dashed") +
xlab('year') +
ylab('Debt (% of GDP)') +
ggtitle(sprintf('Government debt, country = Finland')) +
#scale_colour_manual(name="Colour",values=cols) +
theme(plot.title = element_text(hjust = 0.5))As can be seen from the plot, prior information about length-scale has an noticable effect on the outcome. Our choice for informative prior smoothens the curve the most. Using non-informative and vague prior overfits model quite much. Based only on visual analysis our informative prior seems the most reasonable, because the data contain datapoints that are basically impossible to explain based only on this data (financial crisis). However, our model is sensitive to the choice of prior for length scale.
library(loo)This is loo version 1.1.0
ll <- extract_log_lik(sample1$m)
l <- loo(ll)Some Pareto k diagnostic values are too high. See help('pareto-k-diagnostic') for details.
lComputed from 5000 by 12 log-likelihood matrix
Estimate SE
elpd_loo -30.8 4.2
p_loo 5.8 2.1
looic 61.6 8.4
Pareto k diagnostic values:
Count Pct
(-Inf, 0.5] (good) 6 50.0%
(0.5, 0.7] (ok) 5 41.7%
(0.7, 1] (bad) 1 8.3%
(1, Inf) (very bad) 0 0.0%
See help('pareto-k-diagnostic') for details.
ll <- extract_log_lik(sample2$m)
l <- loo(ll)Some Pareto k diagnostic values are too high. See help('pareto-k-diagnostic') for details.
lComputed from 5000 by 12 log-likelihood matrix
Estimate SE
elpd_loo -21.4 2.3
p_loo 16.1 2.1
looic 42.9 4.6
Pareto k diagnostic values:
Count Pct
(-Inf, 0.5] (good) 0 0.0%
(0.5, 0.7] (ok) 6 50.0%
(0.7, 1] (bad) 6 50.0%
(1, Inf) (very bad) 0 0.0%
See help('pareto-k-diagnostic') for details.
ll <- extract_log_lik(sample3$m)
l <- loo(ll)Some Pareto k diagnostic values are too high. See help('pareto-k-diagnostic') for details.
lComputed from 5000 by 12 log-likelihood matrix
Estimate SE
elpd_loo -25.4 3.4
p_loo 14.8 3.1
looic 50.9 6.8
Pareto k diagnostic values:
Count Pct
(-Inf, 0.5] (good) 0 0.0%
(0.5, 0.7] (ok) 6 50.0%
(0.7, 1] (bad) 6 50.0%
(1, Inf) (very bad) 0 0.0%
See help('pareto-k-diagnostic') for details.
Comparing the models with different prior using psis-LOO is not possible, because models for non informative prior and vague prior get Pareto k values >1.0. Therefore we should use more computationally expenisive methods, such as standard cross-validation, to evalute the performance of our models. However pareto-k values for our informative prior model are quite reasonble: only 2 values are above 0.7 so it is possible to compare that model to our hierarchical model.
Our second model tries to incorporate more information to each model by adding hierarchical structure. The idea is to add global trend and gaussian process to the separate model in the previous section. The global components will be affected by all the EU countries in our dataset.
Similarly to the separate model, the components are formed as:
And:
data {
// Samples used for fitting
int<lower=1> N_is;
int country_ind_is[N_is];
int year_ind_is[N_is];
vector[N_is] y_is;
int<lower=1> N_years_is;
int<lower=1> N_years_pred;
int<lower=1> N_countries;
// The amount of predictions
}
transformed data {
// All data points
int<lower=1> N = N_is + N_years_pred * N_countries;
int<lower=1> year_ind[N];
int<lower=1> country_ind[N];
int<lower=1> N_years = N_years_is + N_years_pred;
real<lower=1> years[N_years];
real jitter = 1e-9;
for (year in 1:N_years) years[year] = year;
// Add in sample year indices
for (n in 1:N_is){
year_ind[n] = year_ind_is[n];
country_ind[n] = country_ind_is[n];
}
// Create out sample year indices
for (year in 1:N_years_pred)
for (country in 1:N_countries) {
country_ind[N_is + (year - 1) * N_countries + country] = country;
year_ind[N_is + (year - 1) * N_countries + country] = N_years_is + year;
}
}
parameters {
real<lower=0> alpha; // Strength parameter for GP
real<lower=0> length_param; // Lag parameter
real<lower=0> global_alpha;
real<lower=0> global_length;
real<lower=0> sigma; // Random, unexplained noise
matrix[N_years, N_countries] eta; // Gaussian 0,1 for generating the covariance from Cholesky decompose
vector[N_years] global_eta;
real mu_0[N_countries];
real mu_b[N_countries];
real<lower=0> global_mu_0;
real global_mu_b;
}
transformed parameters {
matrix[N_years, N_countries] GP_country;
vector[N_years] GP_global;
vector[N] f;
matrix[N_years, N_countries] linear_country;
real linear_global[N_years];
{
matrix[N_years, N_years] K = cov_exp_quad(years, alpha, length_param) + diag_matrix(rep_vector(jitter, N_years));
matrix[N_years, N_years] K_global = cov_exp_quad(years, global_alpha, global_length) + diag_matrix(rep_vector(jitter, N_years));
matrix[N_years, N_years] L_K = cholesky_decompose(K);
matrix[N_years, N_years] L_K_global = cholesky_decompose(K_global);
GP_country = L_K * eta;
GP_global = L_K_global * global_eta;
for (year in 1:N_years) {
linear_global[year] = global_mu_0 + global_mu_b * year;
for (country in 1:N_countries){
linear_country[year, country] = mu_0[country] + mu_b[country] * year;
}
}
for (n in 1:N){
f[n] = linear_country[year_ind[n], country_ind[n]]
+ linear_global[year_ind[n]]
+ GP_country[year_ind[n], country_ind[n]]
+ GP_global[year_ind[n]];
}
}
}
model {
alpha ~ normal(0, 1);
global_alpha ~ normal(0, 1);
//length_param ~ gamma(4,4); // Vague prior
length_param ~ weibull(15, 3 ); // More informative prior
global_length ~ weibull(15, 3);
sigma ~ normal(0, 1);
to_vector(eta) ~ normal(0, 1);
to_vector(global_eta) ~ normal(0, 1);
mu_0 ~ normal(0, 100);
mu_b ~ normal(0, 5);
global_mu_0 ~ normal(0, 100);
global_mu_b ~ normal(0, 5);
y_is ~ normal(f[1:N_is], sigma);
}
generated quantities {
vector[N] y_pred;
vector[N_is] log_lik;
vector[N] year_indicators;
vector[N] country_indicators;
year_indicators = to_vector(year_ind);
country_indicators = to_vector(country_ind);
for (n in 1:N) y_pred[n] = normal_rng(f[n], sigma);
for (n in 1:N_is) log_lik[n] = normal_lpdf(y_is[n] | f[n], sigma);
}
data = read.csv('data.csv', row.names=1)
data = data.frame(t(data))
y_is = unlist(data,use.names = F)
country_ind_is = rep(1:ncol(data),each=15)
year_ind_is = rep(1:15,ncol(data))
N_is = length(y_is)
N_countries = ncol(data)
N_years_pred = 3
N_years_is = 15
# Simple GP + linear model
gp_model_hier = 'debt_gp_hierarchical.stan'
fit_gp_h <- stan(file=gp_model_hier,
data=list(y_is = y_is,
country_ind_is = country_ind_is,
year_ind_is = year_ind_is,
N_years_is = 15,
N_years_pred = N_years_pred,
N_is = N_is,
N_countries = N_countries),
iter=1000,
chains=10)
sample <- extract(fit_gp_h)sample_preds <- data.frame(sample$y_pred[,sample$country_indicators[1,] == match("FI",colnames(data))])
sample_quantiles <- apply(sample_preds,2,function(x){quantile(x,c(0.05,0.5,0.95))})
x = 1:18
sample_data <- data.frame(low = sample_quantiles[1,],
med = sample_quantiles[2,],
high = sample_quantiles[3,],
x = x)
training_data <- data.frame(x=1:15, obs=data[,"FI"])
#validation_data <- data.frame(x=15:18, obs=y_os)
cols <- c("GP median"="black","GP 90% percentile"="lightblue","True debt"="red")
ggplot(sample_data, aes(x=x, y=med)) +
geom_ribbon(aes(x=x,ymin=low,ymax=high,colour="GP 90% percentile"),alpha=0.6,fill="lightblue") +
geom_line(aes(x=x,y=med,colour="GP median")) +
geom_point() +
geom_line(data=training_data, aes(x=x, y=obs,colour="True debt")) +
#geom_line(data=validation_data, aes(x=x, y=obs,colour="True debt"), linetype="dashed") +
xlab('year') +
ylab('Debt (% of GDP)') +
ggtitle(sprintf('Government debt, country = Finland (hierarchical model)')) +
scale_colour_manual(name="Colour",values=cols) +
theme(plot.title = element_text(hjust = 0.5))By adding more data using hierarcical gaussian processes, our model gives tighter error bounds than the separate model for Finland. As expected the uncertainty increases after there are no observed data points.
fit_gp_hInference for Stan model: debt_gp_hierarchical.
10 chains, each with iter=1000; warmup=500; thin=1;
post-warmup draws per chain=500, total post-warmup draws=5000.
mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
alpha 6.85 0.01 0.39 6.14 6.58 6.84 7.12 7.66 1422 1.00
length_param 2.37 0.00 0.12 2.14 2.29 2.36 2.44 2.60 549 1.01
global_alpha 3.44 0.01 0.52 2.52 3.07 3.41 3.77 4.54 2938 1.00
global_length 1.69 0.00 0.15 1.38 1.59 1.69 1.79 1.98 1508 1.01
sigma 1.72 0.00 0.09 1.57 1.66 1.72 1.78 1.90 1482 1.00
eta[1,1] -0.37 0.01 0.85 -2.05 -0.92 -0.37 0.18 1.32 3960 1.00
eta[1,2] 0.38 0.01 0.86 -1.36 -0.20 0.41 0.96 2.03 3763 1.00
eta[1,3] 1.29 0.01 0.87 -0.40 0.70 1.27 1.88 3.04 3786 1.00
eta[1,4] 0.95 0.01 0.87 -0.78 0.37 0.96 1.54 2.64 4085 1.00
eta[1,5] -0.29 0.01 0.87 -2.02 -0.86 -0.29 0.30 1.39 4065 1.00
eta[1,6] -0.68 0.01 0.86 -2.31 -1.26 -0.70 -0.13 1.10 3756 1.00
eta[1,7] 0.37 0.01 0.86 -1.31 -0.25 0.37 0.97 2.06 3705 1.00
eta[1,8] -0.13 0.01 0.89 -1.86 -0.73 -0.15 0.49 1.66 3796 1.00
eta[1,9] -0.15 0.01 0.88 -1.85 -0.75 -0.15 0.44 1.57 4239 1.00
eta[1,10] -0.16 0.01 0.89 -1.91 -0.77 -0.16 0.46 1.55 3606 1.00
eta[1,11] 0.27 0.01 0.86 -1.41 -0.31 0.26 0.82 1.95 3848 1.00
eta[1,12] 0.97 0.02 0.87 -0.79 0.40 0.98 1.55 2.72 3184 1.00
eta[1,13] -0.15 0.01 0.88 -1.86 -0.74 -0.15 0.46 1.56 4222 1.00
eta[1,14] -0.17 0.01 0.85 -1.85 -0.74 -0.18 0.40 1.51 3684 1.00
eta[1,15] 0.35 0.01 0.87 -1.29 -0.24 0.35 0.93 2.06 3951 1.00
eta[1,16] -0.01 0.01 0.86 -1.69 -0.58 -0.01 0.57 1.66 3747 1.00
eta[1,17] 0.11 0.02 0.86 -1.59 -0.47 0.10 0.68 1.81 3069 1.00
eta[1,18] -0.72 0.01 0.88 -2.41 -1.32 -0.72 -0.12 1.00 3579 1.00
eta[1,19] -0.34 0.01 0.86 -2.02 -0.92 -0.34 0.22 1.34 3418 1.00
eta[1,20] 0.00 0.01 0.86 -1.74 -0.58 0.00 0.57 1.68 3897 1.00
eta[1,21] 0.01 0.01 0.88 -1.73 -0.59 0.01 0.59 1.77 3495 1.00
eta[1,22] -0.31 0.01 0.86 -2.01 -0.88 -0.31 0.26 1.36 4004 1.00
eta[1,23] -0.07 0.01 0.86 -1.74 -0.66 -0.07 0.50 1.63 3575 1.00
eta[1,24] -0.31 0.01 0.88 -2.06 -0.90 -0.33 0.28 1.47 3550 1.00
eta[1,25] -0.08 0.02 0.87 -1.79 -0.66 -0.07 0.51 1.63 3085 1.00
eta[1,26] -0.14 0.01 0.87 -1.85 -0.73 -0.13 0.45 1.56 3883 1.00
eta[1,27] -0.14 0.01 0.87 -1.84 -0.72 -0.14 0.43 1.57 3952 1.00
eta[1,28] 0.32 0.01 0.87 -1.43 -0.26 0.32 0.90 2.05 3353 1.00
eta[1,29] -0.01 0.01 0.86 -1.68 -0.61 -0.03 0.57 1.67 3491 1.00
eta[1,30] 0.49 0.02 0.89 -1.27 -0.10 0.48 1.07 2.26 3148 1.00
eta[1,31] 0.55 0.01 0.87 -1.12 -0.04 0.55 1.14 2.29 3616 1.00
eta[1,32] -0.25 0.02 0.88 -1.97 -0.83 -0.25 0.35 1.44 3403 1.00
eta[2,1] -0.18 0.01 0.50 -1.17 -0.51 -0.18 0.16 0.80 5000 1.00
eta[2,2] -0.67 0.01 0.51 -1.68 -1.02 -0.67 -0.32 0.33 3493 1.00
eta[2,3] -1.15 0.01 0.52 -2.21 -1.49 -1.14 -0.80 -0.12 5000 1.00
eta[2,4] 0.56 0.01 0.51 -0.44 0.22 0.56 0.90 1.57 5000 1.00
eta[2,5] 0.37 0.01 0.51 -0.63 0.02 0.38 0.71 1.34 5000 1.00
eta[2,6] 0.88 0.01 0.52 -0.13 0.53 0.89 1.23 1.89 5000 1.00
eta[2,7] -0.04 0.01 0.52 -1.08 -0.39 -0.03 0.31 0.97 3539 1.00
eta[2,8] 0.19 0.01 0.50 -0.83 -0.15 0.19 0.53 1.14 3817 1.00
eta[2,9] 0.18 0.01 0.49 -0.79 -0.15 0.18 0.53 1.15 5000 1.00
eta[2,10] 0.05 0.01 0.50 -0.93 -0.28 0.05 0.39 1.02 3889 1.00
eta[2,11] -1.33 0.01 0.50 -2.30 -1.68 -1.33 -0.98 -0.36 5000 1.00
eta[2,12] -1.21 0.01 0.51 -2.21 -1.56 -1.21 -0.86 -0.21 5000 1.00
eta[2,13] 0.21 0.01 0.51 -0.79 -0.13 0.21 0.54 1.19 5000 1.00
eta[2,14] 0.21 0.01 0.49 -0.73 -0.12 0.21 0.54 1.16 5000 1.00
eta[2,15] 0.50 0.01 0.50 -0.48 0.16 0.50 0.83 1.48 5000 1.00
eta[2,16] 0.63 0.01 0.50 -0.36 0.29 0.63 0.96 1.59 5000 1.00
eta[2,17] 0.10 0.01 0.51 -0.92 -0.24 0.09 0.44 1.11 5000 1.00
eta[2,18] 0.15 0.01 0.50 -0.84 -0.19 0.15 0.48 1.14 5000 1.00
eta[2,19] -1.25 0.01 0.52 -2.26 -1.60 -1.24 -0.89 -0.24 5000 1.00
eta[2,20] -0.49 0.01 0.50 -1.47 -0.82 -0.48 -0.15 0.48 4072 1.00
eta[2,21] -0.54 0.01 0.50 -1.47 -0.88 -0.54 -0.20 0.44 4381 1.00
eta[2,22] -0.04 0.01 0.51 -1.04 -0.39 -0.04 0.31 0.96 5000 1.00
eta[2,23] 0.00 0.01 0.50 -0.95 -0.34 0.00 0.32 0.97 5000 1.00
eta[2,24] 1.81 0.01 0.51 0.81 1.46 1.81 2.16 2.79 3866 1.00
eta[2,25] 0.38 0.01 0.52 -0.63 0.03 0.38 0.73 1.38 5000 1.00
eta[2,26] 0.64 0.01 0.51 -0.36 0.29 0.63 0.99 1.63 5000 1.00
eta[2,27] -0.39 0.01 0.50 -1.39 -0.73 -0.40 -0.06 0.62 5000 1.00
eta[2,28] -0.79 0.01 0.49 -1.79 -1.12 -0.79 -0.46 0.15 5000 1.00
eta[2,29] 0.55 0.01 0.50 -0.41 0.22 0.55 0.89 1.53 3211 1.00
eta[2,30] -0.51 0.01 0.51 -1.49 -0.84 -0.52 -0.17 0.49 5000 1.00
eta[2,31] -0.16 0.01 0.49 -1.14 -0.48 -0.15 0.18 0.77 3751 1.00
eta[2,32] -0.25 0.01 0.51 -1.26 -0.59 -0.24 0.10 0.75 5000 1.00
eta[3,1] 0.48 0.01 0.69 -0.84 0.02 0.48 0.95 1.84 4437 1.00
eta[3,2] -0.32 0.01 0.71 -1.66 -0.82 -0.32 0.17 1.05 4165 1.00
eta[3,3] -0.59 0.01 0.71 -1.98 -1.06 -0.58 -0.12 0.81 3763 1.00
eta[3,4] 0.04 0.01 0.70 -1.33 -0.43 0.05 0.52 1.41 4121 1.00
eta[3,5] 0.20 0.01 0.72 -1.16 -0.28 0.18 0.68 1.61 3375 1.00
eta[3,6] 0.64 0.01 0.71 -0.71 0.15 0.62 1.13 2.07 4019 1.00
eta[3,7] -0.82 0.01 0.70 -2.23 -1.29 -0.81 -0.34 0.51 3636 1.00
eta[3,8] 0.09 0.01 0.71 -1.30 -0.39 0.09 0.57 1.49 3763 1.00
eta[3,9] 0.08 0.01 0.71 -1.27 -0.41 0.07 0.56 1.47 3814 1.00
eta[3,10] 0.41 0.01 0.71 -0.96 -0.07 0.41 0.88 1.81 3677 1.00
eta[3,11] -0.08 0.01 0.70 -1.46 -0.55 -0.08 0.40 1.30 3947 1.00
eta[3,12] -0.86 0.01 0.72 -2.25 -1.36 -0.87 -0.37 0.54 3998 1.00
eta[3,13] 0.06 0.01 0.70 -1.35 -0.41 0.06 0.54 1.41 5000 1.00
eta[3,14] 0.05 0.01 0.70 -1.31 -0.41 0.06 0.53 1.41 3720 1.00
eta[3,15] -0.11 0.01 0.72 -1.50 -0.60 -0.11 0.38 1.31 4150 1.00
eta[3,16] -0.12 0.01 0.70 -1.49 -0.59 -0.13 0.35 1.26 3854 1.00
eta[3,17] 0.00 0.01 0.69 -1.34 -0.46 0.01 0.46 1.34 4035 1.00
eta[3,18] 0.48 0.01 0.71 -0.85 -0.01 0.46 0.94 1.87 3506 1.00
eta[3,19] -1.80 0.01 0.70 -3.18 -2.30 -1.80 -1.32 -0.41 3979 1.00
eta[3,20] 0.35 0.01 0.70 -1.01 -0.13 0.35 0.84 1.70 4130 1.00
eta[3,21] 0.07 0.01 0.70 -1.30 -0.40 0.08 0.54 1.41 4236 1.00
eta[3,22] 0.16 0.01 0.70 -1.22 -0.33 0.17 0.61 1.52 4166 1.00
eta[3,23] -0.83 0.01 0.72 -2.21 -1.34 -0.83 -0.35 0.56 2798 1.00
eta[3,24] 0.08 0.01 0.72 -1.31 -0.42 0.06 0.57 1.51 3642 1.00
eta[3,25] -0.48 0.01 0.69 -1.85 -0.95 -0.46 -0.01 0.84 4008 1.00
eta[3,26] 0.38 0.01 0.69 -0.99 -0.08 0.37 0.85 1.74 4548 1.00
eta[3,27] 0.45 0.01 0.74 -0.98 -0.04 0.45 0.95 1.85 4148 1.00
eta[3,28] -0.39 0.01 0.71 -1.81 -0.86 -0.39 0.10 1.00 4051 1.00
eta[3,29] 0.53 0.01 0.71 -0.86 0.05 0.51 1.00 1.94 3902 1.00
eta[3,30] -0.08 0.01 0.71 -1.44 -0.56 -0.07 0.40 1.30 4126 1.00
eta[3,31] -0.57 0.01 0.69 -1.91 -1.03 -0.57 -0.11 0.80 3831 1.00
[ reached getOption("max.print") -- omitted 4538 rows ]
Samples were drawn using NUTS(diag_e) at Sat Dec 9 11:28:07 2017.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at
convergence, Rhat=1).
values are all 1 so MCMC simulations convergences.
check_treedepth(fit_gp_h)[1] "4754 of 5000 iterations saturated the maximum tree depth of 10 (95.08%)"
[1] " Run again with max_depth set to a larger value to avoid saturation"
Our model hit the maximum trajectory length in MCMC simulations multiple times so we need to increase our treedepth to fix this issue.
check_energy(fit_gp_h)[1] "E-BFMI indicated no pathological behavior"
check_div(fit_gp_h)[1] "64 of 5000 iterations ended with a divergence (1.28%)"
[1] " Try running with larger adapt_delta to remove the divergences"
c_dark <- c("#8F272780")
green <- c("#00FF0080")
partition <- partition_div(fit_gp_h)
div_params <- partition[[1]]
nondiv_params <- partition[[2]]
par(mar = c(4, 4, 0.5, 0.5))
plot(nondiv_params$global_alpha, nondiv_params$sigma,
col=c_dark, pch=16, cex=0.8, xlab="length_param", ylab="sigma")
points(div_params$global_alpha, div_params$sigma,
col=green, pch=16, cex=0.8)We tried different parameter comparisons but we were not able to find any clear problem based on the plots, why our divergences does not vanish. We will try to fix the issue by tuning the MCMC parameters adapt delta and tree depth.
fit_gp_h <- stan(file=gp_model_hier,
data=list(y_is = y_is,
country_ind_is = country_ind_is,
year_ind_is = year_ind_is,
N_years_is = 15,
N_years_pred = N_years_pred,
N_is = N_is,
N_countries = N_countries),
iter=1000,
chains=10,control=list(adapt_delta=0.99,max_treedepth=15))print(fit_gp_h)Inference for Stan model: debt_gp_hierarchical.
10 chains, each with iter=1000; warmup=500; thin=1;
post-warmup draws per chain=500, total post-warmup draws=5000.
mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
alpha 6.85 0.01 0.39 6.12 6.57 6.83 7.11 7.67 1865 1.00
length_param 2.36 0.00 0.12 2.14 2.28 2.36 2.44 2.61 669 1.01
global_alpha 3.43 0.01 0.51 2.50 3.06 3.40 3.76 4.50 5000 1.00
global_length 1.69 0.00 0.15 1.39 1.59 1.69 1.79 1.96 2133 1.00
sigma 1.72 0.00 0.08 1.57 1.66 1.72 1.78 1.89 1425 1.00
eta[1,1] -0.35 0.01 0.87 -2.04 -0.92 -0.36 0.22 1.33 5000 1.00
eta[1,2] 0.37 0.01 0.88 -1.35 -0.22 0.35 0.94 2.10 5000 1.00
eta[1,3] 1.30 0.01 0.91 -0.49 0.69 1.30 1.90 3.13 5000 1.00
eta[1,4] 0.96 0.01 0.88 -0.76 0.38 0.95 1.54 2.71 5000 1.00
eta[1,5] -0.29 0.01 0.87 -1.98 -0.87 -0.29 0.29 1.41 5000 1.00
eta[1,6] -0.70 0.01 0.87 -2.41 -1.28 -0.69 -0.11 1.01 5000 1.00
eta[1,7] 0.36 0.01 0.88 -1.39 -0.23 0.36 0.95 2.11 5000 1.00
eta[1,8] -0.13 0.01 0.86 -1.85 -0.72 -0.13 0.46 1.54 5000 1.00
eta[1,9] -0.14 0.01 0.87 -1.85 -0.73 -0.15 0.45 1.57 5000 1.00
eta[1,10] -0.19 0.01 0.86 -1.86 -0.77 -0.19 0.39 1.48 5000 1.00
eta[1,11] 0.29 0.01 0.87 -1.39 -0.29 0.29 0.88 2.03 5000 1.00
eta[1,12] 0.96 0.01 0.88 -0.74 0.37 0.96 1.54 2.70 5000 1.00
eta[1,13] -0.17 0.01 0.88 -1.91 -0.76 -0.16 0.42 1.52 5000 1.00
eta[1,14] -0.17 0.01 0.86 -1.87 -0.74 -0.18 0.40 1.59 5000 1.00
eta[1,15] 0.39 0.01 0.85 -1.27 -0.19 0.38 0.97 2.03 5000 1.00
eta[1,16] -0.01 0.01 0.87 -1.70 -0.59 -0.03 0.57 1.66 5000 1.00
eta[1,17] 0.12 0.01 0.88 -1.55 -0.48 0.11 0.70 1.82 5000 1.00
eta[1,18] -0.72 0.01 0.86 -2.42 -1.31 -0.74 -0.12 1.00 5000 1.00
eta[1,19] -0.32 0.01 0.88 -1.99 -0.91 -0.33 0.26 1.46 5000 1.00
eta[1,20] 0.03 0.01 0.89 -1.74 -0.58 0.04 0.64 1.76 5000 1.00
eta[1,21] 0.00 0.01 0.88 -1.79 -0.58 0.00 0.58 1.69 5000 1.00
eta[1,22] -0.31 0.01 0.88 -2.03 -0.90 -0.30 0.26 1.40 5000 1.00
eta[1,23] -0.07 0.01 0.86 -1.74 -0.65 -0.08 0.53 1.62 5000 1.00
eta[1,24] -0.31 0.01 0.88 -2.06 -0.90 -0.32 0.28 1.39 5000 1.00
eta[1,25] -0.07 0.01 0.87 -1.78 -0.67 -0.08 0.52 1.60 5000 1.00
eta[1,26] -0.16 0.01 0.88 -1.85 -0.75 -0.16 0.44 1.59 5000 1.00
eta[1,27] -0.11 0.01 0.87 -1.80 -0.70 -0.11 0.47 1.58 5000 1.00
eta[1,28] 0.33 0.01 0.86 -1.35 -0.25 0.33 0.91 2.04 5000 1.00
eta[1,29] 0.00 0.01 0.84 -1.64 -0.57 0.00 0.57 1.64 5000 1.00
eta[1,30] 0.49 0.01 0.87 -1.20 -0.11 0.49 1.10 2.21 5000 1.00
eta[1,31] 0.57 0.01 0.86 -1.12 -0.02 0.56 1.14 2.26 5000 1.00
eta[1,32] -0.25 0.01 0.87 -1.94 -0.83 -0.26 0.33 1.46 5000 1.00
eta[2,1] -0.17 0.01 0.49 -1.15 -0.51 -0.18 0.16 0.78 5000 1.00
eta[2,2] -0.69 0.01 0.50 -1.65 -1.03 -0.69 -0.35 0.32 5000 1.00
eta[2,3] -1.13 0.01 0.52 -2.14 -1.47 -1.13 -0.78 -0.10 5000 1.00
eta[2,4] 0.57 0.01 0.51 -0.42 0.22 0.57 0.91 1.59 5000 1.00
eta[2,5] 0.36 0.01 0.50 -0.63 0.02 0.37 0.70 1.34 5000 1.00
eta[2,6] 0.86 0.01 0.51 -0.14 0.53 0.87 1.20 1.87 5000 1.00
eta[2,7] -0.05 0.01 0.50 -1.04 -0.38 -0.05 0.29 0.95 5000 1.00
eta[2,8] 0.18 0.01 0.52 -0.82 -0.17 0.18 0.54 1.20 5000 1.00
eta[2,9] 0.19 0.01 0.51 -0.81 -0.15 0.19 0.53 1.20 5000 1.00
eta[2,10] 0.07 0.01 0.51 -0.94 -0.26 0.07 0.40 1.06 5000 1.00
eta[2,11] -1.33 0.01 0.51 -2.32 -1.68 -1.33 -1.00 -0.32 5000 1.00
eta[2,12] -1.20 0.01 0.50 -2.19 -1.55 -1.20 -0.87 -0.23 5000 1.00
eta[2,13] 0.21 0.01 0.50 -0.82 -0.13 0.20 0.54 1.20 5000 1.00
eta[2,14] 0.22 0.01 0.50 -0.75 -0.12 0.22 0.56 1.22 5000 1.00
eta[2,15] 0.48 0.01 0.51 -0.51 0.14 0.48 0.83 1.47 5000 1.00
eta[2,16] 0.62 0.01 0.51 -0.38 0.28 0.62 0.96 1.59 5000 1.00
eta[2,17] 0.10 0.01 0.50 -0.88 -0.25 0.09 0.43 1.11 5000 1.00
eta[2,18] 0.13 0.01 0.51 -0.86 -0.22 0.14 0.48 1.13 5000 1.00
eta[2,19] -1.23 0.01 0.50 -2.21 -1.57 -1.24 -0.88 -0.25 5000 1.00
eta[2,20] -0.49 0.01 0.50 -1.46 -0.83 -0.49 -0.14 0.48 5000 1.00
eta[2,21] -0.53 0.01 0.51 -1.55 -0.86 -0.54 -0.19 0.46 5000 1.00
eta[2,22] -0.03 0.01 0.51 -1.01 -0.36 -0.03 0.31 0.96 5000 1.00
eta[2,23] 0.00 0.01 0.50 -0.98 -0.35 0.00 0.33 1.00 5000 1.00
eta[2,24] 1.79 0.01 0.50 0.81 1.46 1.79 2.13 2.77 5000 1.00
eta[2,25] 0.37 0.01 0.51 -0.61 0.03 0.37 0.72 1.34 5000 1.00
eta[2,26] 0.63 0.01 0.50 -0.36 0.29 0.63 0.97 1.59 5000 1.00
eta[2,27] -0.36 0.01 0.49 -1.31 -0.69 -0.36 -0.03 0.60 5000 1.00
eta[2,28] -0.81 0.01 0.49 -1.79 -1.15 -0.80 -0.47 0.13 5000 1.00
eta[2,29] 0.54 0.01 0.50 -0.44 0.20 0.55 0.88 1.51 5000 1.00
eta[2,30] -0.52 0.01 0.50 -1.51 -0.85 -0.53 -0.19 0.47 5000 1.00
eta[2,31] -0.15 0.01 0.51 -1.16 -0.49 -0.14 0.21 0.84 5000 1.00
eta[2,32] -0.26 0.01 0.50 -1.24 -0.59 -0.26 0.08 0.70 5000 1.00
eta[3,1] 0.49 0.01 0.69 -0.87 0.03 0.49 0.96 1.84 5000 1.00
eta[3,2] -0.32 0.01 0.71 -1.71 -0.81 -0.32 0.17 1.07 5000 1.00
eta[3,3] -0.62 0.01 0.71 -2.03 -1.09 -0.61 -0.16 0.75 5000 1.00
eta[3,4] 0.05 0.01 0.71 -1.36 -0.42 0.06 0.52 1.45 5000 1.00
eta[3,5] 0.18 0.01 0.70 -1.16 -0.31 0.17 0.65 1.53 5000 1.00
eta[3,6] 0.64 0.01 0.68 -0.68 0.18 0.65 1.09 1.97 5000 1.00
eta[3,7] -0.80 0.01 0.70 -2.16 -1.28 -0.81 -0.32 0.58 5000 1.00
eta[3,8] 0.08 0.01 0.71 -1.28 -0.42 0.08 0.57 1.44 5000 1.00
eta[3,9] 0.06 0.01 0.70 -1.30 -0.41 0.06 0.52 1.43 5000 1.00
eta[3,10] 0.38 0.01 0.71 -1.05 -0.08 0.39 0.84 1.80 5000 1.00
eta[3,11] -0.07 0.01 0.72 -1.48 -0.55 -0.06 0.42 1.28 5000 1.00
eta[3,12] -0.88 0.01 0.71 -2.27 -1.35 -0.88 -0.39 0.49 5000 1.00
eta[3,13] 0.04 0.01 0.71 -1.37 -0.44 0.04 0.52 1.44 5000 1.00
eta[3,14] 0.04 0.01 0.70 -1.32 -0.44 0.03 0.52 1.43 5000 1.00
eta[3,15] -0.10 0.01 0.70 -1.51 -0.58 -0.10 0.38 1.27 5000 1.00
eta[3,16] -0.12 0.01 0.70 -1.50 -0.57 -0.12 0.35 1.28 5000 1.00
eta[3,17] 0.00 0.01 0.70 -1.36 -0.48 -0.01 0.45 1.35 5000 1.00
eta[3,18] 0.48 0.01 0.73 -0.94 -0.03 0.48 0.99 1.92 5000 1.00
eta[3,19] -1.79 0.01 0.70 -3.15 -2.25 -1.77 -1.33 -0.39 5000 1.00
eta[3,20] 0.37 0.01 0.68 -0.97 -0.09 0.37 0.83 1.73 5000 1.00
eta[3,21] 0.07 0.01 0.70 -1.36 -0.41 0.08 0.54 1.42 5000 1.00
eta[3,22] 0.15 0.01 0.71 -1.22 -0.34 0.13 0.64 1.54 5000 1.00
eta[3,23] -0.85 0.01 0.70 -2.22 -1.32 -0.84 -0.39 0.54 5000 1.00
eta[3,24] 0.08 0.01 0.71 -1.32 -0.40 0.09 0.56 1.50 5000 1.00
eta[3,25] -0.48 0.01 0.71 -1.83 -0.98 -0.48 0.02 0.87 5000 1.00
eta[3,26] 0.37 0.01 0.70 -1.00 -0.09 0.37 0.83 1.74 5000 1.00
eta[3,27] 0.43 0.01 0.68 -0.91 -0.01 0.43 0.88 1.83 5000 1.00
eta[3,28] -0.37 0.01 0.69 -1.76 -0.83 -0.37 0.10 0.97 5000 1.00
eta[3,29] 0.53 0.01 0.70 -0.87 0.05 0.53 1.01 1.88 5000 1.00
eta[3,30] -0.07 0.01 0.71 -1.46 -0.54 -0.07 0.41 1.30 5000 1.00
eta[3,31] -0.56 0.01 0.71 -1.95 -1.04 -0.55 -0.06 0.79 5000 1.00
[ reached getOption("max.print") -- omitted 4538 rows ]
Samples were drawn using NUTS(diag_e) at Sat Dec 9 12:16:42 2017.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at
convergence, Rhat=1).
check_div(fit_gp_h)[1] "0 of 5000 iterations ended with a divergence (0%)"
check_treedepth(fit_gp_h)[1] "0 of 5000 iterations saturated the maximum tree depth of 10 (0%)"
check_energy(fit_gp_h)[1] "E-BFMI indicated no pathological behavior"
By increasing the adapt_delta and tree depth the model have no problems with divergences and does not hit the maximum trajectory threshold.
library(bayesplot)
sample = extract(fit_gp_h)
ppc_dens_overlay(y=data[,"FI"], yrep=sample$y_pred[,sample$country_indicators[1,] == match("FI",colnames(data))][,1:15])+ggtitle("Posterior predictive for Finland (hierarchical model)") + xlab("Debt (% of GDP)")Hierarchical model follows the emprical data distribution quite well, better than the separate model for Finland. Variance at 40-45 (2008 financial crisis) is not as large as it is with the separate model. Moreover variance between different draws in general is lower than with separate model. As expected by increasing the complexity of our model by adding hierarchy makes posterior fit the observed phenomena better.
Model comparision can be achieved using psis-LOO.
library(loo)
ll_sep <- extract_log_lik(sample1$m)
l_sep <- loo(ll_sep)Some Pareto k diagnostic values are too high. See help('pareto-k-diagnostic') for details.
ll_hier <- extract_log_lik(fit_gp_h)[,country_ind_is == match("FI",colnames(data))]
l_hier <- loo(ll_hier)Some Pareto k diagnostic values are too high. See help('pareto-k-diagnostic') for details.
print(l_sep)Computed from 5000 by 12 log-likelihood matrix
Estimate SE
elpd_loo -30.8 4.2
p_loo 5.8 2.1
looic 61.6 8.4
Pareto k diagnostic values:
Count Pct
(-Inf, 0.5] (good) 6 50.0%
(0.5, 0.7] (ok) 5 41.7%
(0.7, 1] (bad) 1 8.3%
(1, Inf) (very bad) 0 0.0%
See help('pareto-k-diagnostic') for details.
print(l_hier)Computed from 5000 by 15 log-likelihood matrix
Estimate SE
elpd_loo -30.7 0.9
p_loo 4.5 0.6
looic 61.5 1.9
Pareto k diagnostic values:
Count Pct
(-Inf, 0.5] (good) 3 20.0%
(0.5, 0.7] (ok) 10 66.7%
(0.7, 1] (bad) 2 13.3%
(1, Inf) (very bad) 0 0.0%
See help('pareto-k-diagnostic') for details.
Pareto-k values are quite reasonable. Only a few values are above 0.7 for both models. Based on LOO values hierarchical model performs slightly better because elpd_loo value is higher. However we could still consider using more computationally heavy model comparison methods, because there are still a few values over 0.7, which makes use of psis-LOO for model comparison possibly questionable. Cross validation could be used instead of psis-LOO.
Finding a proper prior was a bit tricky, because we had only a few datapoints, at least for the separate model. If the prior is too vague, gaussian process overfits badly and if decay speed of the length scale is too slow, gaussian process smoothens the curve too much and makes the prediction too linear.
One option to increase the usefulness of the hierarchical model is to add more layers to the hierarchy. E.g we could group countries into subgroups so that nordic countries have their own “grouped” gaussian process on top of the global and country specfic gp model. There is definately more similarities between nordic countries than with e.g Finland and Italy.
Model comparison should be improved by comparing the models using cross validation. Sensitivity analysis should also be done for hierarchical model.