A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work...

70
A Tutorial on Gibbs Sampling Software for Ecological Modelers N. T. Hobbs NR 575, Systems Ecology, Spring 2010 Aim 5 Introducing MCMC Samplers 5 Introducing BUGS 6 Installing Gibbs Sampling Software 8 For Windows users: Installing WinBugs 8 For Mac users: Installing JAGS 8 Implementing the logistic example to estimate r, K, and τ 8 Examining the Code 8 Technical notes 9 The model statement............................................................................... 9 for loops................................................................................................... 9 Precision as an argument to the normal density function (and the lognormal).............................................................................................. 11 The <- operator...................................................................................... 11

Transcript of A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work...

Page 1: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

A Tutorial on Gibbs Sampling Software for Ecological Modelers

N. T. HobbsNR 575, Systems Ecology, Spring 2010

Aim 5

Introducing MCMC Samplers 5

Introducing BUGS 6

Installing Gibbs Sampling Software 8

For Windows users: Installing WinBugs 8

For Mac users: Installing JAGS 8

Implementing the logistic example to estimate r, K, and τ 8

Examining the Code 8

Technical notes 9

The model statement................................................................................9

for loops....................................................................................................9

Precision as an argument to the normal density function (and the lognormal)...............................................................................................11

The <- operator........................................................................................11

Coding and saving the BUG’s script 11

Saving the program file: JAGS..............................................................11

Saving the program file: WinBUGS.......................................................12

The interface between BUGS and R 12

Interface between R and BUGS: JAGS 14

Page 2: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Interface between R and BUGS: WinBUGS 15

Getting simple output: JAGS and WinBUGS 17

Complete R script for JAGS (to this point) 19

Complete R script for WinBUGS 20

Exercise I: courtesy of McCarthy, M. A. 2007. Bayesian Methods for Ecology. Cambridge University Press, Cambridge, U. K. 21

Using the summary() list 21

Estimating Quantities of Interest Derived from Model Parameters24

Exercise 2 29

Comparing Parameter Values Between Populations 29

Using the MCMC List 31

Exercise 3 36

Checking for Convergence 37

Checking Syntax 39

WinBUGS 39

JAGS 40

Some common error messages 41

JAGS 41

WinBUGS 45

made use of undefined node— 45

multiple definitions of node [x] 45

incompatible copy 45

Splus data 100 46

Cannot Bracket Slice for Nod 46

2

Page 3: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Shape parameter of gamma r too small. 46

Differences Between JAGS and WinBUGS 46

Bibliography 47

Appendix 1: Reference material for JAGS 48

Distributions 48

Functions and operators 49

Reference Material for WinBUGS 51

Distributions 51

Functions and Operators 55

Appendix 2: Answers to Exercises 57

Exercise 1 57

Exercise 2 58

Exercise 3 61

3

Page 4: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

AimThe purpose of this Primer is to teach the programming skills needed to estimate the posterior distributions of parameters and derived quantities of interest in ecological models using software implementing Mote Carlo Markov chain methods. Along the way, I will reinforce some of the ideas and principals that we have learned in lecture. My approach to teaching this topic is quite different than you are likely to find in other sources because I will integrate the programming you need to learn in R with the programming needed in the MCMC software.

The Primer is organized primarily as a tutorial, but it contains a modicum of reference material as well. Although I think this Primer offers a great start for learning JAGS and WinBUGS, it is not intended to be comprehensive. So, some Sunday afternoon when you find yourself with time on your hands, you should read through the WinBUGS and JAGS manual as well.

Introducing MCMC SamplersWinBugs, OpenBUGS, and JAGS are three systems of software that implement Monte Carlo Markov Chain sampling using the BUGS language.1 BUGS stands for Bayesian Analysis Using Gibbs Sampling, so you can get an idea what this language does from its name. Imagine that you took the MCMC code you wrote for a Gibbs sampler and tried to turn it into a general R function for building chains of parameter estimates. Actually, you know enough now to construct a very general tool that would do this. However, you are probably delighted to know that all of this work has been done for you in the BUGS language.

The BUGS language is currently implemented in three flavors of software: OpenBUGS, WinBUGS, and JAGS. OpenBUGS and WinBUGS run on Windows operating systems, while JAGS was specifically constructed to run on Mac OS and Unix.2 Although all three use essentially the same syntax3, OpenBUGS and WinBUGS run in an elaborate graphical user interface, while JAGS only runs from the command line of a Unix shell or from R. However, all three can be easily called from R, and this is the approach I will teach. In the past, I have taught students how to use the graphical version, but they quickly learned, as I have, that the GUI involves far to much tedious pointing and clicking and doesn't’ provide the flexibility that is needed for high level work. So, I have decided to abandon any detailed instruction on the GUI, but you will see it in print elsewhere. If you would like to look at past tutorials that include the GUI, I would be happy to provide them. That said, there is a bit we need to know about the interface, mainly as a syntax checker, which I will cover later. It is important for you to understand that when I talk about a BUGS program, it can be run in either JAGS or WinBUGS. When I am talking about distinct features of these programs and their implementation in R, I will be sure to point that out.1 There is also software called GeoBUBS that is specifically developed for spatial models, but I know virtually nothing about it. However, if you are interested in landscape ecology otherwise have an interest in spatial modeling, I urge you to look into it after completing this tutorial.2 JAGS will also run under Windows and you may like it better than WinBUGS.3 JAGS has a few notable departures from the others. These will be discussed later. If I forget to cover these differences, Mac Users, please remind me!

4

Page 5: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Introducing BUGSThis tutorial will use a simple example of regression as a starting point for teaching the BUGS language and associated R commands. Although the problem starts simply, it builds to include some fairly sophisticated analysis. The model that we will use is the a linear relationship between the per-capita rate of population growth and the density of a population, which, as you know is the starting point for deriving the logistic equation. For the ecosystem scientists among you, this problem is easily recast as the mass specific rate of accumulation of nitrogen in the soil; see for example, Knops and Tillman (2000)4. Happily, both the population example and the ecosystem example can use the symbol N to represent the state variable of interest. Consider the model,

dNdt

1N

r rK

N

which, of course gives the equation for a line with intercept r and slope =

rK (Figure 1)

Figure 1. Simulated data for regression problem.

Note that these quantities enjoy a sturdy biological interpretation; r is the intrinsic rate of

increase,

rK is the strength of the feedback from population size to population growth

rate, and K is the carrying capacity, that is, the population size (o.k., o.k., the gm N per

gm soil) at which

dNdt

1N

0. Presume we have some data consisting of observations of

per capita rate of growth of N paired with observations of N. The vector y contains

4 Remember, ecological modelers have a rather small bag of tricks.

5

Page 6: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

values for the rate and the vector x contains aligned data on N5, i.e. yi

dNi

dt1Ni

, xi N i

. A simple Bayesian model might reasonably specify the posterior distributions of r, K, and τ as

i r rxi

K

P r, K , y,x P yi | i , P r P K P in

n

P r, K , y,x Normal yi | i , Normal 0,.0011 Gamma .001,.001 in

n

Gamma .001,.001

where the priors are uninformative. Now, I have full, abiding confidence that with a couple of hours worth of work, perhaps less, you could knock out a Gibbs sampler to estimate r, K, and τ. However, I am all for doing things nimbly in 15 minutes that might otherwise take a sweaty hour of hard labor, so, consider the code below.

##Logistic example for Primermodel{#priorsK~dgamma(.001,.001)r~dnorm(0.,.001)tau~ dgamma(.001,.001)sigma<-1/sqrt(tau)

#likelihoodfor(i in 1:n){

mu[i] <- r - r/K * x[i]y[i] ~ dnorm(mu[i],tau)}

} #end of modelThis code above implements the Bayesian model, providing full MCMC chains for each parameter, chains that form the basis for estimating their posterior distributions and associated statistics, i.e., means, medians, standard deviations, and credible intervals. As we will soon learn, it becomes child’s play to derive chains other quantities of interest and their posterior distributions, for example, K/2 (What is K/2?), N as a function of time or dN/dt as a function of N. It is easy to construct comparisons between of the growth parameters of two populations or among ten of them. If this seems as if it might be useful to you, you should continue reading.

Installing Gibbs Sampling Software

5 This could also be easily done with a matrix data structure, but I will leave that for a later topic.

6

Page 7: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

For Windows users: Installing WinBugsWinBUGS is free software maintained by the Medical Research Council Biostatistics Unit at the University of Cambridge. It can be downloaded from their web site, http://www.mrc-bsu.cam.ac.uk/bugs/winbugs/contents.shtml.

For Mac users: Installing JAGSFor those of you using MAC OS, JAGS (for Just Another Gibbs Sampler) is available at http://www-fis.iarc.fr/~martyn/software/jags/. You should click on JAGS-1.0.4u.dmg to get the disk image. There is a readme file with instructions. It will be very helpful to be able to run WinBUGS on your Mac as well, if for no other reason, to use its syntax checker for BUGS models. There are two ways to do that. You can, of course, create a Windows virtual machine using Parallels or VM Fusion and simply download WinBUGS onto it. There is also free software called Wine (for Windows Emulation) that allows Winbugs to run on the Mac without Parallels etc--go to idiom.ucsd.edu/~rlevy/winbugsonmacosx.pdf and follow the instructions. It may take a little work to get it set up. Let me know if you need help.

Implementing the logistic example to estimate r, K, and τExamining the CodeStudy the relationship between the numerator of Bayes law and the code. The similarity should be pretty obvious, but there are a few things to point out. Priors and likelihoods are specified using the ~ notation that we have seen in class. In so doing, remember that the following notation is equivalent:

yi ~ Normal i , is the same as

Normal yi | i , So, it is easy to see the correspondence between the fully conditional distribution (i.e., the numerator of Bayes law) and the code. I chose uninformative Gamma priors for K and τ because they must be positive. I chose an uninformative normal for r because it can be positive or negative.

Technical notes

The model statementYour entire model must be enclosed in

model{....

7

Page 8: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

} #end of model

For JAGS users, it is critical that you put a hard return (a blank line) after the } #end of model statement. If you fail to do so, you will get the message #syntax error, unexpected NAME, expecting $end.

for loops

Notice that the for loop replaces the i1

n

in the likelihood. Recall that when we

specify a total likelihood, we ask, what is the probability that we would obtain this data point conditional on the value of the parameter(s) of interest? The total likelihood is the product of the individual likelihoods. Recall in the Excel example that we labored through that you had an entire column of likelihoods adjacent to a column of deterministic predictions of our model. If you were to duplicate these “columns” in WinBUGS, or JAGS you would write

mu[1] <- r - r/K * x[1]y[1] ~ dnorm(mu[1],tau)

mu[2] <- r - r/K * x[2]y[2] ~ dnorm(mu[3],tau)

mu[3] <- r - r/K * x[3]y[3] ~ dnorm(mu[3],tau)

.

.

.mu[n] <- r - r/K * x[n]

y[n] ~ dnorm(mu[n],tau)

Well, presuming that you have something better to do with your time that to write out statements like this for every observation in your data set, you may substitute

for(i in 1:n){mu[i] <- r - r/K * x[i]y[i] ~ dnorm(mu[i],tau)}

for the line by line specification of the likelihood. Thus, the for loop specifies the elements in the product of the likelihoods.

8

Page 9: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Note however, that the for structure in the BUGS language is subtly different from what you have learned in R. For example the following would be legal in R but not in the BUGS language:

#WRONG!!!for(i in 1:n){

mu <- r - r/K * x[i]y[i] ~ dnorm(m,tau)}

If you write something like this in BUGS you will get a message that complains about multiple definitions of node mu. If you think about what the for loop is doing, you can see the reason for this complaint; the incorrect syntax translates to

mu <- r - r/K * x[1]y[1] ~ dnorm(mu,tau)

mu <- r - r/K * x[2]y[2] ~ dnorm(mu,tau)

mu <- r - r/K * x[3]y[3] ~ dnorm(mu,tau)

.

.

.mu <- r - r/K * x[n]

y[n] ~ dnorm(mu,tau),

which is nonsense if you are specifying a likelihood. One more thing about the for construct. If you have two product symbols in the fully conditional distribution with

different indexes, i.e. something like expresssionk expression j

j1

J

,

k1

K

then you would

implement this in BUGS as nested for loops, e.g.,

for(k in 1:K){expression[k]for(j in 1:J){

expression[j]} #end of j loop

} #end of k loop

9

Page 10: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Precision as an argument to the normal density function (and the lognormal)Note that in the code, the second argument to the Normal density function is tau, which

is the precision, defined as the reciprocal of the variance,

1 2

. This means that we must calculate sigma from tau if we want a posterior distribution on sigma. Be very careful about this. For the lognormal, it is the precision on the log scale.

The <- operatorNote that, unlike R, you do not have the option in BUGS to use the = sign in an assignment statement. You must use <-.

Coding and saving the BUG’s scriptCarefully write out all of the code in the Logistic example (above) into program window in R.

Saving the program file: JAGSFor JAGS users, you may save this code in any directory that you like and may name it anything you like. I use names like logisticBUGS.R which lets me know that the file contains BUGS code. Using an R extension allows me to search these files easily with Spotlight.

Alternatively, you can embed the BUGS code in you R script using:

sink("logisticBUG.R") #This is the file name for the bugs codecat(" model{K~dgamma(.001,.001)r~dnorm(0.,.001)tau~ dgamma(.001,.001)sigma<-1/sqrt(tau)

#likelihoodfor(i in 1:n){

mu[i] <- r - r/K * x[i]y[i] ~ dnorm(mu[i],tau)}

} #end of model

",fill=TRUE)sink()

Saving the program file: WinBUGSFor Windows users, you must put the code in a directory immediately off of the root directory with a short name (something like C:\BUGS) and name the file with < 8 characters, i.e., something like logis.bugs or logis.R. If you get a screen full of gibberish

10

Page 11: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

and the rather unhelpful message “INCOMPATIBLE COPY” at the top, the pathname to your file has too many characters. I know, this is cumbersome.

The interface between BUGS and R

Consider the following code:

rm(list=ls())pop.data=(read.csv("Logistic Data"))names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05))

n.xy = nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"), y=as.real(pop.data$"Growth Rate"))

The first two lines bring the growth rate data into R as a data frame. Next we specify the initial conditions for the MCMC chain. This is exactly the same thing as you did when you wrote you MCMC code and assigned a guess to the first element in the chain. There are two important things to notice about this statement. First, this must be composed as as “list of lists”, as you see above. If you use

#WRONGinits= list(K=1500, r=.5, tau=.05)

your code will not run. Second, this statement allows you to set up multiple chains, which are needed to assure convergence6. For example, if you want three chains, you would use something like:

inits=list(list(K=1500, r=.5, tau=.05), #chain 1list(K=1000, r=.1, tau=.03), #chain 2list(K=900, r=.7, tau=.07) #chain 3

) #end of inits list

6 Jennifer Hoeting taught me to start my work with a single chain. Once everything seems to be running, you add additional ones. Note, it sometimes happens that adding a second or third or fourth chain will cause the model to fail because one of its initial conditions causes undefined real results etc. Thus, you should add them one at a time for complex models.

11

Page 12: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Which variables in your BUGS code require initialization? Anything you are estimating must be initialized.7 So, this is everything that has a prior, but also, any variable that is a random effect, which is a bit of an advanced topic now, but I would like for you to tuck that away for later. Think about it this way. When you were writing your own Gibbs sampler, every chain required a value as the first element in the vector holding the chain. That is what you are doing when you specify initial conditions here.

The next couple of statements, n.xy = nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"), y=as.real(pop.data$"Growth Rate"))

specify the data that will be used by your BUGS program. Notice that you can assign data vectors on the R side to different names on the BUGS side. For example, the bit that reads

x=as.real(pop.data$"Population Size")

says that the x vector in your BUGS program (see the code above) is composed of the column in your data frame called Population Size and the bit that reads

y=as.real(pop.data$"Growth Rate")

the y vector required by the BUGS program is composed of a column in your data frame called Growth Rate (pretty cool, I think). It is important for you to understand that the lhs of the = in corresponds to the what the data are called in the BUGS program and the rhs of the = is what they are called in R. Also, note that because pop.data is a data frame I used as.real( ) to be sure that BUGS received real numbers instead of characters or factors, as can happen with data frames. This can be particularly important if you have missing data in the data matrix. The n is required in the BUGS program to index the for loop (see the code) and it must be read as data in this statement. By the way, you don’t need to call this list “data”---it could be anything (“apples”, “bookshelves”, “xy” etc.)

Interface between R and BUGS: JAGSThis section is for JAGS users. WinBUGS users should go to the next section.

Now that you have a list of data and initial values (which I include below for clarity) for the MCMC chain you make calls to JAGS using the following:

7 Actually, if you fail to specify initial values, JAG and WinBUGS will choose them for you, but they often way off. At best, this means that your chains will take a long time to converge; at worst, your model won’t run. My rule is, always specify good initial conditions based on your best knowledge of what the parameter values should be..

12

Page 13: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

setwd("/Users/Tom/Documents/Ecological Modeling Course/WinBUGS manual/Primer of MCMC Sampling Software for Ecologists/")

rm(list=ls())pop.data=(read.csv("Logistic Data"))names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05))

n.xy = nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"), y=as.real(pop.data$"Growth Rate"))library(rjags)

##call to JAGSjm=jags.model("Logistic example BUGS.R",data=data,inits,n.chains=length(inits), n.adapt = 10000)

zm=coda.samples(jm,variable.names=c("K", "r", "sigma"), n.iter=50000, n.thin=1)

The first statement (jm = ....) creates and initializes then MCMC chain. Its first argument is the name of the file containing the BUGS code. Note that in this case, the file resided in the default working directory, which I specified at the top of the file. Otherwise, you would need to specify the full path name. The next two expressions specify where the data come from, where to get the initial values, and how many chains to create (i.e., the length of the list inits). Finally, it specifies the “burn-in” how many samples to throw away before beginning to save values in the chain. Thus, in this case, we will throw away the first 10,000 values.

The second statement (zm=coda.samples...) creates the chains. The first argument (jm) is the name of the jags model you created in the first step. The second argument (variable.names) tells JAGS which variables to “monitor.” These are the variables for which you want output. Finally, n.iter=50000 says we want 50000 elements in each chain and n.thin specifies which of these to keep. For example, if n.thin = 10, we would store every 10th element. Sometimes setting n.thin > 1 is a good idea to reduce autocorrelation and to reduce the size of the data files that you will analyze.

And that’s it. If you have been thinking pure thoughts and paying attention to your coding, your model will run. If not (more likely, I am afraid), error messages will appear on the R console. Do some sleuthing using the section on trouble shooting, below.

Interface between R and BUGS: WinBUGS

13

Page 14: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Now that you have a list of data and initial values (which I include below for clarity) for the MCMC chain you make calls to WinBUGS using the following:##call to WinBUGSrm(list=ls())pop.data=(read.csv("Logistic Data"))names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05))

n.xy = nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"),y=as.real(pop.data$"Growth Rate"))##call to Winbugslibrary(R2WinBUGS)zm.bugs = bugs(

data=data,parameters.to.save = c("r","K","sigma"),inits=inits,n.thin = 1, n.burnin = 10000,model.file = "/BUGS/Logis.R",n.chains = length(inits),n.iter=50000,codaPkg = TRUE, debug=TRUE

) #end of bugs statementzm=read.bugs(zm.bugs)

Consider the long statement with zm.bugs on the left hand side. Here is what it does, part by part:

• data=data tells WinBUGS about the data it needs for the BUGS code. If you had named the data list “bookshelf”, then this statement would read data=bookshelf.

• parameters.to.save lists the variables for which you want posterior distributions (i.e. the variables you want “monitored”)

• inits names the list of lists containing the initial values• n.burnin specifies how may iterations to throw away. This is your estimate of the

number of iterations required to assure convergence. More about that later• model.file gives the location of the BUGS code. Remember to keep this pathname

brief. This is for a very good reason for brevity, discovered only after substantial suffering. There is a quirk with WinBUGS and R (also when you use WinBUGS scripts if you ever do) that produces an unintelligible error message “INCOMPATIBLE COPY.” Hmmm. Well, what this means is that the path name to your files and to the

14

Page 15: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

working directory are too long (isn’t that intuitive). If you have a terse, single level directory structure with folder names like “\ltr”, well you won’t need to worry about this. But if you are like me, you will need to set the working directory for R to something with a brief name (i.e., “C:/BUG”) and store your WinBUGS code there (not your R code). You also need to keep your file names short. You only need to do this until you get the code debugged and running. After that, you can store it anywhere because the error only occurs when WinBUGS is trying to send you an error message. However, it is vital to remember to copy your debugged file to a logical directory or to paste it to the bottom of the R script. Otherwise, you have files all over the place. One more thing. When you use file.choose() to get a path name, the path is specified using \\. These must be manually changed to /, as illustrated above. No whining. Live with it.

• n.chains specifies the number of different chains you want to run. To do any good, these must have different initial conditions as specified in the init list. Multiple chains are needed for convergence diagnostics, which are discussed below.

• coda.Pkg = TRUE tells BUGS to produce “coda” style output, which is the type we will use in this course. If you set coda.Pkg = FALSE you will get BUGS style output, which you can learn about by doing ?R2WinBUGS.

• debug = TRUE means that you want to pause to use the WinBUGS graphical interface to see error diagnostics. This will become apparent when you do it.

When you run R2WinBUGS with the debug option set to TRUE, then the WinBUGS gui appears when the iterations are complete. You must press the close button before R will function again. Sometimes it takes quite a long time (2 minutes?) for R to come back after a WinBUGS run where you monitor lots of variables. Be patient. You would set debug = FALSE when your code is running without errors if you wanted the interface to close automatically without displaying output. You might want this, for example if you were doing multiple runs of your model with calls to WinBUGS embedded in an R for loop.

If you are running WinBUGS, you must execute the statement

zm=read.bugs(zm.bugs)

before you execute the statements below. This creates an MCMC list from a bugs object--more about this later.

Getting simple output: JAGS and WinBUGS

Three statements are very useful for summarizing the output of your chains:

summary(zm)

produces the following at the console:

15

Page 16: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

If you enter traceplot(zm) you get a plot of the values of the chains across iterations, one per window, e.g.,

Entering densityplot(zm) gives plots of the posterior distributions:

16

Page 17: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

If you want single plots, you use syntax like

densityplot(zm)[1]

where 1 corresponds to the row number in the summary table (above). This becomes very handy if you have lots of output variables, as in the next example. You may not want to see density plots of everything. Unfortunately, this syntax doesn’t seem to work for traceplot().

Complete R script for JAGS (to this point)

So, the complete R program for JAGS is

setwd("/Users/Tom/Documents/Ecological Modeling Course/WinBUGS manual/Primer of MCMC Sampling Software for Ecologists/")rm(list=ls())pop.data=(read.csv("Logistic Data"))names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05))

n.xy = nrow(pop.data)

17

Page 18: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

data=list(n=n.xy, x=as.real(pop.data$"Population Size"),y=as.real(pop.data$"Growth Rate"))library(rjags)

##call to JAGSjm=jags.model("Logistic example BUGS.R",data=data,inits,n.chains=length(inits), n.adapt = 10000)

zm=coda.samples(jm,variable.names=c("K", "r", "sigma"), n.iter=50000, n.thin=1)

summary(zm)traceplot(zm)densityplot(zm)

Complete R script for WinBUGS

rm(list=ls())pop.data=(read.csv("Logistic Data"))names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05))

n.xy = nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"),y=as.real(pop.data$"Growth Rate"))##call to Winbugslibrary(R2WinBUGS)zm.bugs <-bugs(

data=data,parameters.to.save = c("r","K","sigma"),inits=inits,n.thin = 1, n.burnin = 10000,model.file = "/BUGS/Logis.R",n.chains = length(inits),n.iter=50000,codaPkg = TRUE, debug=TRUE

) #end of bugs statementzm=read.bugs(zm.bugs)summary(zm)traceplot(zm)

18

Page 19: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

densityplot(zm)

Exercise I: courtesy of McCarthy, M. A. 2007. Bayesian Methods for Ecology. Cambridge University Press, Cambridge, U. K.

Polis et. al. (1998) analyzed the probability of occupancy of islands (p) by lizards that as a function of the ratio of the islands’ perimeter to area (PA). The data from this investigation are available in islands.csv. The response data, as you will see, are 0-1, 0 if there were no lizards found on the island, 1 if there lizards were found. Please construct a simple Bayesian model that represents the probability of occupancy as logit(p) = a + b*PA showing what you have learned about logit functions and the Bernoulli distribution. Write out the Bayesian model. Estimate the posterior distribution of a and b using WinBUGS or JAGS. For now, you may ignore the problem of detection probability. You may assume uninformative priors.

Using the summary() listCongratulations on successfully coding your first BUGS program Continuing with our logistic example, what if you wanted to plot the model predictions against the observations, which, frankly, you should always do. To accomplish this, you would do the following. Modify your R statement by adding mu to the list of variables for which you want output, i.e.:

#For JAGSzm=coda.samples(jm,variable.names=c("K", "r", "sigma", “mu”), n.iter=50000, n.thin=1)

#For Windowszm.bugs <-bugs(

data=data,parameters.to.save = c("r","K","sigma", “mu”), #add mu hereinits=inits,n.thin = 1, n.burnin = 10000,model.file = "/BUGS/Logis.R",n.chains = length(inits),n.iter=50000,codaPkg = TRUE, debug=TRUE

) #end of bugs statement

Now, rerun the statements above and consider the following. The statement

19

Page 20: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

summary(zm)

now returns this:

Iterations = 10001:60000Thinning interval = 1 Number of chains = 1 Sample size per chain = 50000

1. Empirical mean and standard deviation for each variable, plus standard error of the mean:

Mean SD Naive SE Time-series SEK 1.209e+03 1.444e+02 6.460e-01 1.417e+00mu[1] 1.931e-01 2.108e-02 9.428e-05 1.492e-04mu[2] 1.562e-01 1.538e-02 6.880e-05 9.278e-05mu[3] 1.478e-01 1.424e-02 6.367e-05 8.063e-05mu[4] 1.258e-01 1.177e-02 5.264e-05 5.320e-05mu[5] 1.183e-01 1.116e-02 4.993e-05 4.659e-05mu[6] 8.788e-02 1.045e-02 4.674e-05 5.112e-05mu[7] 8.580e-02 1.052e-02 4.703e-05 5.320e-05mu[8] 6.607e-02 1.179e-02 5.273e-05 7.770e-05mu[9] 4.548e-02 1.409e-02 6.300e-05 1.077e-04mu[10] 3.129e-02 1.603e-02 7.171e-05 1.294e-04mu[11] 1.138e-02 1.907e-02 8.528e-05 1.606e-04r 2.052e-01 2.311e-02 1.033e-04 1.683e-04sigma 3.318e-02 8.932e-03 3.994e-05 5.217e-05

2. Quantiles for each variable:

2.5% 25% 50% 75% 97.5%K 1.000e+03 1.117e+03 1.187e+03 1.271e+03 1.556e+03mu[1] 1.497e-01 1.802e-01 1.932e-01 2.063e-01 2.345e-01mu[2] 1.245e-01 1.469e-01 1.563e-01 1.659e-01 1.863e-01mu[3] 1.186e-01 1.391e-01 1.479e-01 1.567e-01 1.755e-01mu[4] 1.020e-01 1.186e-01 1.258e-01 1.332e-01 1.488e-01mu[5] 9.569e-02 1.115e-01 1.184e-01 1.254e-01 1.402e-01mu[6] 6.676e-02 8.142e-02 8.791e-02 9.442e-02 1.087e-01mu[7] 6.450e-02 7.933e-02 8.585e-02 9.239e-02 1.068e-01mu[8] 4.232e-02 5.873e-02 6.613e-02 7.348e-02 8.977e-02mu[9] 1.694e-02 3.666e-02 4.560e-02 5.437e-02 7.377e-02mu[10] -1.075e-03 2.118e-02 3.141e-02 4.140e-02 6.335e-02mu[11] -2.703e-02 -6.485e-04 1.153e-02 2.344e-02 4.944e-02r 1.576e-01 1.911e-01 2.054e-01 2.197e-01 2.507e-01

20

Page 21: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

sigma 2.084e-02 2.695e-02 3.154e-02 3.754e-02 5.539e-02

The summary() function returns a list consisting of two matrices, one that contains the statistics and the other that contains the quantiles for all of the variables that you asked BUGS to monitor (i.e., listed in parameters.to.save() or variable.names()). This list is extremely useful so you really must learn how to manipulate it. To extract the individual matrices from the list, you would use

zm$stat or zm$quantile

You now have a matrix that can be manipulated like any other. Try the following:

b=zm$statb[1:2,]b[1,1]

To complete this plotting example, study the following code. It contains some cool new tricks for your R locker [i.e., grep(), rownames()]. You may want to do a ? on commands that are not familiar to you.

#get the quantile part of the listzm.quantile=summary(zm)$quantile#make a vector with the rownumbers of rows containing mu in the row namemu.i=grep("mu", rownames(zm.quantile))#make some easy notation for Population Sizex=pop.data$"Population Size"#plot the median--could also use matplot hereplot(x,zm.quantile[mu.i,3],typ='l', xlab = "N", main = "Per Capita Growth Rate", ylab = "dN/dt * 1/N")#plot the datapoints(x,pop.data$"Growth Rate")#plot the upper credible intervallines(x,zm.quantile[mu.i,5], lty="dashed", col="red")lines(x,zm.quantile[mu.i,1], lty="dashed", col="red")

Talk to me or to one of the TA’s if you don’t thoroughly understand what is going on in this code.

If you get it right, you will produce, tad-dah--

21

Page 22: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Discuss with you lab mates where these credible intervals are coming from. What do they have to do with the MCMC chain?

Estimating Quantities of Interest Derived from Model ParametersA common difficulty when using frequentist statistics is how to calculate quantities of interest from estimates that you obtain from your analysis. Continuing our example, if we know estimate the means and variances of r and K from a regression analysis, then

how do we estimate

dNdt where

dNdt

N r rK

N

? This is particularly problematic for

frequentist approaches because this function is nonlinear and the variance of its output can be only approximated. Alternatively, using MCMC to estimate the posterior

distribution of

dNdt is easy and the posterior distribution forms the basis for estimating

variances, confidence envelopes, etc. Using MCMC, any quantity that is a function of a random variable becomes a random variable as you learned when you did the half life problem in the MCMC lab exercise.

Consider two quantities of interest that are functions of our estimates of the random

variables r and K: 1) the maximum rate of population growth

K2 , and 2) the rate of

population growth,

dNdt

N r rK

N

. We want to estimate the posterior distributions of

each of these quantities. This requires only minor modification to our BUGS code:

##Logistic example for Primermodel{#priors

22

Page 23: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

K~dgamma(.001,.001)r~dnorm(0.,.001)tau~ dgamma(.001,.001)sigma<-1/sqrt(tau)

#likelihoodfor(i in 1:n){

mu[i] <- r - r/K * x[i]y[i] ~ dnorm(mu[i],tau)}

#Calculate maximum growth rateKover2 <- K/2

#Calculate growth rate over range of N values. These#must be read in as datafor(j in 1:J){

dNdt[j] <- N[j]* (r - r/K *N[j])}

} #end of model

Notice two changes. First is the single line to calculate Kover2. Now take a look at the loop at the bottom of the code:

#Calculate growth rate over range of N values. These#must be read in as datafor(j in 1:J){

dNdt[j] <- N[j]* (r - r/K *N[j])}

I knew that dNdt was a curve and I wasn’t sure that the 11 data points would be sufficient to estimate that curve smoothly. So, I created a vector for N that took on values between 1 and 1500 in steps of 10 (well, actually steps of 10 for all except 1-10) and added the N vector to the data list in the R script. I also added the length of this vector as the scalar, J to the data list. Thus, the vector N and the scalar J in the BUGS code are data. The lovely plot below, shown in comparison with the original linear plot, is produced by the modification of the BUGS file (above) and the the R code beneath the plot.

There is some very important biology here. Notice that for a linear function our uncertainty remains relatively constant over the range of the function. Although uncertainty is greater for extreme values at the ends of the line (left panel), it is not

23

Page 24: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

markedly different. Not so for the nonlinear function (right panel). Uncertainty when the population size is large is enormous--for example, when the population 1100 individuals, it could be growing by almost 60 animals per year or declining annually by 24. This graph has fundamental implications for planning sustainable harvest in the face of uncertainty.

for JAGS:

pop.data=read.csv("Logistic Data")names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05)

)

#create vector of N's for calculating dNdtN=seq(0,1500,10)#substitute 1 for 0 in the N vectorN[N==0]=1n.xy=nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"), y=as.real(pop.data$"Growth Rate"), N=N, J=length(N))library(rjags)

##call to JAGSjm=jags.model("Logistic example BUGSII.R",data=data,inits,n.chains=length(inits), n.adapt = 10000)

24

Page 25: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

zm=coda.samples(jm,variable.names=c("K", "r", "sigma", "mu", "dNdt", "Kover2"), n.iter=50000, n.thin=1)

for WinBUGS:

pop.data=read.csv("Logistic Data")names(pop.data)=c("Year","Population Size", "Growth Rate")

inits=list(list(K=1500, r=.5, tau=.05)

)

#create vector of N's for calcuating dNdtN=seq(0,1500,10)#substitute 1 for 0 in the N vectorN[N==0]=1n.xy=nrow(pop.data)data=list(n=n.xy, x=as.real(pop.data$"Population Size"), y=as.real(pop.data$"Growth Rate"), N=N, J=length(N))##call to Winbugslibrary(R2WinBUGS)zm.bugs <-bugs(

data=data,parameters.to.save = c("r","K","mu", "Kover2", "dNdt"),inits=inits,n.thin = 1, n.burnin = 10000,model.file = "/BUGS/LogisII.R",n.chains = length(inits),n.iter=50000,codaPkg = TRUE, debug=TRUE

) #end of bugs statementzm=read.bugs(zm.bugs)

Output code for both:

#make a couple of summary matriceszm.quantile=summary(zm)$quantilezm.stat=summary(zm)$stat#set up 2 panel plotspar(mfrow=c(1,2))

#get the number of rows to make the next steps easyrows = nrow(zm.stat)

25

Page 26: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

#get some statistics you would likezm.stat[c(1,2,rows, rows-1),] zm.quantile[c(1,2,rows, rows-1),]##make a vecor with the rownumbers of rows containing mu in the row namemu.i=grep("mu", rownames(zm.quantile))#make some easy notation for Population Sizex=pop.data$"Population Size"#plot the median--could also use matplot hereplot(x,zm.quantile[mu.i,3],typ='l', xlab = "N", main = "Per Capita Growth Rate", ylab = "dN/dt * 1/N")#plot the datapoints(x,pop.data$"Growth Rate")#plot the upper credible intervallines(x,zm.quantile[mu.i,5], lty="dashed", col="red")#plot the lower credible intervallines(x,zm.quantile[mu.i,1], lty="dashed", col="red")legend(400,.20,legend=c("median", "95% Credible interval"), lty=c("solid","dashed"), col=c("black", "red"), bty="n")

#get the row numbers for dNdt dNdt.i=grep("dNdt", rownames(zm.quantile))#make some easy notationdNdt=zm.quantile[dNdt.i,]

plot(N,dNdt[,3], typ="l",ylim=c(0,110), xlab="N", ylab="dN/dt", main="Population Growth Rate")lines(N,dNdt[,1], lty="dashed", col="red")lines(N,dNdt[,5], lty="dashed", col="red")legend(5,110,legend=c("median", "95% Credible interval"), lty=c("solid","dashed"), col=c("black", "red"), bty="n")

Exercise 2Modify the model that you constructed in exercise 1 to allow you to output the individual predictions (i.e., the p[i]). Also, create a new variable that allow you to plot the probability of occurrence as a function of island PA ranging from 1-60. Make point plots of the median p[i] at each value of PA with points for the upper and lower 95% credible intervals. Also make a smooth line plot of the predictions across the range of 1-60 and a smooth plot of the upper and lower 95% credible intervals.

Comparing Parameter Values Between Populations

26

Page 27: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Imagine that you had data on two populations and you wanted to compare the strength of density dependent feedbacks to population growth rate between the two populations. We ask, which population has stronger feedbacks? Or we might hypothesize that population 2 has stronger feedbacks than population 1. We define the strength of density dependence as the slope of the line between per-capita population growth rate and population size (e.g., Wang et al. 2006). The data now look like this:

Think carefully about this problem. We now have a vector of parameters, i.e., K = K1,K2 and r = r1,r2. We also have a matrix of data with columns for population size and population growth rate for each population an rows containing values for each year. Although we are doing the simplest thing first (i.e., 2 populations) this example could easily be extended to more than 2 populations. Moreover, it could be modified to apply to any comparisons of parameter values between “populations,” where populations is used in its broadest sense to mean what we sample from. Please try to think broadly as you see what we are doing here, musing, “How could I modify this example to fit my research problem?”

Our simple Bayesian model is now:

i, j ri rixi, j

Ki

P r,K,1, 2 y,x P yi, j | i , i P ri P Ki P i i1

n

j1

2

P r,K,1, 2 y,x Normal yi, j | i , i Normal ri | 0,.001 Gamma Ki | .001,.001 Gamma i | .001,.001 i1

n

j1

2

Think about this model, being particularly careful to understand the subscripts. Now, consider the implementation of this model in BUGS code below:

##Logistic III example for Primermodel{#priorsfor(i in 1:n.pop){

27

Page 28: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

K[i]~dgamma(.001,.001)r[i]~dnorm(0.,.001)tau[i]~ dgamma(.001,.001)sigma[i]<-1/sqrt(tau[i])}

#likelihoodfor(j in 1:n.pop){

for(i in 1:n){mu[i,j] <- r[j] - r[j]/K[j] * x[i,j]y[i,j] ~ dnorm(mu[i,j],tau[j])} #end of i loop

} # end of j loop

# calculate strength of feedbacks and their ratios[1]<-r[1]/K[1]s[2]<-r[2]/K[2]ratio <- s[2]/s[1]

} #end of model

Notice that the code is virtually the same as for our first model, except that now we index the parameters and the observations. The really cool trick comes at the end. The quantity ratio tells us about the relative strength of density dependence. (It could be the relative value of any parameter relative to another--use you imagination here). Given that the credible interval on the ratio does not overlap 1, we can be confident that density dependent feedbacks in population 2 (i.e., s[2]) are stronger than feedbacks in population 1 (i.e. s[2]):

> summary(zm)$quantile 2.5% 25% 50% 75% 97.5%K[1] 1.002190e+03 1.115655e+03 1.185166e+03 1.270009e+03 1.557576e+03K[2] 6.206618e+02 6.753259e+02 7.063284e+02 7.431181e+02 8.664173e+02r[1] 1.588349e-01 1.908177e-01 2.052687e-01 2.196932e-01 2.506633e-01r[2] 1.728313e-01 2.094595e-01 2.250574e-01 2.404328e-01 2.736518e-01ratio 1.093860e+00 1.565790e+00 1.835414e+00 2.166422e+00 3.183662e+00s[1] 1.072269e-04 1.526994e-04 1.731944e-04 1.936909e-04 2.379542e-04s[2] 2.099020e-04 2.862172e-04 3.184726e-04 3.503766e-04 4.192468e-04sigma[1] 2.092391e-02 2.701965e-02 3.158954e-02 3.747498e-02 5.507619e-02sigma[2] 2.086381e-02 2.687533e-02 3.145780e-02 3.739067e-02 5.539449e-02

However, we might want to be more precise in our statements. We might want to say something about the probability that s[2] > s[1] or perhaps the probability that s[2] is twice as great as s[1]. I cover how to do this in the next section.

Using the MCMC ListMuch of the analytical power in the approach you are learning comes directly from the complete MCMC chains. The zm object that we have been producing in the examples above is a MCMC list. For example, lets say for illustration purposes that you only did

28

Page 29: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

10 iterations after a burn-in of 500. What would the zm object look like? For the previous example,

So, the list appears to have a single element, a matrix, with the iterations as rows and the variables as columns. To prove to yourself that is is correct, do something like

a=zm[[1]] # note the double brackets used to extract elements of a lista[1,] #the first row of the matrix

However, recall earlier that I showed you how to run more than one chain by including more than one set of initial conditions in the inits list. So, if we had specified 3 lists of initial conditions using something like:

inits=list(list(K=c(1500,1500), r=c(.5,.5), tau=c(.05,.05)),list(K=c(1000,1000), r=c(.4,.2), tau=c(.01,.07)),list(K=c(1300,1700), r=c(.2,.6), tau=c(.08,.01))

)

29

Page 30: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Then our zm object would be a list of 3 matrices that looks like this:

We can put these matrices together in a way that is really useful. Presume you produced a zm object as above with three chains. Consider the following code:

#make a data frame containing all three chainsc = as.data.frame(rbind(zm[[1]],zm[[2]], zm[[3]])) #note double bracketsplot(density(c$ratio), xlab = "Relative Strength of Density Dependence", xlim=c(0,5), main="Posterior Distribution of Ratio of Slopes")

plot(density(c$"K[1]"), xlab = "Carrying Capacity", xlim=c(400,1700), main="Posterior Distribution of K", ylim=c(0,.010))lines(density(c$"K[2]"), col = "red")legend(900,.009, legend=c("Population 1", "Population 2"), col=c("black", "red"), lty=c("solid", "solid"))

1-ecdf(c$ratio)(1.0) #probability that ratio > 11-ecdf(c$ratio)(1.5) #probability that ratio > 1.5

hist(c$ratio, breaks=500, xlim=c(0,5), freq=FALSE)

30

Page 31: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

abline(v=1.0, col="red")

Let’s look at some key bits to understand what’s going on. First,

c = as.data.frame(rbind(zm[[1]],zm[[2]], zm[[3]])) #note double brackets

This statement takes the chains from the zm MCMC list and combines them into a single data frame with the number of columns = number of variables and number of rows = 3 x the number of iterations. (Note that we should only do this if the chains are nicely mixed, that is, if they have converged on the same posterior distribution. We will learn more about how to test for that in the next section.) We now have a data frame that we can work with the same way we work with any data frame.

Most often, we create a data frame like this to serve two purposes. First, we may want publication quality plots of the posterior distributions; densityplot( ) is fine for quick looks a many variables with one command, but it doesn’t produce high quality output that we can control. The following code uses the data frame c to create some nice plots of the posterior densities.plot(density(c$ratio), xlab = "Relative Strength of Density Dependence", xlim=c(0,5), main="Posterior Distribution of Ratio of Slopes")plot(density(c$"K[1]"), xlab = "Carrying Capacity", xlim=c(400,1700), main="Posterior Distribution of K", ylim=c(0,.010))lines(density(c$"K[2]"), col = "red") #note quotes needed for [ ]legend(900,.009, legend=c("Population 1", "Population 2"), col=c("black", "red"), lty=c("solid", "solid"))

31

Page 32: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

The other reason we might use a data frame like c is to calculate the probabilities. Take a look at the lines that read:

#caclulcate probabilites for ratio exceeding 1 or 1.51-ecdf(c$ratio)(1.0) #probability that ratio >

1-ecdf(c$ratio)(1.5) #probability that ratio > 1.5

The console returns:

> #caclulcate probabilites for ratio exceeding 1 or 1.5> 1-ecdf(c$ratio)(1.0) #probability that ratio > 1[1] 0.9875> 1-ecdf(c$ratio)(1.5) #probability that ratio > 1.5[1] 0.8041733

This code provides a hypothesis test that the strength of density dependence is greater in population 2 compared with population 1. So we can be 99% sure that the dependence is stronger. We can only be 80% certain that it is 50% stronger. I think you can see how flexible this kind of statement could be in analyzing your data. Essentially, it allow us to set up any kind of comparison of interest and attach a probability statement to it.

So, given the utility of this function, you should understand it deeply. Here is what is going on. ecdf stands for “empirical cumulative density function.” It is the same as a cumulative density function we learned about in lecture (remember those?) but it is, well, empirical--that is, we look at a vector, in this case a chain, and we calculate the proportion of values that are less than or equal to the argument to the function. So ecdf(v)(x) gives the proportion of values of v that are less than or equal to x and 1-ecdf(v)(x) gives the proportion of elements of v that exceed x. If you wanted the proportion of values that were between x1 and x2, how would you do it?

So, what this function does is show graphically below. The histogram was created from a 50,000 element chain for ratio. The statement ecdf(c$ratio)(1.0) estimates the area to the left of the vertical red line (actually, the number of elements in the chain that are < 1.0 divided by 50,000) and 1-ecdf(c$ratio)(1.0) estimates the area to the right of the line.

32

Page 33: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Exercise 3Assume you are interested in 2 islands, 1 that has a perimeter to area ratio of 10, the other that has a perimeter to area ratio of 20. What is the 95% confidence interval on the difference in the probability of occupancy of the two islands based on the analysis you did above? What is the problbailty that the p[i] of the larger island is twice as great at the p[i] of the smaller one?

33

Page 34: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Checking for ConvergenceI have emphasized several times that chains must reach what is called a stationary distribution to allow reliable inferences on posterior distributions. You were able to graphically observed convergence in the MCMC lab exercise. There are three primary ways that we will evaluate convergence. As I mentioned above, my working habit is to get my model running using a single chain and then add others for “production” runs. The reasons for this is simple: two chains requires twice as much time to run as a single one. So, running 4 or 5 chains can be time consuming, even for simple models.

The first thing we do to evaluate convergence is to examine the chains themselves, which we can do with a traceplot() function. This is possible even with a single chain, as we saw above, but with multiple chains, we can evaluate mixing. Continuing the previous example above, we obtain the following traceplot, which is one of several that we obtain using the function traceplot(zm):

The different colors represent the different chains. They are well mixed and the horizontal line show that the mean of the distribution is not increasing or declining.

The corresponding density plot looks like

34

Page 35: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

It may be hard to see, but there are 3 different colors in the lines here, showing that all three chains have converged on the same posterior distribution.

Examples of chains that have not converged but that arrive at convergence are shown below.

35

Page 36: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Finally, there is a less artistic approach offered in the Gelman Diagnostic, which we obtain using the function:

#test for convergencegelman.diag(zm)

which produces the output

Potential scale reduction factors:

Point est. 97.5% quantileK[1] 1.02 1.02K[2] 1.00 1.00r[1] 1.00 1.00r[2] 1.00 1.00ratio 1.01 1.01s[1] 1.00 1.00s[2] 1.00 1.00sigma[1] 1.00 1.00sigma[2] 1.00 1.00

Each of the values for the upper confidence limit must be close to 1 if we are to be confident of convergence. If that value is much above 1 (say, 1.1) we should run more iterations. For detail on the Gelman statistic, do ?gelman.diag at the R prompt.

There are also diagnostics that will work on a single chain, see gweke.diag() and gweke.plot().

Checking SyntaxIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax errors quickly and easily. But, in the beginning, this can be, well, tedious. Here are a few tips on syntax checking in general, followed by a list of common errors for both WinBUGS and JAGS.

WinBUGSIf you have been thinking pure thoughts, you will get no syntax errors. However, this never happens to me. Common syntax errors include using = where you needed <-, mismatching parentheses, misspelling distribution or function names, failing to close }’s, leaving out commas, and so on. A surprising one is that the ^ for exponentiation is illegal. If you need to square sigma, then you must use (sigma*sigma) or

36

Page 37: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

pow(sigma,2) If you generate an error, WinBUGS stops at the GUI (if you have set debug = TRUE) and shows, in the lower left corner of the screen, a characteristically unintuitive message in text requiring 2 x glasses to read. The location of the offending syntax within your code is given by a wispy |. Believe me, the | is hard to see, but it is there, somewhere.

JAGSJAGS has many things to recommend it, but one of them is not the way it communicates syntax errors. There are a couple of ways to get around this--actually after a while it is not a problem because the syntax is simple and you will get a nose for what’s wrong. Until then, I strongly urge you to build up your code slowly, in sensible blocks with a few statements at a time. You must fill in the { } within for loops, but other than that, you can add code bit by bit, running the ....=jags.model(.... statement each time to assure your syntax is correct. If you have a syntax error you simply can’t find, then I suggest you 1) open WinBUGS under an emulator 2) Click File, new to open a program window, 3) Paste the offending JAGS code into the window, 4) Click on Model then specification, then check model. The error should be shown with a wispy I and there will a not terribly intuitive message in the lower left hand side of the scree.

These are reported at the R console with language something like:

Error in jags.model("Logistic example BUGSIII.R", data = data, inits, : Parse error on line 1

syntax error, unexpected $undefined, expecting ARROW or '~'

Pay no attention to the line number; it is meaningless. The statement itself can be helpful. Here are a few common ones. The parenthetical statements are mine:

syntax error, unexpected $undefined, expecting ARROW or '~'

(you used a = instead of a <-)

Error in jags.model("Logistic example BUGSIII.R", data = data, inits, : RUNTIME ERROR:Unknown distribution: dmorm

(dnorm was spelled incorrectly, dmorm)

syntax error, unexpected $end, expecting NAME or FUNC or FOR or '}'

You have mismatched [], () or {}

37

Page 38: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

#syntax error, unexpected NAME, expecting $end

The closing bracket for your model statement looks like this:

} #end of model

You must add a hard return after this line.

Some common error messagesJAGSFrom my notebook:

1) Never use _ as a part of a variable name, it reads as if it weren’t there—i.e. N_[i,j] reads as N[i,j] producing potential errors.

2) var is a reserved keyword, so variables cannot be name var.3) Let Y[i] be data. If you want to calculate a quantity based on the data, this cannot be

done in the main body of code the way it is in Winbugs.

Error in jags.model("test.R", data = data, inits, n.chains = 1, n.adapt = 10000) : RUNTIME ERROR:Unable to resolve parameter O[38,1:2] (one of its ancestors may be undefined)

If you change:

[33,] 61 447[34,] 79 351[35,] 54 175[36,] 47 260[37,] 53 287[38,] NA NA[39,] 29 231[40,] 25 404

38

Page 39: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

to

[33,] 61 447[34,] 79 351[35,] 54 175[36,] 47 260[37,] 53 287[38,] 9999 9999[39,] 29 231[40,] 25 404

and loop around it, the model runs. It appears to be treating the NA as a parameter because you loop around it—it never appears on the lhs of ~

Warning message:In readLines(file) : incomplete final line found on 'SS2.R'

will occur when you don’t have a hard return after the last } for the model.

error

syntax error, unexpected '}', expecting $end

occurs when there are mismatched parens

error JAGS does not allow model names:

model state_space_logistic {

must be

model { #state_space_logistic

errorsyntax error, unexpected DOUBLE, expecting FUNC

happens when you have a ~ and mean a <-

i.e.,

39

Page 40: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Wrong:tau.s[t] ~ 1/(sigma.s[t]*sigma.s[t])

right

tau.s[t] <- 1/(sigma.s[t]*sigma.s[t])

Error in setParameters(init.values[[i]], i) : Error in node sigma.s[1]Attempt to set value of non-variable node

You get this error when you have a variable in your init list that is not a variable in the model

When jags doesn’t run, i.e., you get:

> jm=jags.model("obs.model.jags.R", data=data, inits,n.chains=length(inits),n.adapt=n.adapt)Compiling data graph Declaring variables Resolving undeclared variables Allocating nodes Initializing Reading data back into data tableCompiling model graph Declaring variables Resolving undeclared variables Allocating nodes Graph Size: 258

and nothing happens, try switching uninformative gamma prior to uniform

If you are going to use a uniform for tau or sigma, it is better to put it on tau, i.e.,

tau ~ dunif(0,5)sigma <- 1/sqrt(tau)

rather than

sigma ~duinf(0,500)tau <- 1/(sigma*sigma)

This is because the former formulation is sensitive to your choice on the upper bound of the uniform if the data are sparse. The second form is not sensitive.

Error:

40

Page 41: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Error: Error in node x[3,5,193]All possible values have probability zero

caused by uninitialized values for the array x.

Error in setParameters(init.values[[i]], i) : Error in node sigmaAttempt to set value of non-variable node

when sigma is defined by <- instead of ~ and you have an init for sigma

Error in jags.model("Logistic example BUGSIII.R", data = data, inits, : RUNTIME ERROR:Unable to evaluate upper index of counter i

The value for the upper range of the loop was omitted from the data statement

Error in jags.model("IslandBugIII.R", data = data, inits, n.chains = length(inits), : RUNTIME ERROR:Unknown parameter P20

the parameter name was misspelled. Should have been p20

WinBUGSSyntax errors are usually pretty easy to figure out. However, once you model is syntactically correct, you are not out of the woods. Here are some errors that occur on compilation or

made use of undefined node—

This means you have variables in your code that are not data or stochastic quantities to be estimated (i.e., don’t have priors) and are not derive from data or stochastic quantities. It usually means a typo in variable name. Check spelling of the suspect variable. This can also happen when you have a quantity that is defined in terms of stochastic nodes that themselves don’t have priors or if you have a stochastic node that is outside of the model statement.

this chain contains uninitialized variablesYou have not initialized all variables. Remember, anything on the lhs of a ~ that is not data must be initialized.

41

Page 42: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

multiple definitions of node [x]

You have a variable that should be indexed in a loop, and is not indexed.

incompatible copypath names are too long when writing scripts (not recommended) or when using R2WinBUGS

array index is greater than array upper bound

An index to a loop in WinBUGS exceeds the number of data items indexed.

WinBUGS hangs at the compile stepYou probably have a structure that is something like this:

for(t in 2:n){w[t] = some function of w[t-1]w[t]~dnorm(w[t], tau.p)

}

WinBUGS cannot recursively update arrays. You need code something like this:

for(t in 2:n){w.hat[t] = some function of w[t-1]w[t]~dnorm(what[t], tau.p)

}

Splus data 100 You have a vector of initial conditions that is the wrong length. I know, I know, this is not a terribly informative message.

Cannot Bracket Slice for NodShape parameter of gamma r too small. Chances are this occurs when all stochastic nodes (all) have not been initialized. If the gen ints( ) is not greyed out, you have not initialized everything. This can occur when you have arrays of initial values that go from 1-N, but you loop over 2:N. You then get a message that the first value is not stochastic, and WinBUGS generates initial values for you, whether you want them or not. In this case, you need to put an NA for the first element of the initial value array.

One more thing:

Never use 2 periods in notation, for example

42

Page 43: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

y.s.neg should be ys.neg or y.neg but never y.s.neg. For reasons unknown, the double . produces bad results but no error. Be warned.

Differences Between JAGS and WinBUGSThere are a couple of important differences between JAGS and WinBUGS that are covered nicely in the JAGS manual. In short, these have to do with data transformation, which must be done in a data statement. Quoting the JAGS manual:

There are also some operations that are not found in the WinBUGS implementation, notably matrix multiplication, exponentiation via ^, and the ability to write user-defined operators.

43

Page 44: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

BibliographyKnops, J. M. H., and D. Tilman. 2000. Dynamics of soil nitrogen and carbon

accumulation for 61 years after agricultural abandonment. Ecology 81:88-98.Polis, G. A., S. D. Hurd, C. T. Jackson, and F. Sanchez-Pinero. 1998. Multifactor

population limitation: Variable spatial and temporal control of spiders on Gulf of California islands. Ecology 79:490-502.

Wang, G. M., N. T. Hobbs, R. B. Boone, A. W. Illius, I. J. Gordon, J. E. Gross, and K. L. Hamlin. 2006. Spatial and temporal variability modify density dependence in populations of large herbivores. Ecology 87:95-102.

44

Page 45: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Appendix 1: Reference material for JAGSDistributions

45

Page 46: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Functions and operators

46

Page 47: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

47

Page 48: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Reference Material for WinBUGSDistributions

48

Page 49: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

49

Page 50: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

50

Page 51: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

51

Page 52: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Functions and Operators

Note that the ^ for exponentiation is not a permitted operation in WinBUGS. You must use the pow( ) function below.

52

Page 53: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

53

Page 54: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Appendix 2: Answers to Exercises

Exercise 1

log it pi a bxi

P a,b,| y,x Bernoulli yi | pi Normal a | 0,.000001 Normal b | 0,.000001 i1

19

BUGS code

model{ a ~ dnorm(0, 1.0E-6) # uninformative intercept term b ~ dnorm(0, 1.0E-6) # uninformative effect of PA

for (i in 1:n) # for each island { logit(p[i]) <- a + b*PA[i] # logit(p) a function of PA y[i] ~ dbern(p[i]) # observed occurrence drawn from Bernoulli dist'n }} #end of model

R code:

setwd("/Users/Tom/Documents/Ecological Modeling Course/WinBUGS manual/Primer of MCMC Sampling Software for Ecologists")rm(list=ls())islands=read.csv("island data.csv")

data=list(PA=islands[,1], y=islands[,2], n=nrow(islands) )inits=list(

list(a=0,b=0))

jm=jags.model("IslandBug.R",data=data,inits,n.chains=length(inits), n.adapt = 10000)

zm=coda.samples(jm,variable.names=c("a","b"), n.iter=50000, n.thin=1)

#for WinBUGSlibrary(R2WinBUGS)zm.bugs <-bugs(

data=data,

54

Page 55: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

parameters.to.save = c("a","b"),inits=inits,n.thin = 1,n.burnin = 10000,model.file = "/BUGS/IslandI.R",n.chains = length(inits),n.iter=50000,codaPkg = TRUE, debug=TRUE

) #end of bugs statementzm=read.bugs(zm.bugs)

traceplot(zm)densityplot(zm)summary(zm)

Exercise 2

55

Page 56: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

Bugs code

model{ a ~ dnorm(0, 1.0E-6) # uninformative intercept term

56

Page 57: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

b ~ dnorm(0, 1.0E-6) # uninformative effect of PA

for (i in 1:n) # for each island { logit(p[i]) <- a + b*PA[i] # logit(p) a function of PA y[i] ~ dbern(p[i]) # observed occurrence drawn from Bernoulli dist'n } for(j in 1:n.pred){ #p.hat[j] <- ilogit(a + b*x[j]) # for use with JAGS p.hat[j] <- exp(a + b*x[j]) / (1 + exp(a + b*x[j])) #for use with JAGS or WinBUGS } } #end of model

R codesetwd("/Users/Tom/Documents/Ecological Modeling Course/WinBUGS manual/Primer of MCMC Sampling Software for Ecologists")rm(list=ls())islands=read.csv("island data.csv")

#make a sequence to get predicted valuesx=seq(1,60)data=list(PA=islands[,1], y=islands[,2], n=nrow(islands), x=x, n.pred=length(x))inits=list(

list(a=0,b=0))

#for JAGSlibrary(rjags)jm=jags.model("IslandsBugII.R",data=data,inits,n.chains=length(inits), n.adapt = 10000)

zm=coda.samples(jm,variable.names=c("a","b", "p", "p.hat"), n.iter=50000, n.thin=1)

#for WinBUGSlibrary(R2WinBUGS)zm.bugs <-bugs(

data=data,parameters.to.save = c("a","b", "p", "p.hat"),inits=inits,n.thin = 1,

57

Page 58: A Tutorial on Gibbs Sampling Software for …stevel/565/literatur… · Web viewIf you do much work with this software, you will learn the syntax and will be able to sleuth syntax

n.burnin = 10000,model.file = "/BUGS/IslandII.R",n.chains = length(inits),n.iter=50000,codaPkg = TRUE, debug=TRUE

) #end of bugs statementzm=read.bugs(zm.bugs)

#get the quantiless=summary(zm)$quantile#find the predictions at data points. Note fixed = TRUEp1=grep("p[", rownames(s), fixed=TRUE)#plot median and credible intervalsplot(islands[,1],s[p1,3], xlab="Perimeter to Area Ratio", ylab= "Probability Occupied")points(islands[,1],s[p1,5], pch=18)points(islands[,1],s[p1,1], pch=18)

#find the predictions over 1-60p2=grep("p.hat", rownames(s), fixed=TRUE)#plot median and credible intervalsplot(x,s[p2,3], xlab="Perimeter to Area Ratio", ylab= "Probability Occupied", typ='l')lines(x,s[p2,5], lty="dashed")lines(x,s[p2,1], lty="dashed")

Exercise 3

95% CI = .19 - .85

Probability that the larger island (smaller PA) is more than twice as likely to have a lizard as the smaller island = .76

58