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

时间:2017-11-09 18:09:41

标签: r optimization metaprogramming

我在R中实现一个函数,用于找到最小化任意pdf函数的二次误差的参数(例如,pnorm,punif,pbinom等)。设计使得用户从densit函数提供概率,经验分位数,函数名称(params)和参数名称列表(densit)(例如,{{在mean中1}}和sd。例如,pnormq1q2等于-1.644854,0和1.644854,q3p1和{{1等于0.05,0.5,0.95,该函数应该将p2p3分别恢复为大约0和1。

目标是将此类表达式提供给mean,以便后者采用一个函数(称为内部sd),该函数应在优化期间评估表达式;但是,我无法让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 作为符号来评估而不是优化函数中的参数。

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

1 个答案:

答案 0 :(得分:1)

您的功能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

似乎有效:

$(document).ready(function () {

    var source = $('#fetch-results').html();
    var dataTemplate = Handlebars.compile(source);
    var $results = $('#results');

    $('.fetch-btn').on('click', function (e) {

        let parameters = { site_url: 'http://feeds.feedburner.com/Techcrunch'};

        $.get('/update', parameters, function(data){
            if (data instanceof Array) {                
                $results.html(dataTemplate({articles: data}));
            } else {
                $results.html(data);
            }           
        });
    })
});