Skip to content
This repository has been archived by the owner on Jul 29, 2020. It is now read-only.

Commit

Permalink
Week 7 materials and HW2 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Thorson committed May 8, 2018
1 parent 20db014 commit 20bf182
Show file tree
Hide file tree
Showing 13 changed files with 702 additions and 0 deletions.
95 changes: 95 additions & 0 deletions Week 2 -- mixed-effects/Homework solution/HW2.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

setwd( "C:/Users/James.Thorson/Desktop/Project_git/2016_Spatio-temporal_models/Week 2 -- mixed-effects/Homework solution" )

# Simulation settings
Nrep = 100
Target_Coverage = 0.5 # Target nominal CI coverage

# Parameter settings
Nsite = 10
Nobs_per_site = 10
Site_logMean = 2
Site_logSd = 1
Overdispersion_logSd = 0.5

# Libraries
library(TMB)
#library(TMBdebug)

# Compile model
Version = "HW2"
compile( paste0(Version,".cpp") )
dyn.load( dynlib(Version) )

# Recording object
Results = array(NA, dim=c(Nrep,4,3), dimnames=list(NULL,paste0("Random:",c("None","Site","Obs","Both")),c("mu_hat","SE_mu_hat","CoveredTF")))

# Helper functions
CoveredTF = function( x, CI ) x>CI[1] & x<CI[2]

# Simulation loop
for(repI in 1:Nrep){

# Simulation
s_i = rep( 1:Nsite, each=Nobs_per_site)
epsilon_s = rnorm( Nsite, mean=0, sd=Site_logSd )
delta_i = rnorm(Nobs_per_site*Nsite, mean=0, sd=Overdispersion_logSd)
yhat_i = exp( Site_logMean + epsilon_s[s_i] + delta_i )
y_i = rpois( Nsite*Nobs_per_site, lambda=yhat_i )

# Loop through estimation models
for(estI in 1:4){

# Build inputs
Data = list( "n_i"=length(y_i), "n_s"=length(unique(s_i)), "s_i"=s_i-1, "y_i"=y_i)
Parameters = list( "beta0"=-10, "log_sd_epsilon"=2, "log_sd_delta"=2, "epsilon_s"=rep(0,Data$n_s), "delta_i"=rep(0,Data$n_i) )
Random = c("epsilon_s", "delta_i")

# Turn off parameters for some estimation models
Map = list()
# Turn off overdispersion
if(estI %in% c(1,2)){
Map[["delta_i"]] = factor(rep(NA,Data$n_i))
Map[["log_sd_delta"]] = factor(NA)
}
# Turn off site-level variation
if(estI %in% c(1,3)){
Map[["epsilon_s"]] = factor(rep(NA,Data$n_s))
Map[["log_sd_epsilon"]] = factor(NA)
}
Random = setdiff( Random, names(Map))
if( length(Random)==0 ) Random = NULL

# Build object
Obj = MakeADFun(data=Data, parameters=Parameters, random=Random, map=Map)
Obj$env$beSilent()

# Optimize
Opt = nlminb( start=Obj$par, objective=Obj$fn, gradient=Obj$gr )
SD = sdreport( Obj )

# Save results
Results[repI,estI,c("mu_hat","SE_mu_hat")] = summary(SD)['beta0',]
Results[repI,estI,'CoveredTF'] = CoveredTF(CI=Results[repI,estI,'mu_hat']+c(-1,1)*qnorm(1-Target_Coverage/2)*Results[repI,estI,'SE_mu_hat'], x=Site_logMean)
}
}

#################
# Analysis
#################

# Plot estimates
par( mfrow=c(1,4), mar=c(3,3,2,0), mgp=c(2,0.5,0), tck=-0.02, yaxs="i")
for(estI in 1:4){
hist( Results[,estI,'mu_hat'], breaks=seq(1,5,length=25), main=dimnames(Results)[[2]][estI], xlab="", ylab="")
abline( v=Site_logMean, lwd=3, lty="dotted" )
}

# Summarize coverage results
apply( Results[,,'CoveredTF'], MARGIN=2, FUN=mean, na.rm=TRUE )

# Summarize bias
apply( Results[,,'mu_hat'], MARGIN=2, FUN=mean, na.rm=TRUE )



52 changes: 52 additions & 0 deletions Week 2 -- mixed-effects/Homework solution/HW2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <TMB.hpp>
template<class Type>
Type objective_function<Type>::operator() ()
{
// Data
DATA_INTEGER( n_i );
DATA_INTEGER( n_s );
DATA_IVECTOR( s_i );
DATA_VECTOR( y_i );

// Parameters
PARAMETER( beta0 );
PARAMETER( log_sd_epsilon );
PARAMETER( log_sd_delta );
PARAMETER_VECTOR( epsilon_s );
PARAMETER_VECTOR( delta_i );

// Objective funcction
Type jnll = 0;

// Probability of data conditional on fixed and random effect values
vector<Type> ypred_i(n_i);
for( int i=0; i<n_i; i++){
ypred_i(i) = exp( beta0 + epsilon_s(s_i(i)) + delta_i(i) );
jnll -= dpois( y_i(i), ypred_i(i), true );
}

// Probability of site-level variation
for( int s=0; s<n_s; s++){
jnll -= dnorm( epsilon_s(s), Type(0.0), exp(log_sd_epsilon), true );
}

// Probability of overdispersion
for( int i=0; i<n_i; i++){
jnll -= dnorm( delta_i(i), Type(0.0), exp(log_sd_delta), true );
}

// Reporting
Type sd_epsilon = exp(log_sd_epsilon);
Type sd_delta = exp(log_sd_delta);

REPORT( sd_epsilon );
REPORT( sd_delta );
REPORT( epsilon_s );
REPORT( delta_i );
REPORT( beta0 );

ADREPORT( sd_epsilon );
ADREPORT( sd_delta );

return jnll;
}
Binary file not shown.
Binary file not shown.
41 changes: 41 additions & 0 deletions Week 7 -- spatiotemporal models/Lab/Sim_Gompertz_Fn.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Sim_Gompertz_Fn <-
function( n_years, n_stations=100, phi=NULL, SpatialScale=0.1, SD_O=0.5, SD_E=0.2, SD_extra=0.1, rho=0.8, logMeanDens=1, Loc=NULL ){
# Parameters
if( is.null(phi) ) phi = rnorm(1, mean=0, sd=1)
alpha = logMeanDens * (1-rho)

# Spatial model
if( is.null(Loc) ) Loc = cbind( "x"=runif(n_stations, min=0,max=1), "y"=runif(n_stations, min=0,max=1) )
model_O <- RMgauss(var=SD_O^2, scale=SpatialScale)
model_E <- RMgauss(var=SD_E^2, scale=SpatialScale)

# Simulate Omega
Omega = RFsimulate(model = model_O, x=Loc[,'x'], y=Loc[,'y'])@data[,1]

# Simulate Epsilon
Epsilon = array(NA, dim=c(n_stations,n_years))
for(t in 1:n_years){
Epsilon[,t] = RFsimulate(model=model_E, x=Loc[,'x'], y=Loc[,'y'])@data[,1]
}

# Calculate Psi
Theta = array(NA, dim=c(n_stations,n_years))
for(t in 1:n_years){
if(t==1) Theta[,t] = phi + Epsilon[,t] + (alpha + Omega)/(1-rho)
if(t>=2) Theta[,t] = rho * Theta[,t-1] + alpha + Omega + Epsilon[,t]
}

# Simulate data
DF = NULL
for(s in 1:n_stations){
for(t in 1:n_years){
Tmp = c("Site"=s, "Year"=t, "Simulated_example"=rpois(1,lambda=exp(Theta[s,t]+SD_extra*rnorm(1))))#, 'Lon..DDD.DDDDD.'=Loc[s,1], 'Lat..DD.DDDDD.'=Loc[s,2] )
DF = rbind(DF, Tmp)
}}
DF = cbind( DF, 'Longitude'=Loc[DF[,'Site'],1], 'Latitude'=Loc[DF[,'Site'],2] )
DF = data.frame(DF, row.names=NULL)

# Return stuff
Sim_List = list("DF"=DF, "phi"=phi, "Loc"=Loc, "Omega"=Omega, "Epsilon"=Epsilon, "Theta"=Theta)
return(Sim_List)
}
105 changes: 105 additions & 0 deletions Week 7 -- spatiotemporal models/Lab/spatial_gompertz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Space time
#include <TMB.hpp>
// Function for detecting NAs
template<class Type>
bool isNA(Type x){
return R_IsNA(asDouble(x));
}

template<class Type>
Type objective_function<Type>::operator() ()
{
// Indices
DATA_INTEGER( n_i ); // Total number of observations
DATA_INTEGER( n_x ); // Number of vertices in SPDE mesh
DATA_INTEGER( n_t ); // Number of years
DATA_INTEGER( n_p ); // number of columns in covariate matrix X

// Data
DATA_IVECTOR( x_s ); // Association of each station with a given vertex in SPDE mesh
DATA_VECTOR( c_i ); // Count data
DATA_IVECTOR( s_i ); // Station for each sample
DATA_IVECTOR( t_i ); // Time for each sample
DATA_MATRIX( X_xp ); // Covariate design matrix

// SPDE objects
DATA_SPARSE_MATRIX(G0);
DATA_SPARSE_MATRIX(G1);
DATA_SPARSE_MATRIX(G2);

// Fixed effects
PARAMETER_VECTOR(alpha); // Mean of Gompertz-drift field
PARAMETER(phi); // Offset of beginning from equilibrium
PARAMETER(log_tau_E); // log-inverse SD of Epsilon
PARAMETER(log_tau_O); // log-inverse SD of Omega
PARAMETER(log_kappa); // Controls range of spatial variation
PARAMETER(rho); // Autocorrelation (i.e. density dependence)

// Random effects
PARAMETER_ARRAY(Epsilon_input); // Spatial process variation
PARAMETER_VECTOR(Omega_input); // Spatial variation in carrying capacity

// objective function -- joint negative log-likelihood
using namespace density;
Type jnll = 0;
vector<Type> jnll_comp(3);
jnll_comp.setZero();

// Spatial parameters
Type kappa2 = exp(2.0*log_kappa);
Type kappa4 = kappa2*kappa2;
Type pi = 3.141592;
Type Range = sqrt(8) / exp( log_kappa );
Type SigmaE = 1 / sqrt(4*pi*exp(2*log_tau_E)*exp(2*log_kappa));
Type SigmaO = 1 / sqrt(4*pi*exp(2*log_tau_O)*exp(2*log_kappa));
Eigen::SparseMatrix<Type> Q = kappa4*G0 + Type(2.0)*kappa2*G1 + G2;

// Objects for derived values
vector<Type> eta_x(n_x);
array<Type> log_Dpred_xt(n_x, n_t);
vector<Type> Omega_x(n_x);
vector<Type> Equil_x(n_x);
matrix<Type> Epsilon_xt(n_x, n_t);

// Probability of Gaussian-Markov random fields (GMRFs)
jnll_comp(0) += GMRF(Q)(Omega_input);
jnll_comp(1) = SEPARABLE(AR1(rho),GMRF(Q))(Epsilon_input);

// Transform GMRFs
eta_x = X_xp * alpha.matrix();
for(int x=0; x<n_x; x++){
Omega_x(x) = Omega_input(x) / exp(log_tau_O);
Equil_x(x) = ( eta_x(x) + Omega_x(x) ) / (1-rho);
for( int t=0; t<n_t; t++){
Epsilon_xt(x,t) = Epsilon_input(x,t) / exp(log_tau_E);
}
}

// Likelihood contribution from observations
vector<Type> log_chat_i(n_i);
for (int i=0; i<n_i; i++){
log_chat_i(i) = phi*pow(rho,t_i(i)) + Epsilon_xt(x_s(s_i(i)),t_i(i)) + (eta_x(x_s(s_i(i))) + Omega_x(x_s(s_i(i))) ) / (1-rho);
if( !isNA(c_i(i)) ){
jnll_comp(2) -= dpois( c_i(i), exp(log_chat_i(i)), true );
}
}
jnll = jnll_comp.sum();

// Diagnostics
REPORT( jnll_comp );
REPORT( jnll );
// Spatial field summaries
REPORT( Range );
REPORT( SigmaE );
REPORT( SigmaO );
REPORT( rho );
ADREPORT( Range );
ADREPORT( SigmaE );
ADREPORT( SigmaO );
// Fields
REPORT( Epsilon_xt );
REPORT( Omega_x );
REPORT( Equil_x );

return jnll;
}
Loading

0 comments on commit 20bf182

Please sign in to comment.