最小化负对数可能性:由初始值引起的optim()错误

时间:2014-12-11 15:14:30

标签: r optimization mle

我希望通过直接最小化负对数似然(不使用glm)来获得适合某些比例数据的累积正态曲线的最大似然参数(MLE)。对于引入optim()的一些初始值,没有问题:

x <- c(-0.250, -0.056,  0.137,  0.331,  0.525,  0.719,  0.912,  1.100,  1.300)
k <- c(0, 0, 5, 11, 12, 12, 12, 12, 12)
n <- c(12, 12, 12, 12, 12, 12, 12, 12, 12)


nll <- function(p) {
  phi <- pnorm(x, p[1], p[2])
  -sum(k * log(phi) + (n - k) * log(1 - phi))
}

para<- optim(c(0.5, 0.1), nll)$par

xseq <- seq(-.5, 1.5, len = 100)
yseq <- pnorm(xseq, para[1],para[2])
curve <- data.frame(xseq, yseq)

dat <- data.frame(x, k, n)

library(ggplot2)
ggplot(dat,aes(x = x, y = k / n)) + 
  geom_point()+
  geom_line(data = curve, aes(x = xseq, y = yseq))

但是,如果我使用实际上更接近MLE参数的初始值

 para<- optim(c(0.1, 0.1), nll)$par

我收到了以下错误:

Error in optim(c(0.1, 0.1), nll) : function cannot be evaluated at initial parameters

似乎错误是由负对数可能性的评估中的一些无穷大引起的。我发现如果我使用pnorm的log.p选项增加精度,我就不会忽略错误

nll <- function(p) {
  logphi1 <- pnorm(x, p[1], p[2], lower.tail = T, log.p = T)
  logphi2 <- pnorm(x, p[1], p[2], lower.tail = F, log.p = T)
  -sum(k * logphi1 + (n - k) * logphi2)
}
para<- optim(c(0.1, 0.1), nll)$par

但问题是,除了pnorm之外,我还希望将a + b * pnorm的曲线与ab常量拟合,在这些情况下我无法使用{ {1}}以提高精确度。

2 个答案:

答案 0 :(得分:1)

似乎用机器epsilon替换非常小的数字并且数字非常接近1乘1 - (机器epsilon),错误不会发生并且拟合似乎合理。

x <- c(-0.250, -0.056,  0.137,  0.331,  0.525,  0.719,  0.912,  1.100,  1.300)
k <- c(0, 0, 5, 11, 12, 12, 12, 12, 12)
n <- c(12, 12, 12, 12, 12, 12, 12, 12, 12)

nll <- function(p) {
  phi <- pnorm(x, p[1], p[2])
  phi[phi < .Machine$double.eps] <- .Machine$double.eps
  phi[phi > (1 - .Machine$double.eps)] <- 1 - .Machine$double.eps
  -sum(k * log(phi) + (n - k) * log(1 - phi))
}

para<- optim(c(0.1, 0.1), nll)$par

xseq <- seq(-.5, 1.5, len = 100)
yseq <- pnorm(xseq, para[1],para[2])
curve <- data.frame(xseq, yseq)

dat <- data.frame(x, k, n)

library(ggplot2)
ggplot(dat,aes(x = x, y = k / n)) +
  geom_point()+
  geom_line(data = curve, aes(x = xseq, y = yseq))

答案 1 :(得分:0)

问题出在第8个数据点&amp;参数值;他们在评估可能性时会导致NaN,因为pnorm评估为1(数字):

p <- c(0.1,0.1)
pnorm(x[8], p[1], p[2])
## 1
1-pnorm(x[8], p[1], p[2])
## 0
pnorm(x[8], p[1], p[2], lower.tail=FALSE)
## 7.6e-24

后一个值位于machine-epsilon之下,所以即使你写出1 - pnorm(x[8], p[1], p[2], lower.tail=FALSE)的可能性,也不会避免下溢。