This repository has been archived by the owner on Jul 29, 2020. It is now read-only.
forked from James-Thorson/2018_FSH556
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
20db014
commit 20bf182
Showing
13 changed files
with
702 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ) | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 added
BIN
+609 KB
Week 7 -- spatiotemporal models/Lab/Lab 7 -- spatial-Gompertz model.pptx
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
105
Week 7 -- spatiotemporal models/Lab/spatial_gompertz.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
Oops, something went wrong.