在 optim() 中计算表达式时出错
Error during evaluation of expression in optim()
我正在 R 中实现一个函数,用于查找最小化任意 pdf 函数(例如 pnorm、punif、pbinom 等)的二次误差的参数。该设计使得用户提供概率、经验分位数、函数名称 (densit
) 和来自 densit
函数的参数名称列表 (params
)(例如,mean
和 sd
在 pnorm
)。例如,q1
、q2
和 q3
等于 -1.644854、0 和 1.644854,以及 p1
、p2
和 p3
等于 0.05、0.5、0.95,函数应将 mean
和 sd
分别恢复为大约 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
似乎结果表达式被解释器按字面意思理解,即 mean
和 as
作为要计算的符号而不是要优化的函数中的参数。
提前感谢任何有助于解决此问题的提示。
你的函数 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
我正在 R 中实现一个函数,用于查找最小化任意 pdf 函数(例如 pnorm、punif、pbinom 等)的二次误差的参数。该设计使得用户提供概率、经验分位数、函数名称 (densit
) 和来自 densit
函数的参数名称列表 (params
)(例如,mean
和 sd
在 pnorm
)。例如,q1
、q2
和 q3
等于 -1.644854、0 和 1.644854,以及 p1
、p2
和 p3
等于 0.05、0.5、0.95,函数应将 mean
和 sd
分别恢复为大约 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
似乎结果表达式被解释器按字面意思理解,即 mean
和 as
作为要计算的符号而不是要优化的函数中的参数。
提前感谢任何有助于解决此问题的提示。
你的函数 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