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

Commit

Permalink
added Week 2 materials
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Thorson committed Apr 2, 2018
1 parent ea543f6 commit c2e9318
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 0 deletions.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
85 changes: 85 additions & 0 deletions Week 2 -- mixed-effects/Lab 2/Introduction to GLMMs.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

setwd( "C:/Users/James.Thorson/Desktop/Project_git/2018_FSH556/Week 2 -- mixed-effects/Lab 2" )
Use_REML = TRUE

devtools::install_github("kaskr/TMB_contrib_R/TMBhelper")

############
# Generalized linear mixed model
############
library(lme4)

###### Simulate data
# Parameters
Nsite = 10
Nobs_per_site = 10
Site_logMean = log(10)
Site_logSd = 1

# Bookkeeping
s_i = rep( 1:Nsite, each=Nobs_per_site)

# Simulation
z_s = rnorm( Nsite, mean=0, sd=Site_logSd )
Mean_s = exp( Site_logMean + z_s )
y_i = rpois( Nsite*Nobs_per_site, lambda=Mean_s[s_i] )

# Plot data
library(lattice)
histogram( ~ y_i | factor(s_i), breaks=seq( min(y_i), max(y_i), length=10), type="density", panel=function(x,...){ panel.histogram(x, ...); panel.mathdensity(dmath=dnorm, col="black", args = list(mean=mean(x),sd=sd(x))) } ) #

###### Fit using R
# No site level (Not recommended)
GLM = glm( y_i ~ 1, family="poisson" )
print( summary(GLM) )

# Using fixed effects (Not recommended)
GLM = glm( y_i ~ 0 + factor(s_i), family="poisson" )
print( summary(GLM) )

# Using mixed effects (Recommended) -- doesn't appear to use REML
library(lme4)
GLMM = glmer( y_i ~ 1 + (1 | factor(s_i)), family="poisson" )
print( summary(GLMM) )

####################
# Fit using TMB
####################
library(TMB)

# Compile model
Version = "glmm"
compile( paste0(Version,".cpp") )

# Build inputs
Data = list( "n_y"=length(y_i), "n_s"=length(unique(s_i)), "s_i"=s_i-1, "y_i"=y_i)
Parameters = list( "beta0"=-10, "log_sdz"=2, "z_s"=rep(0,Data$n_s) )
Random = c("z_s")
if( Use_REML==TRUE ) Random = union( Random, "beta0")

# Build object
dyn.load( dynlib(Version) )
Obj = MakeADFun(data=Data, parameters=Parameters, random=Random) #

# Prove that function and gradient calls work
Obj$fn( Obj$par )
Obj$gr( Obj$par )

# Optimize
Opt = TMBhelper::Optimize( obj=Obj, newtonsteps=1 )

# Get reporting and SEs
Report = Obj$report()
ParHat = as.list( Opt$SD, "Estimate" )

######################
# Compare estimates
######################

# Global mean
c( "Lme4"=fixef(GLMM), "TMB"=ParHat$beta0 )

# Random effects
cbind( "True"=z_s, "Lme4"=ranef(GLMM)[['factor(s_i)']], "TMB"=ParHat$z_s )


Binary file not shown.
Binary file not shown.
39 changes: 39 additions & 0 deletions Week 2 -- mixed-effects/Lab 2/glmm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <TMB.hpp>
template<class Type>
Type objective_function<Type>::operator() ()
{
// Data
DATA_INTEGER( n_y );
DATA_INTEGER( n_s );
DATA_IVECTOR( s_i );
DATA_VECTOR( y_i );

// Parameters
PARAMETER( beta0 );
PARAMETER( log_sdz );
PARAMETER_VECTOR( z_s );

// Objective funcction
Type jnll = 0;

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

// Probability of random coefficients
for( int s=0; s<n_s; s++){
jnll -= dnorm( z_s(s), Type(0.0), exp(log_sdz), true );
}

// Reporting
Type sdz = exp(log_sdz);

REPORT( sdz );

ADREPORT( sdz );

return jnll;
}
Binary file not shown.
Binary file not shown.
85 changes: 85 additions & 0 deletions Week 2 -- mixed-effects/Lecture 2/linear_mixed_model.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

setwd( "C:/Users/James.Thorson/Desktop/Project_git/2018_FSH556/Week 2 -- mixed-effects/Lecture 2" )
Use_REML = FALSE

devtools::install_github("kaskr/TMB_contrib_R/TMBhelper")

######################
# Simulate data
######################

# Simulate predictors
group_i = rep( 1:10, each=10)
z_g = rnorm( length(unique(group_i)), mean=0, sd=1)
beta0 = 0

# Simulate response
y_i = z_g[group_i] + beta0 + rnorm( length(group_i), mean=0, sd=1)

######################
# Run in R
######################

library(lme4)
Lme = lmer( y_i ~ 1|factor(group_i), REML=Use_REML)

######################
# Run in TMB
######################

library(TMB)

# Compile model
Version = "linear_mixed_model"
compile( paste0(Version,".cpp") )

# Build inputs
Data = list( "n_groups"=length(unique(group_i)), "g_i"=group_i-1, "y_i"=y_i)
Parameters = list( "beta0"=-10, "log_SD0"=2, "log_SDZ"=2, "z_g"=rep(0,Data$n_groups) )
Random = c("z_g")
if( Use_REML==TRUE ) Random = union( Random, "beta0")

# Build object
dyn.load( dynlib("linear_mixed_model") )
Obj = MakeADFun(data=Data, parameters=Parameters, random=Random) #

# Prove that function and gradient calls work
Obj$fn( Obj$par )
Obj$gr( Obj$par )

# Optimize
Opt = TMBhelper::Optimize( obj=Obj, newtonsteps=1 )

# Get reporting and SEs
Report = Obj$report()
ParHat = as.list( Opt$SD, "Estimate" )

######################
# Shrinkage estimator
######################

# jim's attempt at replicating this from first principles
Mu = mean(y_i)
Mu_s = tapply( y_i, INDEX=group_i, FUN=mean)
Sigma = sd( Mu_s )
Sigma_s = sd( y_i - Mu_s[group_i] )
Weights_hat = c( 1/Sigma^2, length(y_i)/length(unique(group_i))/Sigma_s^2 )
Weights_hat = Weights_hat / sum(Weights_hat)

# Predictions
Mu_s_hat = ( Mu*Weights_hat[1] + Mu_s*Weights_hat[2] )

######################
# Compare estimates
######################

# Global mean
c( fixef(Lme), ParHat$beta0, Mu )

# Random effects
cbind( "True"=z_g, "Lme4"=ranef(Lme)[['factor(group_i)']], "TMB"=ParHat$z_g, "Shrinkage_estimator"=Mu_s-Mu )

# Variances
summary(Lme)
unlist( Report[c("SDZ","SD0")] )

40 changes: 40 additions & 0 deletions Week 2 -- mixed-effects/Lecture 2/linear_mixed_model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <TMB.hpp>
template<class Type>
Type objective_function<Type>::operator() ()
{
// Data
DATA_INTEGER( n_groups );
DATA_IVECTOR( g_i );
DATA_VECTOR( y_i );

// Parameters
PARAMETER( beta0 );
PARAMETER( log_SD0 );
PARAMETER( log_SDZ );
PARAMETER_VECTOR( z_g );

// Objective funcction
Type jnll = 0;
int n_i = y_i.size();

// Probability of data conditional on fixed and random effect values
for( int i=0; i<n_i; i++){
jnll -= dnorm( y_i(i), beta0 + z_g(g_i(i)), exp(log_SD0), true );
}

// Probability of random coefficients
for( int g=0; g<n_groups; g++){
jnll -= dnorm( z_g(g), Type(0.0), exp(log_SDZ), true );
}

// Reporting
Type SDZ = exp(log_SDZ);
Type SD0 = exp(log_SD0);

REPORT( SDZ );
REPORT( SD0 );
ADREPORT( SDZ );
ADREPORT( SD0 );

return jnll;
}
Binary file added Week 2 -- mixed-effects/week2-intro.pptx
Binary file not shown.

0 comments on commit c2e9318

Please sign in to comment.