R 优化返回错误值

3

我的目标函数:

helper.post<-function(monthly.mean.return,
                  start.capital,  #initial nest egg
                  target.legacy,
                  monthly.inflation.post,
                  monthly.withdrawals,
                  n.obs){ 

  req = matrix(start.capital, n.obs+1, 1) #matrix for storing target weight

  for (a in 1:n.obs) {
    #cat("a: ",a,"\n")
    req[a + 1, ] = req[a, ] * (1 + monthly.mean.return - monthly.inflation.post) -     monthly.withdrawals[a,]
  }
  ending.value=req[nrow(req),]
  #ending.value
  value=target.legacy - ending.value

  return(abs(value))
}

在以下优化结构中,将n.obs从一个值更改为另一个值会产生相同的输出:
例如,如果n.obs = 288或n.obs = 336,则会得到相同的值。
optimize(f=helper.post,
     start.capital = 1000000,
     target.legacy = 1000000,
     monthly.inflation.post=0.002083333,
     monthly.withdrawals = matrix(rep(10000,n.obs)),
     n.obs = n.obs, 
     lower = 0,
     upper = 1,
     tol = 0.00000000000000000000000000000000001)$minimum

这个值看起来是一个估计值,而不是正确的值。有没有想法我可能做错了什么?对于如此精确的优化工作,是否有其他更好的优化工具可用?我尝试过uni-root,但它似乎不起作用,因为端点不是相反的符号。

uniroot( helper.post, 
     c(0, 1),
     start.capital = start.capital,
     target.legacy = target.legacy,
     monthly.inflation.post=monthly.inflation.post,
     monthly.withdrawals = monthly.withdrawals,
     n.obs = n.obs)$root
1个回答

6

让我们先稍微修改您的代码。我用向量替换了单列矩阵。我还添加了一个选项,可以返回错误本身或其绝对值。在尝试使用optim最小化误差时,您需要使用绝对值,而在尝试寻找其根时,您需要使用错误值本身与uniroot

helper.post <- function(monthly.mean.return,
                        start.capital,
                        target.legacy,
                        monthly.inflation.post,
                        monthly.withdrawals,
                        n.obs,
                        return.abs = TRUE) { 

  req <- numeric(n.obs + 1)
  req[1] <- start.capital

  for (month in 1:n.obs) {
    req[month + 1] <- req[month] *
                      (1 + monthly.mean.return - monthly.inflation.post) -
                      monthly.withdrawals[month]
  }
  ending.value <- req[n.obs + 1]
  error <- target.legacy - ending.value

  return(ifelse(return.abs, abs(error), error))
}

现在让我们对其进行优化:
n.obs <- 288

optimize(f = helper.post,
         start.capital = 1000000,
         target.legacy = 1000000,
         monthly.inflation.post = 0.002083333,
         monthly.withdrawals = matrix(rep(10000,n.obs)),
         n.obs = n.obs, 
         lower = 0,
         upper = 1,
         tol = 1e-20)$minimum
# [1] 0.01208333

现在我们来使用 uni.root 来检查解决方案:

uniroot(helper.post, 
        c(0, 1),
        start.capital = 1000000,
        target.legacy = 1000000,
        monthly.inflation.post = 0.002083333,
        monthly.withdrawals = matrix(rep(10000,n.obs)),
        n.obs = n.obs,
        return.abs = FALSE,
        tol = 1e-20)$root
# [1] 0.01208333

它们匹配。一个工具或另一个工具都没有问题...

如果您使用不同的n.obs值再次运行,您将获得完全相同的结果。为什么?因为您选择了恒定的提款和相同的起始和目标资本价值:您得到的输出是在每个月之间保持该余额恒定所需的利率,而与总月数无关。

实际上,这是您想要放入单元测试中的内容。因为这是一个预期且易于解释的结果。另一个容易想到的测试是,如果您在任何地方都使提款金额等于零,则期望您的答案与通货膨胀率相匹配。尝试一下,可以看到确实如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接