我尝试使用R中的Metropolis算法从二元密度进行模拟,但是没有运气。密度可以表示为 ,其中是Singh-Maddala分布
参数,q,b和p(y | x)是对数正态的,其中log-mean是x的分数,而log-sd是常数。为了测试我的样本是否是我想要的样本,我查看了x的边际密度,其应为p(x)。我尝试了R包MCMCpack,mcmc和dream中的不同Metropolis算法。我舍弃了老化,使用细化处理,使用了大小不超过100万的样本,但是由此产生的边际密度从来不是我提供的那种。
这是我使用的代码的最终版本:
logvrls <- function(x,el,sdlog,a,scl,q.arg) {
if(x[2]>0) {
dlnorm(x[1],meanlog=el*log(x[2]),sdlog=sdlog,log=TRUE)+
dsinmad(x[2],a=a,scale=scl,q.arg=q.arg,log=TRUE)
}
else -Inf
}
a <- 1.35
q <- 3.3
scale <- 10/gamma(1 + 1/a)/gamma(q - 1/a)* gamma(q)
Initvrls <- function(pars,nseq,meanlog,sdlog,a,scale,q) {
cbind(rlnorm(nseq,meanlog,sdlog),rsinmad(nseq,a,scale,q))
}
library(dream)
aa <- dream(logvrls,
func.type="logposterior.density",
pars=list(c(0,Inf),c(0,Inf)),
FUN.pars=list(el=0.2,sdlog=0.2,a=a,scl=scale,q.arg=q),
INIT=Initvrls,
INIT.pars=list(meanlog=1,sdlog=0.1,a=a,scale=scale,q=q),
control=list(nseq=3,thin.t=10)
)
我选择了理想的方案,因为它一直采样直至收敛。我已经通过三种方式测试了我是否具有正确的结果。使用KS统计量,比较分位数,并根据所得样本的最大似然估计Singh-Maddala分布的参数:
ks.test(as.numeric(aa$Seq[[2]][,2]),psinmad,a=a,scale=scale,q.arg=q)
lsinmad <- function(x,sample)
sum(dsinmad(sample,a=x[1],scale=x[2],q.arg=x[3],log=TRUE))
optim(c(2,20,2),lsinmad,method="BFGS",sample=aa$Seq[[1]][,2])
qq <- eq(0.025,.975,by=0.025)
tst <- cbind(qq,
sapply(aa$Seq,function(l)round(quantile(l[,2],qq),3)),
round(qsinmad(qq,a,scale,q),3))
colnames(tst) <- c("Quantile","S1","S2","S3","True")
library(ggplot2)
qplot(x=Quantile,y=value,
data=melt(data.frame(tst),id=1),
colour=variable,group=variable,geom="line")
当我查看这些比较的结果时,KS统计量几乎总是拒绝零假设,即样本来自具有提供参数的Singh-Maddala分布。最大似然估计参数有时接近其真实值,但通常离舒适区太远,以致无法接受采样过程成功。与分位数一样,经验分位数不是太远,而是太远。
我的问题是我做错了什么?我自己的假设:
- MCMC不适合此类采样
- 由于理论上的原因,MCMC无法收敛(分布函数不满足所需的性质,无论它们是什么)
- 我没有正确使用Metropolis算法
- 我的分布测试不正确,因为我没有独立的样本。
抱歉,维基百科链接引用了错误的公式,当我编写问题时,乍一看似乎还可以。我没有找到可用的链接,因此只将公式放在问题中。
—
mpiktas 2010年
dsinmad
需要三个参数,或者我错过了什么。