Though there is MCMCpack and also Stan, just fun to walk thy random walk.
metrop.rwalker.proposal.fun <- function(theta){
# finding the right scaling factor is more of an art than science
# or try and error to look for the best fit on acceptance %, ideally .234
# good starting point 2.38/sqrt(N.dimensions)
# looking to replace rnorm with multivariate version mvrnorm ?
n.theta <- length(theta)
scale.sd <- round(2.38/sqrt(n.theta), 2)
return(rnorm(n=n.theta, mean=theta, sd=rep(scale.sd, n.theta)))
}
hamiltonian.proposal.fun <- function(theta){
#forget it.. it is a good theory
# H(q, p) = U(q) + K(p) .. the potential and kinetic energy
# simulate data by the way of the physical system moves than a random walk
# faster convergence
# more parameters to worry: epsilon, M, t, L
# not to mention the change of proposal..
# U(q) = -log[pi(q) * L(q|D)]
# hmc proposal and actual simulation is tight up
# condition:
# runif(1) < exp(-U(q*)+U(q)-K(p*)+K(p))
# no to mention the painful gradient (log likelihood function)
# there are research work being done on the gradient free hamiltonian
# don't quote on me, it is still an exciting new area
#
# good read, I'll leave the work for others :)
# indeed, please refer to hmc.r
#
# for now, it does exactly the random walk if hmc = TRUE
return(theta+rnorm(length(theta), sd=2.38))
}
# Metroplis Hasting Monte Carlo Simulation
# currently not support thinning nor multiple chains
# fun .......... the logged posterior sampling function
# theta.init ... initial parameter(s) value
# nmc .......... number of iterations for the chain
# nbi .......... number of burn-ins
# hmc .......... reserved for future Hamiltonian or RWHMC implementation
mcmc <- function(fun, theta.init, nmc, nbi, hmc = FALSE, ...) {
iterations <- nmc + nbi
chain <- array(dim = c(iterations, length(theta.init)))
chain[1, ] <- theta.init
# choose the proposal function
if(hmc){
propose <- hamiltonian.proposal.fun #hamiltonian
}else{
propose <- metrop.rwalker.proposal.fun #metroplis
}
for(i in 1:(iterations-1)) {
proposal <- propose(chain[i, ])
p <- exp(fun(proposal, ...) - fun(chain[i, ], ...))
if(runif(1) < p) {
chain[i+1, ] <- proposal #accept
}else{
chain[i+1, ] <- chain[i, ] #reject
}
}
return(chain[-(1:nbi), ])
}
LS0tDQp0aXRsZTogIm1jbWMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaG91Z2ggdGhlcmUgaXMgX01DTUNwYWNrXyBhbmQgYWxzbyBfU3Rhbl8sIGp1c3QgZnVuIHRvIHdhbGsgdGh5IF9yYW5kb20gd2Fsa18uDQoNCmBgYHtyfQ0KbWV0cm9wLnJ3YWxrZXIucHJvcG9zYWwuZnVuIDwtIGZ1bmN0aW9uKHRoZXRhKXsNCiAgIyBmaW5kaW5nIHRoZSByaWdodCBzY2FsaW5nIGZhY3RvciBpcyBtb3JlIG9mIGFuIGFydCB0aGFuIHNjaWVuY2UNCiAgIyBvciB0cnkgYW5kIGVycm9yIHRvIGxvb2sgZm9yIHRoZSBiZXN0IGZpdCBvbiBhY2NlcHRhbmNlICUsIGlkZWFsbHkgLjIzNA0KICAjIGdvb2Qgc3RhcnRpbmcgcG9pbnQgMi4zOC9zcXJ0KE4uZGltZW5zaW9ucykNCiAgIyBsb29raW5nIHRvIHJlcGxhY2Ugcm5vcm0gd2l0aCBtdWx0aXZhcmlhdGUgdmVyc2lvbiBtdnJub3JtID8gDQoNCiAgbi50aGV0YSAgPC0gbGVuZ3RoKHRoZXRhKQ0KICBzY2FsZS5zZCA8LSByb3VuZCgyLjM4L3NxcnQobi50aGV0YSksIDIpDQogIHJldHVybihybm9ybShuPW4udGhldGEsIG1lYW49dGhldGEsIHNkPXJlcChzY2FsZS5zZCwgbi50aGV0YSkpKQ0KfQ0KDQpoYW1pbHRvbmlhbi5wcm9wb3NhbC5mdW4gPC0gZnVuY3Rpb24odGhldGEpew0KICAjZm9yZ2V0IGl0Li4gaXQgaXMgYSBnb29kIHRoZW9yeQ0KICAjIEgocSwgcCkgPSBVKHEpICsgSyhwKSAuLiB0aGUgcG90ZW50aWFsIGFuZCBraW5ldGljIGVuZXJneQ0KICAjIHNpbXVsYXRlIGRhdGEgYnkgdGhlIHdheSBvZiB0aGUgcGh5c2ljYWwgc3lzdGVtIG1vdmVzIHRoYW4gYSByYW5kb20gd2Fsaw0KICAjIGZhc3RlciBjb252ZXJnZW5jZQ0KICAjIG1vcmUgcGFyYW1ldGVycyB0byB3b3JyeTogZXBzaWxvbiwgTSwgdCwgTA0KICAjIG5vdCB0byBtZW50aW9uIHRoZSBjaGFuZ2Ugb2YgcHJvcG9zYWwuLg0KICAjICAgVShxKSA9IC1sb2dbcGkocSkgKiBMKHF8RCldDQogICMgaG1jIHByb3Bvc2FsIGFuZCBhY3R1YWwgc2ltdWxhdGlvbiBpcyB0aWdodCB1cA0KICAjICBjb25kaXRpb246DQogICMgICAgIHJ1bmlmKDEpIDwgZXhwKC1VKHEqKStVKHEpLUsocCopK0socCkpDQogICMgbm8gdG8gbWVudGlvbiB0aGUgcGFpbmZ1bCBncmFkaWVudCAobG9nIGxpa2VsaWhvb2QgZnVuY3Rpb24pDQogICMgdGhlcmUgYXJlIHJlc2VhcmNoIHdvcmsgYmVpbmcgZG9uZSBvbiB0aGUgZ3JhZGllbnQgZnJlZSBoYW1pbHRvbmlhbg0KICAjIGRvbid0IHF1b3RlIG9uIG1lLCBpdCBpcyBzdGlsbCBhbiBleGNpdGluZyBuZXcgYXJlYQ0KICAjDQogICMgZ29vZCByZWFkLCBJJ2xsIGxlYXZlIHRoZSB3b3JrIGZvciBvdGhlcnMgOikNCiAgIyBpbmRlZWQsIHBsZWFzZSByZWZlciB0byBobWMucg0KICAjDQogICMgZm9yIG5vdywgaXQgZG9lcyBleGFjdGx5IHRoZSByYW5kb20gd2FsayBpZiBobWMgPSBUUlVFDQoNCiAgcmV0dXJuKHRoZXRhK3Jub3JtKGxlbmd0aCh0aGV0YSksIHNkPTIuMzgpKQ0KfQ0KDQojIE1ldHJvcGxpcyBIYXN0aW5nIE1vbnRlIENhcmxvIFNpbXVsYXRpb24NCiMgY3VycmVudGx5IG5vdCBzdXBwb3J0IHRoaW5uaW5nIG5vciBtdWx0aXBsZSBjaGFpbnMNCiMgZnVuIC4uLi4uLi4uLi4gdGhlIGxvZ2dlZCBwb3N0ZXJpb3Igc2FtcGxpbmcgZnVuY3Rpb24NCiMgdGhldGEuaW5pdCAuLi4gaW5pdGlhbCBwYXJhbWV0ZXIocykgdmFsdWUNCiMgbm1jIC4uLi4uLi4uLi4gbnVtYmVyIG9mIGl0ZXJhdGlvbnMgZm9yIHRoZSBjaGFpbg0KIyBuYmkgLi4uLi4uLi4uLiBudW1iZXIgb2YgYnVybi1pbnMNCiMgaG1jIC4uLi4uLi4uLi4gcmVzZXJ2ZWQgZm9yIGZ1dHVyZSBIYW1pbHRvbmlhbiBvciBSV0hNQyBpbXBsZW1lbnRhdGlvbg0KbWNtYyA8LSBmdW5jdGlvbihmdW4sIHRoZXRhLmluaXQsIG5tYywgbmJpLCBobWMgPSBGQUxTRSwgLi4uKSB7DQoNCiAgaXRlcmF0aW9ucyA8LSBubWMgKyBuYmkNCiAgY2hhaW4gPC0gYXJyYXkoZGltID0gYyhpdGVyYXRpb25zLCBsZW5ndGgodGhldGEuaW5pdCkpKQ0KICBjaGFpblsxLCBdIDwtIHRoZXRhLmluaXQNCg0KICAjIGNob29zZSB0aGUgcHJvcG9zYWwgZnVuY3Rpb24NCiAgaWYoaG1jKXsNCiAgICBwcm9wb3NlIDwtIGhhbWlsdG9uaWFuLnByb3Bvc2FsLmZ1biAgICAgICAgICAjaGFtaWx0b25pYW4NCiAgfWVsc2V7DQogICAgcHJvcG9zZSA8LSBtZXRyb3AucndhbGtlci5wcm9wb3NhbC5mdW4gICAgICAgI21ldHJvcGxpcw0KICB9DQoNCiAgZm9yKGkgaW4gMTooaXRlcmF0aW9ucy0xKSkgew0KICAgIHByb3Bvc2FsIDwtIHByb3Bvc2UoY2hhaW5baSwgXSkNCiAgICBwIDwtIGV4cChmdW4ocHJvcG9zYWwsIC4uLikgLSBmdW4oY2hhaW5baSwgXSwgLi4uKSkNCg0KICAgIGlmKHJ1bmlmKDEpIDwgcCkgew0KICAgICAgY2hhaW5baSsxLCBdIDwtIHByb3Bvc2FsICAgICAgICNhY2NlcHQNCiAgICB9ZWxzZXsNCiAgICAgIGNoYWluW2krMSwgXSA8LSBjaGFpbltpLCBdICAgICAjcmVqZWN0DQogICAgfQ0KICB9DQoNCiAgcmV0dXJuKGNoYWluWy0oMTpuYmkpLCBdKQ0KfQ0KYGBgDQoNCg==