I'm trying to implement a random walk Metropolis-Hastings algorithm in R. I have used the the self-defined functions logit
and invlogit
to apply and undo the logit function. I have also used the normal distribution to add random noise. Given these two facts, once you use the inverse transformation on the transformed parameter + random noise, the proposal distribution is no longer symmetric, which is why I then apply the corrective term log(yt*(1 - yt)) - log(xt*(1 - xt))
to the acceptance probability.
My problem is that there seems to be two ways to implement this algorithm in R. If both of these ways were equal, then, as I understand it, I should be getting equal values for both when calculating acceptanceRate
. However, this is not the case, which leads me to believe that one implementation is flawed (has bugs) and the other doesn't.
However, two other possibilities are that (1) both ways are incorrect or (2) both ways are correct and I'm misunderstanding something. I'm new to R coding, and I still can't understand why these deviations exist in the value of acceptanceRate
between the two implementations.
Note: my specific problem of interest is why I'm getting different value for acceptanceRate
between the two implementations.
Implementation 1
log.posterior <- function(p) (12+p)*log(p) + (9-p)*log(1-p)
B <- 10000 ## number of realisations we want to have
chain <- rep(0, B+1) ## vector to hold realisations
chain[1] <- 0.5 ## initial value
num.accept <- 0 ## keep track on how often we accept proposals
for(i in 1:B){
xt <- chain[i] ## current point
logit <- function(p) log(p/(1-p))
invlogit <- function(lo) 1/(1 + exp(-lo))
yt <- invlogit(rnorm(1, mean = logit(xt), sd = 0.45)) ## proposal
lapt <- log.posterior(yt) - log.posterior(xt) + log(yt*(1 - yt)) - log(xt*(1 - xt)) ## acceptance probability on the log scale)
if( runif(1) <= exp(lapt) ){
chain[i+1] <- yt ## accept proposal if runif(1) is less or equal to the acceptance probility
num.accept <- num.accept + 1 ## proposal was accepted
}else
chain[i+1] <- xt ## reject proposal
}
acceptanceRate <- num.accept/B
See how implementation 1 uses yt <- invlogit(rnorm(1, mean = logit(xt), sd = 0.45))
? Everything is accumulated and done together.
Implementation 2
log.posterior <- function(p) (12+p)*log(p) + (9-p)*log(1-p)
B <- 10000 ## number of realisations we want to have
chain <- rep(0, B+1) ## vector to hold realisations
chain[1] <- 0.5 ## initial value
num.accept <- 0 ## keep track on how often we accept proposals
for(i in 1:B){
xt <- chain[i] ## current point
logit <- function(p) log(p/(1-p))
xt <- logit(xt)
yt <- xt + rnorm(1, mean = 0, sd = 0.45) ## proposal
invlogit <- function(lo) 1/(1 + exp(-lo))
xt <- invlogit(xt)
yt <- invlogit(yt)
lapt <- log.posterior(yt) - log.posterior(xt) + log(yt*(1 - yt)) - log(xt*(1 - xt)) ## acceptance probability on the log scale)
if( runif(1) <= exp(lapt) ){
chain[i+1] <- yt ## accept proposal if runif(1) is less or equal to the acceptance probility
num.accept <- num.accept + 1 ## proposal was accepted
}else
chain[i+1] <- xt ## reject proposal
}
acceptanceRate <- num.accept/B
Notice that implementation 2 breaks everything down into separate pieces are proceeds sequentially.