我正在尝试通过R中的最大似然从二项分布估计参数 n 和 p 。
我正在使用stats包中的函数optim
,但是有错误。
那是我的代码:
xi = rbinom(100, 20, 0.5) # Sample
n = length(xi) # Sample size
# Log-Likelihood
lnlike <- function(theta){
log(prod(choose(theta[1],xi))) + sum(xi*log(theta[2])) +
(n*theta[1] - sum(xi))*log(1-theta[2])
}
# Optimizing
optim(theta <- c(10,.3), lnlike, hessian=TRUE)
optim中的错误(theta&lt; -c(10,0.3),lnlike,hessian = TRUE): 函数无法在初始参数下进行评估
有人这样做过吗?使用了哪个功能?
答案 0 :(得分:6)
tl; dr 如果响应变量大于二项式N(也就是二项式N),您将获得零的可能性(因而是负无限对数似然)理论最大响应值)。在大多数实际问题中,N被认为是已知的并且仅估计概率。如果你想估计N,你需要(1)将它约束为&gt; =样本中的最大值; (2)做一些特殊的事情来优化必须离散的参数(这是一个高级/棘手的问题)。
这个答案的第一部分显示了用于识别问题的调试策略,第二部分说明了同时优化N和p的策略(通过在合理的N范围内的暴力)。
设定:
set.seed(101)
n <- 100
xi <- rbinom(n, size=20, prob=0.5) # Sample
对数似然函数:
lnlike <- function(theta){
log(prod(choose(theta[1],xi))) + sum(xi*log(theta[2])) +
(n*theta[1] - sum(xi))*log(1-theta[2])
}
让我们打破这一点。
theta <- c(10,0.3) ## starting values
lnlike(c(10,0.3)) ## -Inf
好的,起始值的对数似然是-Inf
。 optim()
能够解决这个问题并不奇怪。
让我们完成这些条款。
log(prod(choose(theta[1],xi))) ## -Inf
好的,我们在第一个任期内已经遇到了麻烦。
prod(choose(theta[1],xi)) ## 0
产品为零......为什么?
choose(theta[1],xi)
## [1] 120 210 10 0 0 10 120 210 0 0 45 210 1 0
很多零。为什么? xi
有什么价值?
## [1] 7 6 9 12 11 9 7 6
啊哈!我们对7,6,9都很好......但是遇到了麻烦。
badvals <- (choose(theta[1],xi)==0)
all(badvals==(xi>10)) ## TRUE
如果你真的想这样做,可以通过合理的n
...
## likelihood function
llik2 <- function(p,n) {
-sum(dbinom(xi,prob=p,size=n,log=TRUE))
}
## possible N values (15 to 50)
nvec <- max(xi):50
Lvec <- numeric(length(nvec))
for (i in 1:length(nvec)) {
## optim() wants method="Brent"/lower/upper for 1-D optimization
Lvec[i] <- optim(par=0.5,fn=llik2,n=nvec[i],method="Brent",
lower=0.001,upper=0.999)$val
}
nvec[which.min(Lvec)] ## 20
par(las=1,bty="l")
plot(nvec,Lvec,type="b")
答案 1 :(得分:3)
为什么会遇到麻烦?
如果您执行lnlike(c(10, 0.3))
,则会获得-Inf
。这就是为什么您的错误消息抱怨lnlike
,而不是optim
。
通常,n
是已知的,只需要估算p
。在这种情况下,矩估计器或最大似然估计器都是闭合形式,并且不需要数值优化。所以,估计n
非常奇怪。
如果您确实想要估算,您必须意识到它受到限制。检查
range(xi) ## 5 15
您的观察范围为[5, 15]
,因此需要n >= 15
。你怎么能传递初始值10? n
的搜索方向应该是较大的起始值,然后逐渐向下搜索,直到达到max(xi)
。因此,您可以尝试30
n
的初始值。
此外,您无需以当前方式定义lnlike
。这样做:
lnlike <- function(theta, x) -sum(dbinom(x, size = theta[1], prob = theta[2], log = TRUE))
optim
通常用于最小化(尽管它可以实现最大化)。我在函数中加了一个减号以获得负对数似然。通过这种方式,您可以最小化lnlike
w.r.t. theta
。xi
作为lnlike
的附加参数传递,而不是从全球环境中获取。 天真尝试optim
:
在我的评论中,我已经说过,我不相信使用optim
估算n
会有效,因为n
必须是整数而optim
用于连续变量。这些错误和警告会说服你。
optim(c(30,.3), fn = lnlike, x = xi, hessian = TRUE)
Error in optim(c(30, 0.3), fn = lnlike, x = xi, hessian = TRUE) :
non-finite finite-difference value [1]
In addition: There were 15 or more warnings (use warnings() to see the
first 15
> warnings()
Warning messages:
1: In dbinom(x, size = theta[1], prob = theta[2], log = TRUE) : NaNs produced
2: In dbinom(x, size = theta[1], prob = theta[2], log = TRUE) : NaNs produced
3: In dbinom(x, size = theta[1], prob = theta[2], log = TRUE) : NaNs produced
4: In dbinom(x, size = theta[1], prob = theta[2], log = TRUE) : NaNs produced
5: In dbinom(x, size = theta[1], prob = theta[2], log = TRUE) : NaNs produced
<强>解决方案吗
Ben为你提供了一条路。我们手动对optim
进行网格搜索,而不是让n
估算n
。对于每个候选人n
,我们执行单变量优化w.r.t. p
。 (哎呀,实际上,这里不需要进行数值优化。)这样,您获得n
的概要可能性。然后,我们在网格上找到n
以最小化此配置文件的可能性。
Ben已经为您提供了详细信息,我将不再重复。很好(而且很快)的工作,本!