在编写似然函数时使用积分的问题

时间:2012-05-24 15:02:02

标签: r

我正在尝试编写由集成定义的分布的似然函数。我正在使用integrate()函数,但当我尝试在函数的其余部分使用它时,我得到错误:

“B中的错误(alpha + i,beta + 6 - i)/ B(alpha,beta):二元运算符的非数字参数”

积分的值例如是“9.501501,绝对误差<0.00078”。我试过使用trunc(),但这也无济于事。我对R比较陌生,所以有一个已知的解决方案吗?任何帮助将不胜感激!

B <- function(a,b){ 
   integrand <- function(t){(t^(a-1))*((1-t)^(b-1))} 
   integrate(integrand,lower=0,upper=1) 
} 
betalik <- function(alpha,beta){ 
    likelihood <- 0 Z <- c(37,22,25,29,34,49) 
    for(i in 1:6) 
       likelihood <- likelihood + 
         Z[i]*log((B(alpha+i,beta+6-i))/B(alpha,beta)) 
    return(likelihood) 

}

道连,

2 个答案:

答案 0 :(得分:4)

使用?integrate ....

中的整合示例
integrate(dnorm, -1.96, 1.96)
# 0.9500042 with absolute error < 1e-11

这里到底发生了什么?那么,集成函数创建一个“集成”类S3对象,它基本上是一个包含许多字段的列表,然后将print()应用于它,依次执行print.integrate()。该函数的输出实际上字符串“0.9500042,绝对错误<1e-11”,它只是以这种方式显示。

要了解integrate()实际创建的R对象,请执行

obj = integrate(dnorm, -1.96, 1.96)
str(obj)
# List of 5
# $ value       : num 0.95
# $ abs.error   : num 1.05e-11
# $ subdivisions: int 1
# $ message     : chr "OK"
# $ call        : language integrate(f = dnorm, lower = -1.96, upper = 1.96)
# - attr(*, "class")= chr "integrate"

因此,如果您只想要积分值,那么您必须提取该函数创建的列表的value字段,以便进行计算。 E.g。

10*integrate(dnorm, -1.96, 1.96)$value
# [1] 9.500042

答案 1 :(得分:4)

跟进上面的评论和答案......

以下是您的原始函数,格式更精确,整合@Fhnuzoag关于从$value结果中提取integrate()组件的注释:

B <- function(a,b){
    integrand <- function(t){(t^(a-1))*((1-t)^(b-1))}
    integrate(integrand,lower=0,upper=1)$value
}
betalik <- function(alpha,beta){
    likelihood <- 0
    Z <- c(37,22,25,29,34,49)
    for(i in 1:6) likelihood <- likelihood +
        Z[i]*log((B(alpha+i,beta+6-i))/B(alpha,beta))
    return(likelihood)
} 

在这里,我们检查@dason的评论,即你的B函数等同于R的内置beta函数(但R函数当然更快,可能更准确):

all.equal(B(1.1,2.7),beta(1.1,2.7))  ## TRUE

我更喜欢分别指定'数据':

Z <- c(37,22,25,29,34,49)

使用内置lbeta(log-beta)函数的似然函数的新版本,并进行了矢量化:

blik2 <- function(alpha,beta,Z) {
    index <- 1:6
    sum(Z*(lbeta(alpha+index,beta+6-index)-lbeta(alpha,beta)))
}

all.equal(blik2(1.1,2.7,Z),betalik(1.1,2.7))
## small difference, blik2 is *probably* more
##   accurate ... "Mean relative difference: 6.406495e-08"

(最好进一步概括这一点并将代码中的6值替换为length(Z) ...)