在 optim() 中计算表达式时出错

Error during evaluation of expression in optim()

我正在 R 中实现一个函数,用于查找最小化任意 pdf 函数(例如 pnorm、punif、pbinom 等)的二次误差的参数。该设计使得用户提供概率、经验分位数、函数名称 (densit) 和来自 densit 函数的参数名称列表 (params)(例如,meansdpnorm)。例如,q1q2q3 等于 -1.644854、0 和 1.644854,以及 p1p2p3 等于 0.05、0.5、0.95,函数应将 meansd 分别恢复为大约 0 和 1。

目标是将这样的表达式提供给 optim,以便后者采用一个函数(在内部调用 quadraticFun),该函数应在优化期间评估表达式;但是,我不能让 optim 对这种表达式进行估计。函数是这样的:

fun  <- function(p1 = 0.05, p2 = 0.50, p3 = 0.95, q1, q2, q3, output = "complete", densit, params) {
    densit <- substitute(densit)
    params <- sapply(params, as.name)
    densiCall1 <- as.call(c(as.list(densit), as.list(q1), params))
    densiCall2 <- as.call(c(as.list(densit), as.list(q2), params))
    densiCall3 <- as.call(c(as.list(densit), as.list(q3), params))
    quadratEq <- substitute((densiCall1 - p1)^2 +
                            (densiCall2 - p2)^2 +
                            (densiCall3 - p3)^2)
    quadraticFun <- function(params) {
        eval(quadratEq)
    }    
    initVals <- rep(1, times = length(params))
    res <- optim(initVals, quadraticFun) # ERROR SOMEWHERE AROUND HERE...
    # if output is set to "complete", return the whole res object, otherwise, return just the parameters 
    if (output == "parameters") {
        return(res$par)
    }
    return(res)
}

使用下一个示例进行调试表明错误在调用 optim(initVals, quadraticFun) 期间出现,特别是在评估 quadraticFun 期间出现以下消息:

> findParams(q1 = -1.644854, q2 = 0, q3 = 1.644854, densit = pnorm, params = list("mean", "sd"))
Error in pnorm(-1.644854, mean, sd) : 
  Non-numeric argument to mathematical function

似乎结果表达式被解释器按字面意思理解,即 meanas 作为要计算的符号而不是要优化的函数中的参数。

提前感谢任何有助于解决此问题的提示。

你的函数 quadraticFun 没有工作,因为它没有正确地将 params 参数传递给 densiCall1 函数。

我稍微修改了代码,只需要计算一个调用,这样更容易处理。现在 densit 是一个字符串,我相信你可以改变这个。 这是我想出的一个函数:

findParams <- function(q = c( -1.644854, 0, 1.644854), 
        p = c(0.05,  0.50, 0.95), output = "complete", densit="pnorm",
        params = c("mean", "sd")) {
    l <- length(params)
    cl <- vector("list", 2  + length(params))
    cl[[1]] <- as.name(densit)
    cl[[2]] <- q
    names(cl) <- c(NA, "q", params)
    mode(cl) <- "call"
    quadraticFun <- function(x) {
        cl[3:(l+2)] <- x
        res <- eval(cl)
        sum((res - p)^2)
    }    
    initVals <- rep(1, times = l)
    res <- optim(initVals, quadraticFun)
    if (output == "parameters") {
        return(res$par)
    }
    return(res)
}

它似乎有效:

findParams()
$par
[1] 0.0001065349 1.0001052494

$value
[1] 2.682477e-09

$counts
function gradient
      67       NA

$convergence
[1] 0

$message
NULL